Merge "Add an opt-out property for camera compat freeform treatment." into main
diff --git a/apct-tests/perftests/core/src/android/os/TracePerfTest.java b/apct-tests/perftests/core/src/android/os/TracePerfTest.java
index bf7c96a..d905124 100644
--- a/apct-tests/perftests/core/src/android/os/TracePerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/TracePerfTest.java
@@ -127,14 +127,38 @@
public void testInstantPerfettoWithArgs() {
PerfettoTrace.instant(FOO_CATEGORY, "testInstantP")
.addArg("foo", "bar")
- .addFlow(1)
+ .setFlow(1)
.emit();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
PerfettoTrace.instant(FOO_CATEGORY, "testInstantP")
.addArg("foo", "bar")
- .addFlow(1)
+ .setFlow(1)
+ .emit();
+ }
+ }
+
+ @Test
+ public void testInstantPerfettoWithProto() {
+ PerfettoTrace.begin(FOO_CATEGORY, "message_queue_receive")
+ .beginProto()
+ .beginNested(2004 /* message_queue */)
+ .addField(1 /* sending_thread_name */, "foo")
+ .endNested()
+ .endProto()
+ .addTerminatingFlow(5)
+ .emit();
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ PerfettoTrace.begin(FOO_CATEGORY, "message_queue_receive")
+ .beginProto()
+ .beginNested(2004 /* message_queue */)
+ .addField(1 /* sending_thread_name */, "foo")
+ .endNested()
+ .endProto()
+ .addTerminatingFlow(5)
.emit();
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index ebfda52..010006e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -809,7 +809,11 @@
if (!verifyCallerLocked(cb)) {
return;
}
-
+ if (mVerb != VERB_EXECUTING) {
+ // Any state other than executing means the
+ // job is in transient or stopped state
+ return;
+ }
executing = getRunningJobLocked();
}
if (executing != null && jobId == executing.getJobId()) {
diff --git a/boot/boot-image-profile-extra.txt b/boot/boot-image-profile-extra.txt
index ced0d17..ce99bfe 100644
--- a/boot/boot-image-profile-extra.txt
+++ b/boot/boot-image-profile-extra.txt
@@ -45,11 +45,15 @@
HSPLandroid/os/MessageQueue$StackNodeType;->*
HSPLandroid/os/MessageQueue$StateNode;->*
HSPLandroid/os/MessageQueue$TimedParkStateNode;->*
+
+# For now, compile all methods in PerfettoTrace and PerfettoTrackEventExtra.
+# Similar to the existing Trace APIs, these new APIs can impact the performance
+# of many subsystems including MessageQueue. This also keeps benchmark
+# comparisons between both APIs fair.
HSPLandroid/os/PerfettoTrace$Category;->*
HSPLandroid/os/PerfettoTrace;->*
HSPLandroid/os/PerfettoTrackEventExtra;->*
-HSPLandroid/os/PerfettoTrackEventExtra$BuilderImpl;->*
-HSPLandroid/os/PerfettoTrackEventExtra$NoOpBuilder;->*
+HSPLandroid/os/PerfettoTrackEventExtra$Builder;->*
HSPLandroid/os/PerfettoTrackEventExtra$ArgBool;->*
HSPLandroid/os/PerfettoTrackEventExtra$ArgInt64;->*
HSPLandroid/os/PerfettoTrackEventExtra$ArgDouble;->*
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 1f15daf..335dc97 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -178,8 +178,8 @@
};
struct IdmapConstraint {
- // Constraint type can be TYPE_DISPLAY_ID or TYP_DEVICE_ID, please refer
- // to ConstraintType in OverlayConstraint.java
+ // Constraint type can be android::kOverlayConstraintTypeDisplayId or
+ // android::kOverlayConstraintTypeDeviceId
uint32_t constraint_type;
uint32_t constraint_value;
diff --git a/core/api/current.txt b/core/api/current.txt
index 5c0ecf72..4862236 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -18112,6 +18112,7 @@
method public void setThickness(@Px int);
method public void setThicknessRatio(@FloatRange(from=0.0f, fromInclusive=false) float);
method public void setUseLevel(boolean);
+ field @FlaggedApi("com.android.graphics.flags.gradient_drawable_shape_rounded_cap") public static final int ARC = 4; // 0x4
field public static final int LINE = 2; // 0x2
field public static final int LINEAR_GRADIENT = 0; // 0x0
field public static final int OVAL = 1; // 0x1
@@ -38342,7 +38343,7 @@
field @FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control") public static final String ACTION_REQUEST_MEDIA_ROUTING_CONTROL = "android.settings.REQUEST_MEDIA_ROUTING_CONTROL";
field public static final String ACTION_REQUEST_SCHEDULE_EXACT_ALARM = "android.settings.REQUEST_SCHEDULE_EXACT_ALARM";
field public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String ACTION_SATELLITE_SETTING = "android.settings.SATELLITE_SETTING";
+ field public static final String ACTION_SATELLITE_SETTING = "android.settings.SATELLITE_SETTING";
field public static final String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
field public static final String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";
@@ -44990,7 +44991,7 @@
field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT = "carrier_supported_satellite_notification_hysteresis_sec_int";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE = "carrier_supported_satellite_services_per_provider_bundle";
+ field public static final String KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE = "carrier_supported_satellite_services_per_provider_bundle";
field public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL = "carrier_supports_opp_data_auto_provisioning_bool";
field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
field public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL = "carrier_supports_tethering_bool";
@@ -45123,9 +45124,9 @@
field public static final String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
field public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
field public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY = "ntn_lte_rsrp_thresholds_int_array";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "ntn_lte_rsrq_thresholds_int_array";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "ntn_lte_rssnr_thresholds_int_array";
+ field public static final String KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY = "ntn_lte_rsrp_thresholds_int_array";
+ field public static final String KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "ntn_lte_rsrq_thresholds_int_array";
+ field public static final String KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "ntn_lte_rssnr_thresholds_int_array";
field public static final String KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
field public static final String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
field public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
@@ -45141,7 +45142,7 @@
field public static final String KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG = "opportunistic_network_max_backoff_time_long";
field public static final String KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG = "opportunistic_network_ping_pong_time_long";
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_OVERRIDE_WFC_ROAMING_MODE_WHILE_USING_NTN_BOOL = "override_wfc_roaming_mode_while_using_ntn_bool";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT = "parameters_used_for_ntn_lte_signal_bar_int";
+ field public static final String KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT = "parameters_used_for_ntn_lte_signal_bar_int";
field public static final String KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL = "ping_test_before_data_switch_bool";
field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
field @FlaggedApi("com.android.internal.telephony.flags.hide_prefer_3g_item") public static final String KEY_PREFER_3G_VISIBILITY_BOOL = "prefer_3g_visibility_bool";
@@ -45170,14 +45171,14 @@
field public static final String KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL = "rtt_supported_while_roaming_bool";
field public static final String KEY_RTT_UPGRADE_SUPPORTED_BOOL = "rtt_upgrade_supported_bool";
field public static final String KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL = "rtt_upgrade_supported_for_downgraded_vt_call";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ATTACH_SUPPORTED_BOOL = "satellite_attach_supported_bool";
+ field public static final String KEY_SATELLITE_ATTACH_SUPPORTED_BOOL = "satellite_attach_supported_bool";
field @FlaggedApi("com.android.internal.telephony.flags.satellite_25q4_apis") public static final String KEY_SATELLITE_CONNECTED_NOTIFICATION_THROTTLE_MILLIS_INT = "satellite_connected_notification_throttle_millis_int";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT = "satellite_connection_hysteresis_sec_int";
+ field public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT = "satellite_connection_hysteresis_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_DATA_SUPPORT_MODE_INT = "satellite_data_support_mode_int";
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_DISPLAY_NAME_STRING = "satellite_display_name_string";
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_ENTITLEMENT_APP_NAME_STRING = "satellite_entitlement_app_name_string";
- 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 public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT = "satellite_entitlement_status_refresh_days_int";
+ field 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.satellite_25q4_apis") public static final String KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL = "satellite_ignore_data_roaming_setting_bool";
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING = "satellite_information_redirect_url_string";
@@ -46484,7 +46485,7 @@
method public boolean isNetworkRegistered();
method public boolean isNetworkRoaming();
method public boolean isNetworkSearching();
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public boolean isNonTerrestrialNetwork();
+ method public boolean isNonTerrestrialNetwork();
method @Deprecated public boolean isRegistered();
method @Deprecated public boolean isRoaming();
method @Deprecated public boolean isSearching();
@@ -46500,7 +46501,7 @@
field public static final int NR_STATE_RESTRICTED = 1; // 0x1
field public static final int SERVICE_TYPE_DATA = 2; // 0x2
field public static final int SERVICE_TYPE_EMERGENCY = 5; // 0x5
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int SERVICE_TYPE_MMS = 6; // 0x6
+ field public static final int SERVICE_TYPE_MMS = 6; // 0x6
field public static final int SERVICE_TYPE_SMS = 3; // 0x3
field public static final int SERVICE_TYPE_UNKNOWN = 0; // 0x0
field public static final int SERVICE_TYPE_VIDEO = 4; // 0x4
@@ -46721,7 +46722,7 @@
method public boolean getRoaming();
method public int getState();
method public boolean isSearching();
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public boolean isUsingNonTerrestrialNetwork();
+ method public boolean isUsingNonTerrestrialNetwork();
method public void setIsManualSelection(boolean);
method public void setOperatorName(String, String, String);
method public void setRoaming(boolean);
@@ -47860,7 +47861,7 @@
field public static final int TYPE_MMS = 2; // 0x2
field @FlaggedApi("com.android.internal.telephony.flags.oem_paid_private") public static final int TYPE_OEM_PAID = 65536; // 0x10000
field @FlaggedApi("com.android.internal.telephony.flags.oem_paid_private") public static final int TYPE_OEM_PRIVATE = 131072; // 0x20000
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int TYPE_RCS = 32768; // 0x8000
+ field public static final int TYPE_RCS = 32768; // 0x8000
field public static final int TYPE_SUPL = 4; // 0x4
field public static final int TYPE_VSIM = 4096; // 0x1000
field public static final int TYPE_XCAP = 2048; // 0x800
@@ -53801,8 +53802,8 @@
method @FlaggedApi("com.android.graphics.hwui.flags.limited_hdr") public void setDesiredHdrHeadroom(@FloatRange(from=0.0f, to=10000.0) float);
method public void setSecure(boolean);
method public void setSurfaceLifecycle(int);
- method public void setZOrderMediaOverlay(boolean);
- method public void setZOrderOnTop(boolean);
+ method @Deprecated @FlaggedApi("android.view.flags.deprecate_surface_view_z_order_apis") public void setZOrderMediaOverlay(boolean);
+ method @Deprecated @FlaggedApi("android.view.flags.deprecate_surface_view_z_order_apis") public void setZOrderOnTop(boolean);
field public static final int SURFACE_LIFECYCLE_DEFAULT = 0; // 0x0
field public static final int SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT = 2; // 0x2
field public static final int SURFACE_LIFECYCLE_FOLLOWS_VISIBILITY = 1; // 0x1
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 40069aa..526a213 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -165,6 +165,16 @@
package android.media {
+ public class AudioDeviceVolumeManager {
+ method @FlaggedApi("android.media.audio.unify_absolute_volume_management") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.BLUETOOTH_STACK}) public void setDeviceAbsoluteMultiVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, @NonNull java.util.List<android.media.VolumeInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener);
+ method @FlaggedApi("android.media.audio.unify_absolute_volume_management") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.BLUETOOTH_STACK}) public void setDeviceAbsoluteVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, @NonNull android.media.VolumeInfo, @NonNull java.util.concurrent.Executor, @NonNull android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener);
+ }
+
+ @FlaggedApi("android.media.audio.unify_absolute_volume_management") public static interface AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener {
+ method public void onAudioDeviceVolumeAdjusted(@NonNull android.media.AudioDeviceAttributes, @NonNull android.media.VolumeInfo, int, int);
+ method public void onAudioDeviceVolumeChanged(@NonNull android.media.AudioDeviceAttributes, @NonNull android.media.VolumeInfo);
+ }
+
public class AudioManager {
method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0d5ec19..137c967 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4199,7 +4199,7 @@
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
method public void setRequestDowngrade(boolean);
- method @FlaggedApi("android.content.pm.recoverability_detection") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackImpactLevel(int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackImpactLevel(int);
method @FlaggedApi("android.content.pm.rollback_lifetime") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackLifetimeMillis(long);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
}
@@ -4374,9 +4374,9 @@
field public static final int ROLLBACK_DATA_POLICY_RESTORE = 0; // 0x0
field public static final int ROLLBACK_DATA_POLICY_RETAIN = 2; // 0x2
field public static final int ROLLBACK_DATA_POLICY_WIPE = 1; // 0x1
- field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_HIGH = 1; // 0x1
- field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_LOW = 0; // 0x0
- field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2; // 0x2
+ field public static final int ROLLBACK_USER_IMPACT_HIGH = 1; // 0x1
+ field public static final int ROLLBACK_USER_IMPACT_LOW = 0; // 0x0
+ field public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2; // 0x2
field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0; // 0x0
field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1; // 0x1
field public static final int SYSTEM_APP_STATE_INSTALLED = 2; // 0x2
@@ -15285,7 +15285,7 @@
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull public android.telephony.NetworkRegistrationInfo.Builder setIsNonTerrestrialNetwork(boolean);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setIsNonTerrestrialNetwork(boolean);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int);
method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
@@ -16422,7 +16422,7 @@
field public static final String TYPE_MMS_STRING = "mms";
field @FlaggedApi("com.android.internal.telephony.flags.oem_paid_private") public static final String TYPE_OEM_PAID_STRING = "oem_paid";
field @FlaggedApi("com.android.internal.telephony.flags.oem_paid_private") public static final String TYPE_OEM_PRIVATE_STRING = "oem_private";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String TYPE_RCS_STRING = "rcs";
+ field public static final String TYPE_RCS_STRING = "rcs";
field public static final String TYPE_SUPL_STRING = "supl";
field public static final String TYPE_VSIM_STRING = "vsim";
field public static final String TYPE_XCAP_STRING = "xcap";
@@ -18589,13 +18589,13 @@
}
@FlaggedApi("com.android.internal.telephony.flags.satellite_state_change_listener") public final class SatelliteManager {
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void addAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void addAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void deprovisionSatellite(@NonNull java.util.List<android.telephony.satellite.SatelliteSubscriberInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void deprovisionService(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.Set<java.lang.Integer> getAttachRestrictionReasonsForCarrier(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.Set<java.lang.Integer> getAttachRestrictionReasonsForCarrier(int);
method @FlaggedApi("com.android.internal.telephony.flags.satellite_25q4_apis") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.List<java.lang.String> getSatelliteDataOptimizedApps();
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int[] getSatelliteDisallowedReasons();
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.List<java.lang.String> getSatellitePlmnsForCarrier(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.List<java.lang.String> getSatellitePlmnsForCarrier(int);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void pollPendingDatagrams(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionSatellite(@NonNull java.util.List<android.telephony.satellite.SatelliteSubscriberInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionService(@NonNull String, @NonNull byte[], @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
@@ -18608,11 +18608,11 @@
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void registerForSatelliteDisallowedReasonsChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteDisallowedReasonsCallback);
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSelectedNbIotSatelliteSubscriptionChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback);
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSupportedStateChanged(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void removeAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestAttachEnabledForCarrier(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void removeAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestAttachEnabledForCarrier(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestCapabilities(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.satellite.SatelliteCapabilities,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestEnabled(@NonNull android.telephony.satellite.EnableRequestAttributes, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsAttachEnabledForCarrier(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
+ method @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsAttachEnabledForCarrier(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsCommunicationAllowedForCurrentLocation(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsDemoModeEnabled(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsEmergencyModeEnabled(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
@@ -18656,15 +18656,15 @@
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DISPLAY_MODE_OPENED = 2; // 0x2
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DISPLAY_MODE_UNKNOWN = 0; // 0x0
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS = 1; // 0x1
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2; // 0x2
+ field public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2; // 0x2
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 3; // 0x3
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 1; // 0x1
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2; // 0x2
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 4; // 0x4
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0; // 0x0
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT = "android.telephony.satellite.PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2; // 0x2
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1; // 0x1
+ field public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2; // 0x2
+ field public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1; // 0x1
field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0; // 0x0
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0; // 0x0
field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7; // 0x7
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 975c2c2..4222c7c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1737,6 +1737,7 @@
method @NonNull public int[] getUserDisabledHdrTypes();
method public boolean isMinimalPostProcessingRequested(int);
method @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public void overrideHdrTypes(int, @NonNull int[]);
+ method @FlaggedApi("com.android.server.display.feature.flags.delay_implicit_rr_registration_until_rr_accessed") public void resetImplicitRefreshRateCallbackStatus();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) public void setGlobalUserPreferredDisplayMode(@NonNull android.view.Display.Mode);
method @RequiresPermission(android.Manifest.permission.MODIFY_HDR_CONVERSION_MODE) public void setHdrConversionMode(@NonNull android.hardware.display.HdrConversionMode);
@@ -1915,6 +1916,10 @@
package android.hardware.usb {
+ public class UsbManager {
+ method public boolean isUvcGadgetSupportEnabled();
+ }
+
public final class UsbPort {
method @FlaggedApi("android.hardware.usb.flags.enable_is_mode_change_supported_api") @RequiresPermission(android.Manifest.permission.MANAGE_USB) public boolean isModeChangeSupported();
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 6151b8e..a12c067 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.annotation.PermissionMethod;
import android.annotation.PermissionName;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityManager.RestrictionLevel;
@@ -1365,8 +1366,8 @@
* watchdog reset.
* @hide
*/
- public abstract void killApplicationSync(String pkgName, int appId, int userId,
- String reason, int exitInfoReason);
+ public abstract void killApplicationSync(String pkgName, int appId,
+ @CanBeALL @UserIdInt int userId, String reason, int exitInfoReason);
/**
* Queries the offset data for a given method on a process.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 588ca1d..c765298 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -101,6 +101,7 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ProviderInfoList;
import android.content.pm.ServiceInfo;
+import android.content.pm.SystemFeaturesCache;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -1342,6 +1343,10 @@
ApplicationSharedMemory instance =
ApplicationSharedMemory.fromFileDescriptor(
applicationSharedMemoryFd, /* mutable= */ false);
+ if (android.content.pm.Flags.cacheSdkSystemFeatures()) {
+ SystemFeaturesCache.setInstance(
+ new SystemFeaturesCache(instance.readSystemFeaturesCache()));
+ }
instance.closeFileDescriptor();
ApplicationSharedMemory.setInstance(instance);
}
@@ -4771,6 +4776,7 @@
// frame.
final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.hide(startingWindowLeash);
+ startingWindowLeash.release();
view.syncTransferSurfaceOnDraw();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f2e7e85..1ed64f9 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -78,6 +78,7 @@
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SuspendDialogInfo;
+import android.content.pm.SystemFeaturesCache;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VersionedPackage;
import android.content.pm.dex.ArtManager;
@@ -803,16 +804,6 @@
@Override
public Boolean recompute(HasSystemFeatureQuery query) {
try {
- // As an optimization, check first to see if the feature was defined at
- // compile-time as either available or unavailable.
- // TODO(b/203143243): Consider hoisting this optimization out of the cache
- // after the trunk stable (build) flag has soaked and more features are
- // defined at compile-time.
- Boolean maybeHasSystemFeature =
- RoSystemFeatures.maybeHasFeature(query.name, query.version);
- if (maybeHasSystemFeature != null) {
- return maybeHasSystemFeature.booleanValue();
- }
return ActivityThread.currentActivityThread().getPackageManager().
hasSystemFeature(query.name, query.version);
} catch (RemoteException e) {
@@ -823,15 +814,28 @@
@Override
public boolean hasSystemFeature(String name, int version) {
+ // We check for system features in the following order:
+ // * Build time-defined system features (constant, very efficient)
+ // * SDK-defined system features (cached at process start, very efficient)
+ // * IPC-retrieved system features (lazily cached, requires per-feature IPC)
+ // TODO(b/375000483): Refactor all of this logic, including flag queries, into
+ // the SystemFeaturesCache class after initial rollout and validation.
+ Boolean maybeHasSystemFeature = RoSystemFeatures.maybeHasFeature(name, version);
+ if (maybeHasSystemFeature != null) {
+ return maybeHasSystemFeature;
+ }
+ if (com.android.internal.os.Flags.applicationSharedMemoryEnabled()
+ && android.content.pm.Flags.cacheSdkSystemFeatures()) {
+ maybeHasSystemFeature =
+ SystemFeaturesCache.getInstance().maybeHasFeature(name, version);
+ if (maybeHasSystemFeature != null) {
+ return maybeHasSystemFeature;
+ }
+ }
return mHasSystemFeatureCache.query(new HasSystemFeatureQuery(name, version));
}
/** @hide */
- public void disableHasSystemFeatureCache() {
- mHasSystemFeatureCache.disableLocal();
- }
-
- /** @hide */
public static void invalidateHasSystemFeatureCache() {
mHasSystemFeatureCache.invalidateCache();
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 0519695..1a6e9b0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2976,6 +2976,13 @@
if (display != null) {
updateDeviceIdIfChanged(display.getDisplayId());
}
+ updateResourceOverlayConstraints();
+ }
+
+ private void updateResourceOverlayConstraints() {
+ if (mResources != null) {
+ mResources.getAssets().setOverlayConstraints(getDisplayId(), getDeviceId());
+ }
}
@Override
@@ -2988,9 +2995,11 @@
}
}
- return new ContextImpl(this, mMainThread, mPackageInfo, mParams,
+ final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
mAttributionSource.getAttributionTag(), mAttributionSource.getNext(), mSplitName,
mToken, mUser, mFlags, mClassLoader, null, deviceId, true);
+ context.updateResourceOverlayConstraints();
+ return context;
}
@NonNull
@@ -3285,6 +3294,7 @@
mDeviceId = updatedDeviceId;
mAttributionSource = createAttributionSourceWithDeviceId(mAttributionSource, mDeviceId);
notifyOnDeviceChangedListeners(updatedDeviceId);
+ updateResourceOverlayConstraints();
}
}
@@ -3700,6 +3710,7 @@
mResourcesManager.setLocaleConfig(lc);
}
}
+ updateResourceOverlayConstraints();
}
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 4b1afa5..01b2953 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -146,6 +146,7 @@
int getFrontActivityScreenCompatMode();
void setFrontActivityScreenCompatMode(int mode);
void setFocusedTask(int taskId);
+ boolean setTaskIsPerceptible(int taskId, boolean isPerceptible);
boolean removeTask(int taskId);
void removeAllVisibleRecentTasks();
List<ActivityManager.RunningTaskInfo> getTasks(int maxNum, boolean filterOnlyVisibleRecents,
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index b611acf..eb9feb9 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -50,6 +50,7 @@
import android.os.UserManager;
import android.ravenwood.annotation.RavenwoodKeep;
import android.ravenwood.annotation.RavenwoodKeepPartialClass;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
import android.ravenwood.annotation.RavenwoodReplace;
import android.util.AndroidRuntimeException;
import android.util.Log;
@@ -460,6 +461,7 @@
*
* @param runner The code to run on the main thread.
*/
+ @RavenwoodReplace(blockedBy = ActivityThread.class)
public void runOnMainSync(Runnable runner) {
validateNotAppThread();
SyncRunnable sr = new SyncRunnable(runner);
@@ -467,6 +469,13 @@
sr.waitForComplete();
}
+ private void runOnMainSync$ravenwood(Runnable runner) {
+ validateNotAppThread();
+ SyncRunnable sr = new SyncRunnable(runner);
+ mInstrContext.getMainExecutor().execute(sr);
+ sr.waitForComplete();
+ }
+
boolean isSdkSandboxAllowedToStartActivities() {
return Process.isSdkSandbox()
&& mThread != null
@@ -2442,7 +2451,8 @@
}
}
- private final void validateNotAppThread() {
+ @RavenwoodKeep
+ private void validateNotAppThread() {
if (Looper.myLooper() == Looper.getMainLooper()) {
throw new RuntimeException(
"This method can not be called from the main application thread");
@@ -2586,6 +2596,7 @@
}
}
+ @RavenwoodKeepWholeClass
private static final class SyncRunnable implements Runnable {
private final Runnable mTarget;
private boolean mComplete;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5dca1c7..719e438 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -18,6 +18,7 @@
import static android.annotation.Dimension.DP;
import static android.app.Flags.evenlyDividedCallStyleActionLayout;
+import static android.app.Flags.notificationsRedesignTemplates;
import static android.app.admin.DevicePolicyResources.Drawables.Source.NOTIFICATION;
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
@@ -818,7 +819,8 @@
R.layout.notification_2025_template_expanded_base,
R.layout.notification_2025_template_heads_up_base,
R.layout.notification_2025_template_header,
- R.layout.notification_2025_template_conversation,
+ R.layout.notification_2025_template_collapsed_conversation,
+ R.layout.notification_2025_template_expanded_conversation,
R.layout.notification_2025_template_collapsed_call,
R.layout.notification_2025_template_expanded_call,
R.layout.notification_2025_template_collapsed_messaging,
@@ -5963,7 +5965,10 @@
|| resId == getCompactHeadsUpBaseLayoutResource()
|| resId == getMessagingCompactHeadsUpLayoutResource()
|| resId == getCollapsedMessagingLayoutResource()
- || resId == getCollapsedMediaLayoutResource());
+ || resId == getCollapsedMediaLayoutResource()
+ || resId == getCollapsedConversationLayoutResource()
+ || (notificationsRedesignTemplates()
+ && resId == getCollapsedCallLayoutResource()));
RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
resetStandardTemplate(contentView);
@@ -6001,8 +6006,7 @@
// Update margins to leave space for the top line (but not for headerless views like
// HUNS, which use a different layout that already accounts for that). Templates that
// have content that will be displayed under the small icon also use a different margin.
- if (Flags.notificationsRedesignTemplates()
- && !p.mHeaderless && !p.mSkipTopLineAlignment) {
+ if (Flags.notificationsRedesignTemplates() && !p.mHeaderless) {
int margin = getContentMarginTop(mContext,
R.dimen.notification_2025_content_margin_top);
contentView.setViewLayoutMargin(R.id.notification_main_column,
@@ -7673,12 +7677,18 @@
}
}
+ // Note: In the 2025 redesign, we use two separate layouts for the collapsed and expanded
+ // version of conversations. See below.
private int getConversationLayoutResource() {
- if (Flags.notificationsRedesignTemplates()) {
- return R.layout.notification_2025_template_conversation;
- } else {
- return R.layout.notification_template_material_conversation;
- }
+ return R.layout.notification_template_material_conversation;
+ }
+
+ private int getCollapsedConversationLayoutResource() {
+ return R.layout.notification_2025_template_collapsed_conversation;
+ }
+
+ private int getExpandedConversationLayoutResource() {
+ return R.layout.notification_2025_template_expanded_conversation;
}
private int getCollapsedCallLayoutResource() {
@@ -9462,7 +9472,7 @@
boolean hideRightIcons = viewType != StandardTemplateParams.VIEW_TYPE_NORMAL;
boolean isConversationLayout = mConversationType != CONVERSATION_TYPE_LEGACY;
boolean isImportantConversation = mConversationType == CONVERSATION_TYPE_IMPORTANT;
- boolean isHeaderless = !isConversationLayout && isCollapsed;
+ boolean isLegacyHeaderless = !isConversationLayout && isCollapsed;
//TODO (b/217799515): ensure mConversationTitle always returns the correct
// conversationTitle, probably set mConversationTitle = conversationTitle after this
@@ -9483,7 +9493,8 @@
} else {
isOneToOne = !isGroupConversation();
}
- if (isHeaderless && isOneToOne && TextUtils.isEmpty(conversationTitle)) {
+ if ((isLegacyHeaderless || notificationsRedesignTemplates())
+ && isOneToOne && TextUtils.isEmpty(conversationTitle)) {
conversationTitle = getOtherPersonName();
}
@@ -9493,22 +9504,24 @@
.viewType(viewType)
.highlightExpander(isConversationLayout)
.hideProgress(true)
- .title(isHeaderless ? conversationTitle : null)
.text(null)
.hideLeftIcon(isOneToOne)
- .hideRightIcon(hideRightIcons || isOneToOne)
- .headerTextSecondary(isHeaderless ? null : conversationTitle)
- .skipTopLineAlignment(true);
+ .hideRightIcon(hideRightIcons || isOneToOne);
+ if (notificationsRedesignTemplates()) {
+ p.title(conversationTitle)
+ .hideAppName(isCollapsed);
+ } else {
+ p.title(isLegacyHeaderless ? conversationTitle : null)
+ .headerTextSecondary(isLegacyHeaderless ? null : conversationTitle);
+ }
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
- isConversationLayout
- ? mBuilder.getConversationLayoutResource()
- : isCollapsed
- ? mBuilder.getCollapsedMessagingLayoutResource()
- : mBuilder.getExpandedMessagingLayoutResource(),
+ getMessagingLayoutResource(isConversationLayout, isCollapsed),
p,
bindResult);
- if (isConversationLayout) {
+ if (isConversationLayout && !notificationsRedesignTemplates()) {
+ // Redesign note: This view is replaced by the `title`, which is handled normally.
mBuilder.setTextViewColorPrimary(contentView, R.id.conversation_text, p);
+ // Redesign note: This special divider is no longer needed.
mBuilder.setTextViewColorSecondary(contentView, R.id.app_name_divider, p);
}
@@ -9538,7 +9551,18 @@
contentView.setBoolean(R.id.status_bar_latest_event_content,
"setIsImportantConversation", isImportantConversation);
}
- if (isHeaderless) {
+ if (notificationsRedesignTemplates() && !isCollapsed) {
+ // Align the title to the app/small icon in the expanded form. In other layouts,
+ // this margin is added directly to the notification_main_column parent, but for
+ // messages we don't want the margin to be applied to the actual messaging
+ // content since it can contain icons that are displayed below the app icon.
+ Resources res = mBuilder.mContext.getResources();
+ int marginStart = res.getDimensionPixelSize(
+ R.dimen.notification_2025_content_margin_start);
+ contentView.setViewLayoutMargin(R.id.title,
+ RemoteViews.MARGIN_START, marginStart, TypedValue.COMPLEX_UNIT_PX);
+ }
+ if (isLegacyHeaderless) {
// Collapsed legacy messaging style has a 1-line limit.
contentView.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
}
@@ -9549,6 +9573,33 @@
return contentView;
}
+ private int getMessagingLayoutResource(boolean isConversationLayout, boolean isCollapsed) {
+ if (notificationsRedesignTemplates()) {
+ // Note: We eventually would like to use the same layouts for both conversations and
+ // regular messaging notifications.
+ if (isConversationLayout) {
+ if (isCollapsed) {
+ return mBuilder.getCollapsedConversationLayoutResource();
+ } else {
+ return mBuilder.getExpandedConversationLayoutResource();
+ }
+ } else {
+ if (isCollapsed) {
+ return mBuilder.getCollapsedMessagingLayoutResource();
+ } else {
+ return mBuilder.getExpandedMessagingLayoutResource();
+ }
+ }
+
+ } else {
+ return isConversationLayout
+ ? mBuilder.getConversationLayoutResource()
+ : isCollapsed
+ ? mBuilder.getCollapsedMessagingLayoutResource()
+ : mBuilder.getExpandedMessagingLayoutResource();
+ }
+ }
+
private CharSequence getKey(Person person) {
return person == null ? null
: person.getKey() == null ? person.getName() : person.getKey();
@@ -10986,6 +11037,7 @@
private RemoteViews makeCallLayout(int viewType) {
final boolean isCollapsed = viewType == StandardTemplateParams.VIEW_TYPE_NORMAL;
+ final boolean isHeadsUp = viewType == StandardTemplateParams.VIEW_TYPE_HEADS_UP;
Bundle extras = mBuilder.mN.extras;
CharSequence title = mPerson != null ? mPerson.getName() : null;
CharSequence text = mBuilder.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
@@ -11001,22 +11053,31 @@
.hideLeftIcon(true)
.hideRightIcon(true)
.hideAppName(isCollapsed)
- .titleViewId(R.id.conversation_text)
.title(title)
- .text(text)
- .summaryText(mBuilder.processLegacyText(mVerificationText));
+ .text(text);
+ if (!notificationsRedesignTemplates()) {
+ // We're using the normal title in the redesign, not a special text.
+ p.titleViewId(R.id.conversation_text)
+ // The verification text is now part of the top line views, so this is no
+ // longer necessary.
+ .summaryText(mBuilder.processLegacyText(mVerificationText));
+ }
mBuilder.mActions = getActionsListWithSystemActions();
final RemoteViews contentView;
if (isCollapsed) {
contentView = mBuilder.applyStandardTemplate(
mBuilder.getCollapsedCallLayoutResource(), p, null /* result */);
+ } else if (notificationsRedesignTemplates() && isHeadsUp) {
+ contentView = mBuilder.applyStandardTemplateWithActions(
+ mBuilder.getCollapsedCallLayoutResource(), p, null /* result */);
} else {
contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getExpandedCallLayoutResource(), p, null /* result */);
}
// Bind some extra conversation-specific header fields.
- if (!p.mHideAppName) {
+ if (!notificationsRedesignTemplates() && !p.mHideAppName) {
+ // Redesign note: This special divider is no longer needed.
mBuilder.setTextViewColorSecondary(contentView, R.id.app_name_divider, p);
contentView.setViewVisibility(R.id.app_name_divider, View.VISIBLE);
}
@@ -14676,7 +14737,6 @@
Icon mPromotedPicture;
boolean mCallStyleActions;
boolean mAllowTextWithProgress;
- boolean mSkipTopLineAlignment;
int mTitleViewId;
int mTextViewId;
@Nullable CharSequence mTitle;
@@ -14702,7 +14762,6 @@
mPromotedPicture = null;
mCallStyleActions = false;
mAllowTextWithProgress = false;
- mSkipTopLineAlignment = false;
mTitleViewId = R.id.title;
mTextViewId = R.id.text;
mTitle = null;
@@ -14769,11 +14828,6 @@
return this;
}
- public StandardTemplateParams skipTopLineAlignment(boolean skipTopLineAlignment) {
- mSkipTopLineAlignment = skipTopLineAlignment;
- return this;
- }
-
final StandardTemplateParams hideSnoozeButton(boolean hideSnoozeButton) {
this.mHideSnoozeButton = hideSnoozeButton;
return this;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 08719fc..5359ba4 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -14200,6 +14200,9 @@
* <li>Manifest.permission.ACTIVITY_RECOGNITION</li>
* <li>Manifest.permission.BODY_SENSORS</li>
* </ul>
+ * On devices running {@link android.os.Build.VERSION_CODES#BAKLAVA}, the
+ * {@link android.health.connect.HealthPermissions} are also included in the
+ * restricted list.
* <p>
* A profile owner may not grant these permissions (i.e. call this method with any of the
* permissions listed above and {@code grantState} of {@code #PERMISSION_GRANT_STATE_GRANTED}),
@@ -17644,9 +17647,17 @@
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
})
public boolean isFinancedDevice() {
- return isDeviceManaged()
- && getDeviceOwnerType(getDeviceOwnerComponentOnAnyUser())
- == DEVICE_OWNER_TYPE_FINANCED;
+ try {
+ return isDeviceManaged()
+ && getDeviceOwnerType(getDeviceOwnerComponentOnAnyUser())
+ == DEVICE_OWNER_TYPE_FINANCED;
+ } catch (IllegalStateException e) {
+ // getDeviceOwnerType() will throw IllegalStateException if the device does not have a
+ // DO. This can happen under a race condition when the DO is removed after
+ // isDeviceManaged() (so it still returns true) but before getDeviceOwnerType().
+ // In this case, the device should not be considered a financed device.
+ return false;
+ }
}
// TODO(b/315298076): revert ag/25574027 and update the doc
diff --git a/core/java/android/app/contextualsearch/flags.aconfig b/core/java/android/app/contextualsearch/flags.aconfig
index bc1f7ce..1de034b 100644
--- a/core/java/android/app/contextualsearch/flags.aconfig
+++ b/core/java/android/app/contextualsearch/flags.aconfig
@@ -24,7 +24,7 @@
}
flag {
- name: "contextual_search_window_layer"
+ name: "contextual_search_prevent_self_capture"
namespace: "sysui_integrations"
description: "Identify live contextual search UI to exclude from contextual search screenshot."
bug: "390176823"
diff --git a/core/java/android/app/supervision/flags.aconfig b/core/java/android/app/supervision/flags.aconfig
index 94de038..7094183 100644
--- a/core/java/android/app/supervision/flags.aconfig
+++ b/core/java/android/app/supervision/flags.aconfig
@@ -72,3 +72,11 @@
description: "Flag that enables system APIs in Supervision Manager"
bug: "382034839"
}
+
+flag {
+ name: "enable_web_content_filters_screen"
+ is_exported: true
+ namespace: "supervision"
+ description: "Flag that enables the web content filters screen with Supervision settings entry point"
+ bug: "395134536"
+}
diff --git a/core/java/android/appwidget/OWNERS b/core/java/android/appwidget/OWNERS
index 0e85d5b..1dc4cbb 100644
--- a/core/java/android/appwidget/OWNERS
+++ b/core/java/android/appwidget/OWNERS
@@ -3,5 +3,4 @@
pinyaoting@google.com
suprabh@google.com
sunnygoyal@google.com
-zakcohen@google.com
shamalip@google.com
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index ba1473c..67ade79 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -135,3 +135,11 @@
description: "Show virtual devices in Settings"
bug: "338974320"
}
+
+flag {
+ name: "migrate_viewconfiguration_constants_to_resources"
+ namespace: "virtual_devices"
+ description: "Use resources instead of constants in ViewConfiguration"
+ is_fixed_read_only: true
+ bug: "370928384"
+}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index efcaa0e..a753cbf 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -23,6 +23,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SpecialUsers.CanBeALL;
+import android.annotation.SpecialUsers.CanBeCURRENT;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -2709,7 +2711,7 @@
public final void registerContentObserverAsUser(@NonNull Uri uri,
boolean notifyForDescendants,
@NonNull ContentObserver observer,
- @NonNull UserHandle userHandle) {
+ @NonNull @CanBeALL @CanBeCURRENT UserHandle userHandle) {
Objects.requireNonNull(uri, "uri");
Objects.requireNonNull(observer, "observer");
Objects.requireNonNull(userHandle, "userHandle");
@@ -2723,7 +2725,7 @@
/** @hide - designated user version */
@UnsupportedAppUsage
public final void registerContentObserver(Uri uri, boolean notifyForDescendants,
- ContentObserver observer, @UserIdInt int userHandle) {
+ ContentObserver observer, @CanBeALL @CanBeCURRENT @UserIdInt int userHandle) {
try {
getContentService().registerContentObserver(uri, notifyForDescendants,
observer.getContentObserver(), userHandle, mTargetSdkVersion);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index d64ef75..4bbbad4 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -3250,7 +3250,6 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
- @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION)
public void setRollbackImpactLevel(@PackageManager.RollbackImpactLevel int impactLevel) {
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
throw new IllegalArgumentException(
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 6ae2df2..9e91f59 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1619,7 +1619,6 @@
* @hide
*/
@SystemApi
- @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION)
public static final int ROLLBACK_USER_IMPACT_LOW = 0;
/**
@@ -1629,7 +1628,6 @@
* @hide
*/
@SystemApi
- @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION)
public static final int ROLLBACK_USER_IMPACT_HIGH = 1;
/**
@@ -1638,7 +1636,6 @@
* @hide
*/
@SystemApi
- @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION)
public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2;
/** @hide */
@@ -2041,7 +2038,7 @@
public static final int INSTALL_SCENARIO_DEFAULT = 0;
/**
- * Installation scenario providing the fastest “install button to launch" experience possible.
+ * Installation scenario providing the fastest "install button to launch" experience possible.
*/
public static final int INSTALL_SCENARIO_FAST = 1;
@@ -3588,7 +3585,7 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device is
- * compatible with Android’s security model.
+ * compatible with Android's security model.
*
* <p>See sections 2 and 9 in the
* <a href="https://source.android.com/compatibility/android-cdd">Android CDD</a> for more
diff --git a/core/java/android/content/pm/SystemFeaturesCache.java b/core/java/android/content/pm/SystemFeaturesCache.java
index c41a7ab..b3d70fa 100644
--- a/core/java/android/content/pm/SystemFeaturesCache.java
+++ b/core/java/android/content/pm/SystemFeaturesCache.java
@@ -16,9 +16,8 @@
package android.content.pm;
+import android.annotation.MainThread;
import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
@@ -35,16 +34,53 @@
*
* @hide
*/
-public final class SystemFeaturesCache implements Parcelable {
+public final class SystemFeaturesCache {
// Sentinel value used for SDK-declared features that are unavailable on the current device.
private static final int UNAVAILABLE_FEATURE_VERSION = Integer.MIN_VALUE;
+ // This will be initialized just once, from the process main thread, but ready from any thread.
+ private static volatile SystemFeaturesCache sInstance;
+
// An array of versions for SDK-defined features, from [0, PackageManager.SDK_FEATURE_COUNT).
@NonNull
private final int[] mSdkFeatureVersions;
/**
+ * Installs the process-global cache instance.
+ *
+ * <p>Note: Usage should be gated on android.content.pm.Flags.cacheSdkSystemFeature(). In
+ * practice, this should only be called from 1) SystemServer init, or 2) bindApplication.
+ */
+ @MainThread
+ public static void setInstance(SystemFeaturesCache instance) {
+ if (sInstance != null) {
+ throw new IllegalStateException("SystemFeaturesCache instance already initialized.");
+ }
+ sInstance = instance;
+ }
+
+ /**
+ * Gets the process-global cache instance.
+ *
+ * Note: Usage should be gated on android.content.pm.Flags.cacheSdkSystemFeature(), and should
+ * always occur after the instance has been installed early in the process lifecycle.
+ */
+ public static @NonNull SystemFeaturesCache getInstance() {
+ SystemFeaturesCache instance = sInstance;
+ if (instance == null) {
+ throw new IllegalStateException("SystemFeaturesCache not initialized");
+ }
+ return instance;
+ }
+
+ /** Clears the process-global cache instance for testing. */
+ @VisibleForTesting
+ public static void clearInstance() {
+ sInstance = null;
+ }
+
+ /**
* Populates the cache from the set of all available {@link FeatureInfo} definitions.
*
* System features declared in {@link PackageManager} will be entered into the cache based on
@@ -69,20 +105,28 @@
}
}
- /** Only used by @{code CREATOR.createFromParcel(...)} */
- private SystemFeaturesCache(@NonNull Parcel parcel) {
- final int[] featureVersions = parcel.createIntArray();
- if (featureVersions == null) {
- throw new IllegalArgumentException(
- "Parceled SDK feature versions should never be null");
- }
- if (featureVersions.length != PackageManager.SDK_FEATURE_COUNT) {
+ /**
+ * Populates the cache from an array of SDK feature versions originally obtained via {@link
+ * #getSdkFeatureVersions()} from another instance.
+ */
+ public SystemFeaturesCache(@NonNull int[] sdkFeatureVersions) {
+ if (sdkFeatureVersions.length != PackageManager.SDK_FEATURE_COUNT) {
throw new IllegalArgumentException(
String.format(
"Unexpected cached SDK feature count: %d (expected %d)",
- featureVersions.length, PackageManager.SDK_FEATURE_COUNT));
+ sdkFeatureVersions.length, PackageManager.SDK_FEATURE_COUNT));
}
- mSdkFeatureVersions = featureVersions;
+ mSdkFeatureVersions = sdkFeatureVersions;
+ }
+
+ /**
+ * Gets the raw cached feature versions.
+ *
+ * <p>Note: This should generally only be neded for (de)serialization purposes.
+ */
+ // TODO(b/375000483): Consider reusing the ApplicationSharedMemory mapping for version lookup.
+ public int[] getSdkFeatureVersions() {
+ return mSdkFeatureVersions;
}
/**
@@ -105,29 +149,4 @@
return mSdkFeatureVersions[sdkFeatureIndex] >= version;
}
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel parcel, int flags) {
- parcel.writeIntArray(mSdkFeatureVersions);
- }
-
- @NonNull
- public static final Parcelable.Creator<SystemFeaturesCache> CREATOR =
- new Parcelable.Creator<SystemFeaturesCache>() {
-
- @Override
- public SystemFeaturesCache createFromParcel(Parcel parcel) {
- return new SystemFeaturesCache(parcel);
- }
-
- @Override
- public SystemFeaturesCache[] newArray(int size) {
- return new SystemFeaturesCache[size];
- }
- };
}
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index e4b8c90..255a08c 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -391,3 +391,12 @@
bug: "319137634"
is_fixed_read_only: true
}
+
+flag {
+ name: "always_load_past_certs_v4"
+ is_exported: true
+ namespace: "package_manager_service"
+ description: "Always read the corresponding v3/3.1 signature block for the current v4 to get the past rotated certificates, even when not verifying integrity."
+ bug: "378539511"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 7cd2d31..bcb5088 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -148,8 +148,8 @@
* @hide
*/
public static class Builder {
- private ArrayList<ApkAssets> mUserApkAssets = new ArrayList<>();
- private ArrayList<ResourcesLoader> mLoaders = new ArrayList<>();
+ private final ArrayList<ApkAssets> mUserApkAssets = new ArrayList<>();
+ private final ArrayList<ResourcesLoader> mLoaders = new ArrayList<>();
private boolean mNoInit = false;
@@ -1625,6 +1625,23 @@
}
/**
+ * Passes the display id and device id to AssetManager, to filter out overlays based on
+ * any {@link android.content.om.OverlayConstraint}.
+ *
+ * @hide
+ */
+ public void setOverlayConstraints(int displayId, int deviceId) {
+ if (!Flags.rroConstraints()) {
+ return;
+ }
+
+ synchronized (this) {
+ ensureValidLocked();
+ nativeSetOverlayConstraints(mObject, displayId, deviceId);
+ }
+ }
+
+ /**
* @hide
*/
@UnsupportedAppUsage
@@ -1717,6 +1734,7 @@
int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp,
int screenHeightDp, int screenLayout, int uiMode, int colorMode, int grammaticalGender,
int majorVersion, boolean forceRefresh);
+ private static native void nativeSetOverlayConstraints(long ptr, int displayId, int deviceId);
private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
long ptr, boolean includeOverlays, boolean includeLoaders);
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index ef200c3..2e09994 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -2358,8 +2358,13 @@
* @param locales The locale list. If null, an empty LocaleList will be assigned.
*/
public void setLocales(@Nullable LocaleList locales) {
+ LocaleList oldList = mLocaleList;
mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales;
locale = mLocaleList.get(0);
+ if (!mLocaleList.equals(oldList)) {
+ Slog.v(TAG, "Updating configuration, locales updated from " + oldList
+ + " to " + mLocaleList);
+ }
setLayoutDirection(locale);
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 0559631..2658efa 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -482,7 +482,6 @@
*
* @return Typeface The Typeface data associated with the resource.
*/
- @RavenwoodThrow(blockedBy = Typeface.class)
@NonNull public Typeface getFont(@FontRes int id) throws NotFoundException {
final TypedValue value = obtainTempTypedValue();
try {
@@ -507,7 +506,6 @@
/**
* @hide
*/
- @RavenwoodThrow(blockedBy = Typeface.class)
public void preloadFonts(@ArrayRes int id) {
final TypedArray array = obtainTypedArray(id);
try {
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 96c7176..8c76fd7 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -491,6 +491,9 @@
}
defaultLocale =
adjustLanguageTag(lc.getDefaultLocale().toLanguageTag());
+ Slog.v(TAG, "Updating configuration, with default locale "
+ + defaultLocale + " and selected locales "
+ + Arrays.toString(selectedLocales));
} else {
String[] availableLocales;
// The LocaleList has changed. We must query the AssetManager's
@@ -526,6 +529,7 @@
for (int i = 0; i < locales.size(); i++) {
selectedLocales[i] = adjustLanguageTag(locales.get(i).toLanguageTag());
}
+ defaultLocale = adjustLanguageTag(lc.getDefaultLocale().toLanguageTag());
} else {
selectedLocales = new String[]{
adjustLanguageTag(locales.get(0).toLanguageTag())};
@@ -1064,7 +1068,6 @@
* Loads a font from XML or resources stream.
*/
@Nullable
- @RavenwoodThrow(blockedBy = Typeface.class)
public Typeface loadFont(Resources wrapper, TypedValue value, int id) {
if (value.string == null) {
throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 79185a1..ee7d008 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -1043,7 +1043,6 @@
* not a font resource.
*/
@Nullable
- @RavenwoodThrow(blockedBy = Typeface.class)
public Typeface getFont(@StyleableRes int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
diff --git a/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java b/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
index bfbcfd8..1bf01f4 100644
--- a/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
+++ b/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
@@ -68,6 +68,7 @@
* @hide
*/
@SystemApi
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class FontFamilyUpdateRequest {
/**
diff --git a/core/java/android/graphics/fonts/FontFileUpdateRequest.java b/core/java/android/graphics/fonts/FontFileUpdateRequest.java
index cf1dca9..1f2be6f 100644
--- a/core/java/android/graphics/fonts/FontFileUpdateRequest.java
+++ b/core/java/android/graphics/fonts/FontFileUpdateRequest.java
@@ -28,6 +28,7 @@
* @hide
*/
@SystemApi
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class FontFileUpdateRequest {
private final ParcelFileDescriptor mParcelFileDescriptor;
diff --git a/core/java/android/hardware/contexthub/HubEndpoint.java b/core/java/android/hardware/contexthub/HubEndpoint.java
index b7edef6..47ba51d 100644
--- a/core/java/android/hardware/contexthub/HubEndpoint.java
+++ b/core/java/android/hardware/contexthub/HubEndpoint.java
@@ -126,7 +126,16 @@
if (sessionExists) {
Log.w(
TAG,
- "onSessionOpenComplete: session already exists, id=" + sessionId);
+ "onSessionOpenRequest: session already exists, id=" + sessionId);
+ }
+
+ if (mLifecycleCallback == null) {
+ Log.w(
+ TAG,
+ "onSessionOpenRequest: "
+ + "failed to open session, no lifecycle callback attached",
+ new Exception());
+ rejectSession(sessionId);
}
if (!sessionExists && mLifecycleCallback != null) {
diff --git a/core/java/android/hardware/contexthub/HubEndpointSession.java b/core/java/android/hardware/contexthub/HubEndpointSession.java
index ca59be8..c5e2d7a 100644
--- a/core/java/android/hardware/contexthub/HubEndpointSession.java
+++ b/core/java/android/hardware/contexthub/HubEndpointSession.java
@@ -88,7 +88,6 @@
: ContextHubTransaction.TYPE_HUB_MESSAGE_DEFAULT);
if (!isResponseRequired) {
// If the message doesn't require acknowledgement, respond with success immediately
- // TODO(b/379162322): Improve handling of synchronous failures.
mHubEndpoint.sendMessage(this, message, null);
ret.setResponse(
new ContextHubTransaction.Response<>(
diff --git a/core/java/android/hardware/contexthub/IContextHubEndpoint.aidl b/core/java/android/hardware/contexthub/IContextHubEndpoint.aidl
index eb1255c..5e6bb2d 100644
--- a/core/java/android/hardware/contexthub/IContextHubEndpoint.aidl
+++ b/core/java/android/hardware/contexthub/IContextHubEndpoint.aidl
@@ -99,5 +99,5 @@
* Invoked when a callback from IContextHubEndpointCallback finishes.
*/
@EnforcePermission("ACCESS_CONTEXT_HUB")
- void onCallbackFinished();
+ oneway void onCallbackFinished();
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 7850e37..92a56fc 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -851,6 +851,12 @@
* Registers a display listener to receive notifications about when
* displays are added, removed or changed.
*
+ * Because of the high frequency at which the refresh rate can change, clients will be
+ * registered for refresh rate change callbacks only when they request for refresh rate
+ * data({@link Display#getRefreshRate()}. Or alternately, you can consider using
+ * {@link #registerDisplayListener(Executor, long, DisplayListener)} and explicitly subscribe to
+ * {@link #EVENT_TYPE_DISPLAY_REFRESH_RATE} event
+ *
* We encourage to use {@link #registerDisplayListener(Executor, long, DisplayListener)}
* instead to subscribe for explicit events of interest
*
@@ -863,8 +869,8 @@
public void registerDisplayListener(DisplayListener listener, Handler handler) {
registerDisplayListener(listener, handler, EVENT_TYPE_DISPLAY_ADDED
| EVENT_TYPE_DISPLAY_CHANGED
- | EVENT_TYPE_DISPLAY_REFRESH_RATE
- | EVENT_TYPE_DISPLAY_REMOVED);
+ | EVENT_TYPE_DISPLAY_REMOVED, 0,
+ ActivityThread.currentPackageName(), /* isEventFilterExplicit */ false);
}
/**
@@ -882,9 +888,8 @@
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
@Nullable Handler handler, @EventType long eventFilter) {
- mGlobal.registerDisplayListener(listener, handler,
- mGlobal.mapFiltersToInternalEventFlag(eventFilter, 0),
- ActivityThread.currentPackageName());
+ registerDisplayListener(listener, handler, eventFilter, 0,
+ ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true);
}
/**
@@ -901,9 +906,8 @@
@FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
public void registerDisplayListener(@NonNull Executor executor, @EventType long eventFilter,
@NonNull DisplayListener listener) {
- mGlobal.registerDisplayListener(listener, executor,
- mGlobal.mapFiltersToInternalEventFlag(eventFilter, 0),
- ActivityThread.currentPackageName());
+ registerDisplayListener(listener, executor, eventFilter, 0,
+ ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true);
}
/**
@@ -924,9 +928,39 @@
public void registerDisplayListener(@NonNull DisplayListener listener,
@Nullable Handler handler, @EventType long eventFilter,
@PrivateEventType long privateEventFilter) {
+ registerDisplayListener(listener, handler, eventFilter, privateEventFilter,
+ ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true);
+ }
+
+ /**
+ * Registers a display listener to receive notifications about given display event types.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ * @param eventFilter A bitmask of the event types for which this listener is subscribed.
+ * @param privateEventFilter A bitmask of the private event types for which this listener
+ * is subscribed.
+ * @param isEventFilterExplicit Indicates if the client explicitly supplied the display events
+ * to be subscribed to.
+ *
+ */
+ private void registerDisplayListener(@NonNull DisplayListener listener,
+ @Nullable Handler handler, @EventType long eventFilter,
+ @PrivateEventType long privateEventFilter, String packageName,
+ boolean isEventFilterExplicit) {
mGlobal.registerDisplayListener(listener, handler,
mGlobal.mapFiltersToInternalEventFlag(eventFilter, privateEventFilter),
- ActivityThread.currentPackageName());
+ packageName, /* isEventFilterExplicit */ isEventFilterExplicit);
+ }
+
+ private void registerDisplayListener(@NonNull DisplayListener listener,
+ Executor executor, @EventType long eventFilter,
+ @PrivateEventType long privateEventFilter, String packageName,
+ boolean isEventFilterExplicit) {
+ mGlobal.registerDisplayListener(listener, executor,
+ mGlobal.mapFiltersToInternalEventFlag(eventFilter, privateEventFilter),
+ packageName, /* isEventFilterExplicit */ isEventFilterExplicit);
}
/**
@@ -1146,6 +1180,28 @@
}
/**
+ * Resets the behavior that automatically registers clients for refresh rate change callbacks
+ * when they register via {@link #registerDisplayListener(DisplayListener, Handler)}
+ *
+ * <p>By default, clients are not registered for refresh rate change callbacks via
+ * {@link #registerDisplayListener(DisplayListener, Handler)}. However, calling
+ * {@link Display#getRefreshRate()} triggers automatic registration for existing and future
+ * {@link DisplayListener} instances. This method reverts this behavior, preventing new
+ * clients from being automatically registered for refresh rate change callbacks. Note that the
+ * existing ones will continue to stay registered
+ *
+ * <p>In essence, this method returns the system to its initial state, where explicit calls to
+ * {{@link Display#getRefreshRate()} are required to receive refresh rate change notifications.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_DELAY_IMPLICIT_RR_REGISTRATION_UNTIL_RR_ACCESSED)
+ @TestApi
+ public void resetImplicitRefreshRateCallbackStatus() {
+ mGlobal.resetImplicitRefreshRateCallbackStatus();
+ }
+
+ /**
* Overrides HDR modes for a display device.
*
* @hide
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index a7d610e..c4af871 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -187,6 +187,9 @@
private final Binder mToken = new Binder();
+ // Guarded by mLock
+ private boolean mShouldImplicitlyRegisterRrChanges = false;
+
@VisibleForTesting
public DisplayManagerGlobal(IDisplayManager dm) {
mDm = dm;
@@ -390,16 +393,36 @@
* the handler for the main thread.
* If that is still null, a runtime exception will be thrown.
* @param packageName of the calling package.
+ * @param isEventFilterExplicit Indicates if the client explicitly supplied the display events
+ * to be subscribed to.
+ */
+ public void registerDisplayListener(@NonNull DisplayListener listener,
+ @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask,
+ String packageName, boolean isEventFilterExplicit) {
+ Looper looper = getLooperForHandler(handler);
+ Handler springBoard = new Handler(looper);
+ registerDisplayListener(listener, new HandlerExecutor(springBoard), internalEventFlagsMask,
+ packageName, isEventFilterExplicit);
+ }
+
+ /**
+ * Register a listener for display-related changes.
+ *
+ * @param listener The listener that will be called when display changes occur.
+ * @param handler Handler for the thread that will be receiving the callbacks. May be null.
+ * If null, listener will use the handler for the current thread, and if still null,
+ * the handler for the main thread.
+ * If that is still null, a runtime exception will be thrown.
+ * @param internalEventFlagsMask Mask of events to be listened to.
+ * @param packageName of the calling package.
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
@Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask,
String packageName) {
- Looper looper = getLooperForHandler(handler);
- Handler springBoard = new Handler(looper);
- registerDisplayListener(listener, new HandlerExecutor(springBoard), internalEventFlagsMask,
- packageName);
+ registerDisplayListener(listener, handler, internalEventFlagsMask, packageName, true);
}
+
/**
* Register a listener for display-related changes.
*
@@ -407,10 +430,12 @@
* @param executor Executor for the thread that will be receiving the callbacks. Cannot be null.
* @param internalEventFlagsMask Mask of events to be listened to.
* @param packageName of the calling package.
+ * @param isEventFilterExplicit Indicates if the explicit events to be subscribed to
+ * were supplied or not
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
@NonNull Executor executor, @InternalEventFlag long internalEventFlagsMask,
- String packageName) {
+ String packageName, boolean isEventFilterExplicit) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
@@ -429,7 +454,7 @@
int index = findDisplayListenerLocked(listener);
if (index < 0) {
mDisplayListeners.add(new DisplayListenerDelegate(listener, executor,
- internalEventFlagsMask, packageName));
+ internalEventFlagsMask, packageName, isEventFilterExplicit));
registerCallbackIfNeededLocked();
} else {
mDisplayListeners.get(index).setEventsMask(internalEventFlagsMask);
@@ -439,6 +464,22 @@
}
}
+
+ /**
+ * Registers all the clients to INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE events if qualified
+ */
+ public void registerForRefreshRateChanges() {
+ if (!Flags.delayImplicitRrRegistrationUntilRrAccessed()) {
+ return;
+ }
+ synchronized (mLock) {
+ if (!mShouldImplicitlyRegisterRrChanges) {
+ mShouldImplicitlyRegisterRrChanges = true;
+ updateCallbackIfNeededLocked();
+ }
+ }
+ }
+
public void unregisterDisplayListener(DisplayListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
@@ -521,8 +562,14 @@
long mask = 0;
final int numListeners = mDisplayListeners.size();
for (int i = 0; i < numListeners; i++) {
- mask |= mDisplayListeners.get(i).mInternalEventFlagsMask;
+ DisplayListenerDelegate displayListenerDelegate = mDisplayListeners.get(i);
+ if (!Flags.delayImplicitRrRegistrationUntilRrAccessed()
+ || mShouldImplicitlyRegisterRrChanges) {
+ displayListenerDelegate.implicitlyRegisterForRRChanges();
+ }
+ mask |= displayListenerDelegate.mInternalEventFlagsMask;
}
+
if (mDispatchNativeCallbacks) {
mask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED
| INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
@@ -802,6 +849,18 @@
}
/**
+ * Resets the implicit registration of refresh rate change callbacks
+ *
+ */
+ public void resetImplicitRefreshRateCallbackStatus() {
+ if (Flags.delayImplicitRrRegistrationUntilRrAccessed()) {
+ synchronized (mLock) {
+ mShouldImplicitlyRegisterRrChanges = false;
+ }
+ }
+ }
+
+ /**
* Overrides HDR modes for a display device.
*
*/
@@ -1439,21 +1498,27 @@
}
}
- private static final class DisplayListenerDelegate {
+ @VisibleForTesting
+ static final class DisplayListenerDelegate {
public final DisplayListener mListener;
public volatile long mInternalEventFlagsMask;
+ // Indicates if the client explicitly supplied the display events to be subscribed to.
+ private final boolean mIsEventFilterExplicit;
+
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private final Executor mExecutor;
private AtomicLong mGenerationId = new AtomicLong(1);
private final String mPackageName;
DisplayListenerDelegate(DisplayListener listener, @NonNull Executor executor,
- @InternalEventFlag long internalEventFlag, String packageName) {
+ @InternalEventFlag long internalEventFlag, String packageName,
+ boolean isEventFilterExplicit) {
mExecutor = executor;
mListener = listener;
mInternalEventFlagsMask = internalEventFlag;
mPackageName = packageName;
+ mIsEventFilterExplicit = isEventFilterExplicit;
}
void sendDisplayEvent(int displayId, @DisplayEvent int event, @Nullable DisplayInfo info,
@@ -1470,6 +1535,11 @@
});
}
+ @VisibleForTesting
+ boolean isEventFilterExplicit() {
+ return mIsEventFilterExplicit;
+ }
+
void clearEvents() {
mGenerationId.incrementAndGet();
}
@@ -1478,6 +1548,17 @@
mInternalEventFlagsMask = newInternalEventFlagsMask;
}
+ private void implicitlyRegisterForRRChanges() {
+ // For backward compatibility, if the user didn't supply the explicit events while
+ // subscribing, register them to refresh rate change events if they subscribed to
+ // display changed events
+ if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED) != 0
+ && !mIsEventFilterExplicit) {
+ setEventsMask(mInternalEventFlagsMask
+ | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE);
+ }
+ }
+
private void handleDisplayEventInner(int displayId, @DisplayEvent int event,
@Nullable DisplayInfo info, boolean forceUpdate) {
if (extraLogging()) {
@@ -1677,6 +1758,9 @@
public void registerNativeChoreographerForRefreshRateCallbacks() {
synchronized (mLock) {
mDispatchNativeCallbacks = true;
+ if (Flags.delayImplicitRrRegistrationUntilRrAccessed()) {
+ mShouldImplicitlyRegisterRrChanges = true;
+ }
registerCallbackIfNeededLocked();
updateCallbackIfNeededLocked();
DisplayInfo display = getDisplayInfoLocked(Display.DEFAULT_DISPLAY);
@@ -1806,4 +1890,9 @@
return baseEventMask;
}
+
+ @VisibleForTesting
+ CopyOnWriteArrayList<DisplayListenerDelegate> getDisplayListeners() {
+ return mDisplayListeners;
+ }
}
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index bb5491d..7187034 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -153,5 +153,5 @@
// Called when a discovery callback is finished executing
@EnforcePermission("ACCESS_CONTEXT_HUB")
- void onDiscoveryCallbackFinished();
+ oneway void onDiscoveryCallbackFinished();
}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index c0e506b..21d3ef0 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -126,6 +126,9 @@
/* Returns true if the specified USB function is enabled. */
boolean isFunctionEnabled(String function);
+ /* Returns true if UVC gadget support is enabled. */
+ boolean isUvcGadgetSupportEnabled();
+
/* Sets the current USB function. */
@EnforcePermission("MANAGE_USB")
void setCurrentFunctions(long functions, int operationId);
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index d2e232a..a005e33 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -30,8 +30,10 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -1437,6 +1439,21 @@
}
/**
+ * Returns true if the specified UVC gadget function support is enabled.
+ * <p>
+ * @hide
+ */
+ @TestApi
+ @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
+ public boolean isUvcGadgetSupportEnabled() {
+ try {
+ return mService.isUvcGadgetSupportEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Sets the current USB functions when in device mode.
* <p>
* USB functions represent interfaces which are published to the host to access
@@ -1641,6 +1658,7 @@
}
}
+ // TODO: b/396680593 Deprecate to de-dup with isUvcGadgetSupportEnabled()
/**
* Returns whether UVC is advertised to be supported or not. SELinux
* enforces that this function returns {@code false} when called from a
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a528ba4..7b47efd4 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -990,6 +990,8 @@
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (android.view.inputmethod.Flags.refactorInsetsController()) {
+ // After the IME window was hidden, we can remove its surface
+ scheduleImeSurfaceRemoval();
// The hide request first finishes the animation and then proceeds to the server
// side, finally reaching here, marking this the end state.
ImeTracker.forLogging().onHidden(statsToken);
diff --git a/core/java/android/os/BundleMerger.java b/core/java/android/os/BundleMerger.java
index dc243a5..fd5a18c 100644
--- a/core/java/android/os/BundleMerger.java
+++ b/core/java/android/os/BundleMerger.java
@@ -119,11 +119,23 @@
public static final int STRATEGY_ARRAY_APPEND = 50;
/**
+ * Merge strategy that combines two conflicting array values by creating a new array
+ * containing all unique elements from both arrays.
+ */
+ public static final int STRATEGY_ARRAY_UNION = 55;
+
+ /**
* Merge strategy that combines two conflicting {@link ArrayList} values by
* appending the last {@link ArrayList} after the first {@link ArrayList}.
*/
public static final int STRATEGY_ARRAY_LIST_APPEND = 60;
+ /**
+ * Merge strategy that combines two conflicting {@link String} values by
+ * appending the last {@link String} after the first {@link String}.
+ */
+ public static final int STRATEGY_STRING_APPEND = 70;
+
@IntDef(flag = false, prefix = { "STRATEGY_" }, value = {
STRATEGY_REJECT,
STRATEGY_FIRST,
@@ -136,7 +148,9 @@
STRATEGY_BOOLEAN_AND,
STRATEGY_BOOLEAN_OR,
STRATEGY_ARRAY_APPEND,
+ STRATEGY_ARRAY_UNION,
STRATEGY_ARRAY_LIST_APPEND,
+ STRATEGY_STRING_APPEND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Strategy {}
@@ -298,8 +312,12 @@
return booleanOr(first, last);
case STRATEGY_ARRAY_APPEND:
return arrayAppend(first, last);
+ case STRATEGY_ARRAY_UNION:
+ return arrayUnion(first, last);
case STRATEGY_ARRAY_LIST_APPEND:
return arrayListAppend(first, last);
+ case STRATEGY_STRING_APPEND:
+ return stringAppend(first, last);
default:
throw new UnsupportedOperationException();
}
@@ -361,6 +379,29 @@
return res;
}
+ private static @NonNull Object arrayUnion(@NonNull Object first, @NonNull Object last) {
+ if (!first.getClass().isArray()) {
+ throw new IllegalArgumentException("Unable to union " + first.getClass());
+ }
+ final int firstLength = Array.getLength(first);
+ final int lastLength = Array.getLength(last);
+ final ArrayList<Object> list = new ArrayList<>(firstLength + lastLength);
+ final ArraySet<Object> set = new ArraySet<>();
+ for (int i = 0; i < firstLength; i++) {
+ set.add(Array.get(first, i));
+ }
+ for (int i = 0; i < lastLength; i++) {
+ set.add(Array.get(last, i));
+ }
+ final Class<?> clazz = first.getClass().getComponentType();
+ final int setSize = set.size();
+ final Object res = Array.newInstance(clazz, setSize);
+ for (int i = 0; i < setSize; i++) {
+ Array.set(res, i, set.valueAt(i));
+ }
+ return res;
+ }
+
@SuppressWarnings("unchecked")
private static @NonNull Object arrayListAppend(@NonNull Object first, @NonNull Object last) {
if (!(first instanceof ArrayList)) {
@@ -374,6 +415,13 @@
return res;
}
+ private static @NonNull Object stringAppend(@NonNull Object first, @NonNull Object last) {
+ if (!(first instanceof String)) {
+ throw new IllegalArgumentException("Unable to append " + first.getClass());
+ }
+ return ((String) first) + ((String) last);
+ }
+
public static final @android.annotation.NonNull Parcelable.Creator<BundleMerger> CREATOR =
new Parcelable.Creator<BundleMerger>() {
@Override
diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
index 349a2f0..3c03bb5 100644
--- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
@@ -178,11 +178,6 @@
// We can lift these restrictions in the future after we've made it possible for test
// authors to test Looper and MessageQueue without resorting to reflection.
-
- // Holdback study.
- if (sIsProcessAllowedToUseConcurrent && Flags.messageQueueForceLegacy()) {
- sIsProcessAllowedToUseConcurrent = false;
- }
}
@RavenwoodReplace
@@ -238,9 +233,13 @@
traceMessageCount();
PerfettoTrace.instant(PerfettoTrace.MQ_CATEGORY, "message_queue_send")
.addFlow(msg.mEventId.get())
- .addArg("receiving_thread", mThread.getName())
- .addArg("delay", when - SystemClock.uptimeMillis())
- .addArg("what", msg.what)
+ .beginProto()
+ .beginNested(2004 /* message_queue */)
+ .addField(2 /* receiving_thread_name */, mThread.getName())
+ .addField(3 /* message_code */, msg.what)
+ .addField(4 /* message_delay_ms */, when - SystemClock.uptimeMillis())
+ .endNested()
+ .endProto()
.emit();
}
diff --git a/core/java/android/os/LockedMessageQueue/MessageQueue.java b/core/java/android/os/LockedMessageQueue/MessageQueue.java
deleted file mode 100644
index 2401f3d..0000000
--- a/core/java/android/os/LockedMessageQueue/MessageQueue.java
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * 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.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodRedirect;
-import android.ravenwood.annotation.RavenwoodRedirectionClass;
-import android.util.Log;
-import android.util.Printer;
-import android.util.SparseArray;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.GuardedBy;
-
-import dalvik.annotation.optimization.NeverCompile;
-
-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()}.
- */
-@RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_ravenwood")
-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()
- */
- @NeverCompile
- 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;
-
- @RavenwoodRedirect
- private native static long nativeInit();
- @RavenwoodRedirect
- private native static void nativeDestroy(long ptr);
- @UnsupportedAppUsage
- @RavenwoodRedirect
- private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
- @RavenwoodRedirect
- private native static void nativeWake(long ptr);
- @RavenwoodRedirect
- private native static boolean nativeIsPolling(long ptr);
- @RavenwoodRedirect
- 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);
- }
-
- @NeverCompile
- 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;
- }
-
- @NeverCompile
- void dumpPriorityQueue(ProtoOutputStream proto, MessageHeap priorityQueue) {
- for (int i = 0; i < priorityQueue.numElements(); i++) {
- Message m = priorityQueue.getMessageAt(i);
- m.dumpDebug(proto, MessageQueueProto.MESSAGES);
- }
- }
-
- @NeverCompile
- 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 + ")");
- }
- }
-
- @NeverCompile
- 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/Looper.java b/core/java/android/os/Looper.java
index d16e447..1329b90 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -200,7 +200,11 @@
}
PerfettoTrace.begin(PerfettoTrace.MQ_CATEGORY, "message_queue_receive")
- .addArg("sending_thread", msg.mSendingThreadName)
+ .beginProto()
+ .beginNested(2004 /* message_queue */)
+ .addField(1 /* sending_thread_name */, msg.mSendingThreadName)
+ .endNested()
+ .endProto()
.addTerminatingFlow(msg.mEventId.get())
.emit();
diff --git a/core/java/android/os/PerfettoTrace.java b/core/java/android/os/PerfettoTrace.java
index 741d542..932836f 100644
--- a/core/java/android/os/PerfettoTrace.java
+++ b/core/java/android/os/PerfettoTrace.java
@@ -232,10 +232,6 @@
* @param eventName The event name to appear in the trace.
*/
public static PerfettoTrackEventExtra.Builder instant(Category category, String eventName) {
- if (!category.isEnabled()) {
- return PerfettoTrackEventExtra.noOpBuilder();
- }
-
return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_INSTANT, category)
.setEventName(eventName);
}
@@ -247,10 +243,6 @@
* @param eventName The event name to appear in the trace.
*/
public static PerfettoTrackEventExtra.Builder begin(Category category, String eventName) {
- if (!category.isEnabled()) {
- return PerfettoTrackEventExtra.noOpBuilder();
- }
-
return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_SLICE_BEGIN, category)
.setEventName(eventName);
}
@@ -261,10 +253,6 @@
* @param category The perfetto category.
*/
public static PerfettoTrackEventExtra.Builder end(Category category) {
- if (!category.isEnabled()) {
- return PerfettoTrackEventExtra.noOpBuilder();
- }
-
return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_SLICE_END, category);
}
@@ -275,10 +263,6 @@
* @param value The value of the counter.
*/
public static PerfettoTrackEventExtra.Builder counter(Category category, long value) {
- if (!category.isEnabled()) {
- return PerfettoTrackEventExtra.noOpBuilder();
- }
-
return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_COUNTER, category)
.setCounter(value);
}
@@ -302,10 +286,6 @@
* @param value The value of the counter.
*/
public static PerfettoTrackEventExtra.Builder counter(Category category, double value) {
- if (!category.isEnabled()) {
- return PerfettoTrackEventExtra.noOpBuilder();
- }
-
return PerfettoTrackEventExtra.builder().init(PERFETTO_TE_TYPE_COUNTER, category)
.setCounter(value);
}
diff --git a/core/java/android/os/PerfettoTrackEventExtra.java b/core/java/android/os/PerfettoTrackEventExtra.java
index adb98aa..f4b5dfe 100644
--- a/core/java/android/os/PerfettoTrackEventExtra.java
+++ b/core/java/android/os/PerfettoTrackEventExtra.java
@@ -23,6 +23,8 @@
import libcore.util.NativeAllocationRegistry;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
@@ -33,8 +35,8 @@
*/
@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class PerfettoTrackEventExtra {
+ private static final boolean DEBUG = false;
private static final int DEFAULT_EXTRA_CACHE_SIZE = 5;
- private static final Builder NO_OP_BUILDER = new NoOpBuilder();
private static final ThreadLocal<PerfettoTrackEventExtra> sTrackEventExtra =
new ThreadLocal<PerfettoTrackEventExtra>() {
@Override
@@ -44,15 +46,18 @@
};
private static final AtomicLong sNamedTrackId = new AtomicLong();
private static final Supplier<Flow> sFlowSupplier = Flow::new;
- private static final Supplier<BuilderImpl> sBuilderSupplier = BuilderImpl::new;
+ private static final Supplier<Builder> sBuilderSupplier = Builder::new;
private static final Supplier<FieldInt64> sFieldInt64Supplier = FieldInt64::new;
private static final Supplier<FieldDouble> sFieldDoubleSupplier = FieldDouble::new;
private static final Supplier<FieldString> sFieldStringSupplier = FieldString::new;
private static final Supplier<FieldNested> sFieldNestedSupplier = FieldNested::new;
+ private final List<PerfettoPointer> mPendingPointers = new ArrayList<>();
private CounterInt64 mCounterInt64;
private CounterDouble mCounterDouble;
private Proto mProto;
+ private Flow mFlow;
+ private Flow mTerminatingFlow;
/**
* Represents a native pointer to a Perfetto C SDK struct. E.g. PerfettoTeHlExtra.
@@ -132,245 +137,10 @@
}
}
- public interface Builder {
- /**
- * Emits the track event.
- */
- void emit();
-
- /**
- * Initialize the builder for a new trace event.
- */
- Builder init(int traceType, PerfettoTrace.Category category);
-
- /**
- * Sets the event name for the track event.
- */
- Builder setEventName(String eventName);
-
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
- Builder addArg(String name, long val);
-
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
- Builder addArg(String name, boolean val);
-
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
- Builder addArg(String name, double val);
-
- /**
- * Adds a debug arg with key {@code name} and value {@code val}.
- */
- Builder addArg(String name, String val);
-
- /**
- * Adds a flow with {@code id}.
- */
- Builder addFlow(int id);
-
- /**
- * Adds a terminating flow with {@code id}.
- */
- Builder addTerminatingFlow(int id);
-
- /**
- * Adds the events to a named track instead of the thread track where the
- * event occurred.
- */
- Builder usingNamedTrack(long parentUuid, String name);
-
- /**
- * Adds the events to a process scoped named track instead of the thread track where the
- * event occurred.
- */
- Builder usingProcessNamedTrack(String name);
-
- /**
- * Adds the events to a thread scoped named track instead of the thread track where the
- * event occurred.
- */
- Builder usingThreadNamedTrack(long tid, String name);
-
- /**
- * Adds the events to a counter track instead. This is required for
- * setting counter values.
- */
- Builder usingCounterTrack(long parentUuid, String name);
-
- /**
- * Adds the events to a process scoped counter track instead. This is required for
- * setting counter values.
- */
- Builder usingProcessCounterTrack(String name);
-
- /**
- * Adds the events to a thread scoped counter track instead. This is required for
- * setting counter values.
- */
- Builder usingThreadCounterTrack(long tid, String name);
-
- /**
- * Sets a long counter value on the event.
- *
- */
- Builder setCounter(long val);
-
- /**
- * Sets a double counter value on the event.
- *
- */
- Builder setCounter(double val);
-
- /**
- * Adds a proto field with field id {@code id} and value {@code val}.
- */
- Builder addField(long id, long val);
-
- /**
- * Adds a proto field with field id {@code id} and value {@code val}.
- */
- Builder addField(long id, double val);
-
- /**
- * Adds a proto field with field id {@code id} and value {@code val}.
- */
- Builder addField(long id, String val);
-
- /**
- * Begins a proto field with field
- * Fields can be added from this point and there must be a corresponding
- * {@link endProto}.
- *
- * The proto field is a singleton and all proto fields get added inside the
- * one {@link beginProto} and {@link endProto} within the {@link Builder}.
- */
- Builder beginProto();
-
- /**
- * Ends a proto field.
- */
- Builder endProto();
-
- /**
- * Begins a nested proto field with field id {@code id}.
- * Fields can be added from this point and there must be a corresponding
- * {@link endNested}.
- */
- Builder beginNested(long id);
-
- /**
- * Ends a nested proto field.
- */
- Builder endNested();
- }
-
- @android.ravenwood.annotation.RavenwoodKeepWholeClass
- public static final class NoOpBuilder implements Builder {
- @Override
- public void emit() {}
- @Override
- public Builder init(int traceType, PerfettoTrace.Category category) {
- return this;
- }
- @Override
- public Builder setEventName(String eventName) {
- return this;
- }
- @Override
- public Builder addArg(String name, long val) {
- return this;
- }
- @Override
- public Builder addArg(String name, boolean val) {
- return this;
- }
- @Override
- public Builder addArg(String name, double val) {
- return this;
- }
- @Override
- public Builder addArg(String name, String val) {
- return this;
- }
- @Override
- public Builder addFlow(int id) {
- return this;
- }
- @Override
- public Builder addTerminatingFlow(int id) {
- return this;
- }
- @Override
- public Builder usingNamedTrack(long parentUuid, String name) {
- return this;
- }
- @Override
- public Builder usingProcessNamedTrack(String name) {
- return this;
- }
- @Override
- public Builder usingThreadNamedTrack(long tid, String name) {
- return this;
- }
- @Override
- public Builder usingCounterTrack(long parentUuid, String name) {
- return this;
- }
- @Override
- public Builder usingProcessCounterTrack(String name) {
- return this;
- }
- @Override
- public Builder usingThreadCounterTrack(long tid, String name) {
- return this;
- }
- @Override
- public Builder setCounter(long val) {
- return this;
- }
- @Override
- public Builder setCounter(double val) {
- return this;
- }
- @Override
- public Builder addField(long id, long val) {
- return this;
- }
- @Override
- public Builder addField(long id, double val) {
- return this;
- }
- @Override
- public Builder addField(long id, String val) {
- return this;
- }
- @Override
- public Builder beginProto() {
- return this;
- }
- @Override
- public Builder endProto() {
- return this;
- }
- @Override
- public Builder beginNested(long id) {
- return this;
- }
- @Override
- public Builder endNested() {
- return this;
- }
- }
-
/**
* Builder for Perfetto track event extras.
*/
- public static final class BuilderImpl implements Builder {
+ public static final class Builder {
// For performance reasons, we hold a reference to mExtra as a holder for
// perfetto pointers being added. This way, we avoid an additional list to hold
// the pointers in Java and we can pass them down directly to native code.
@@ -383,10 +153,13 @@
private Builder mParent;
private FieldContainer mCurrentContainer;
+ private boolean mIsCategoryEnabled;
private final CounterInt64 mCounterInt64;
private final CounterDouble mCounterDouble;
private final Proto mProto;
+ private final Flow mFlow;
+ private final Flow mTerminatingFlow;
private final RingBuffer<NamedTrack> mNamedTrackCache;
private final RingBuffer<CounterTrack> mCounterTrackCache;
@@ -400,9 +173,9 @@
private final Pool<FieldString> mFieldStringCache;
private final Pool<FieldNested> mFieldNestedCache;
private final Pool<Flow> mFlowCache;
- private final Pool<BuilderImpl> mBuilderCache;
+ private final Pool<Builder> mBuilderCache;
- private BuilderImpl() {
+ private Builder() {
mExtra = sTrackEventExtra.get();
mNamedTrackCache = mExtra.mNamedTrackCache;
mCounterTrackCache = mExtra.mCounterTrackCache;
@@ -420,20 +193,32 @@
mCounterInt64 = mExtra.getCounterInt64();
mCounterDouble = mExtra.getCounterDouble();
mProto = mExtra.getProto();
+ mFlow = mExtra.getFlow();
+ mTerminatingFlow = mExtra.getTerminatingFlow();
}
- @Override
+ /**
+ * Emits the track event.
+ */
public void emit() {
- checkParent();
- mIsBuilt = true;
+ if (!mIsCategoryEnabled) {
+ return;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
+ mIsBuilt = true;
native_emit(mTraceType, mCategory.getPtr(), mEventName, mExtra.getPtr());
- // Reset after emitting to free any the extras used to trace the event.
- mExtra.reset();
}
- @Override
+ /**
+ * Initialize the builder for a new trace event.
+ */
public Builder init(int traceType, PerfettoTrace.Category category) {
+ if (!category.isEnabled()) {
+ return this;
+ }
mTraceType = traceType;
mCategory = category;
mEventName = "";
@@ -446,18 +231,27 @@
mExtra.reset();
// Reset after on init in case the thread created builders without calling emit
- return initInternal(this, null);
+ return initInternal(this, null, true);
}
- @Override
+ /**
+ * Sets the event name for the track event.
+ */
public Builder setEventName(String eventName) {
mEventName = eventName;
return this;
}
- @Override
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ */
public Builder addArg(String name, long val) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
ArgInt64 arg = mArgInt64Cache.get(name.hashCode());
if (arg == null || !arg.getName().equals(name)) {
arg = new ArgInt64(name);
@@ -468,9 +262,16 @@
return this;
}
- @Override
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ */
public Builder addArg(String name, boolean val) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
ArgBool arg = mArgBoolCache.get(name.hashCode());
if (arg == null || !arg.getName().equals(name)) {
arg = new ArgBool(name);
@@ -481,9 +282,16 @@
return this;
}
- @Override
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ */
public Builder addArg(String name, double val) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
ArgDouble arg = mArgDoubleCache.get(name.hashCode());
if (arg == null || !arg.getName().equals(name)) {
arg = new ArgDouble(name);
@@ -494,9 +302,16 @@
return this;
}
- @Override
+ /**
+ * Adds a debug arg with key {@code name} and value {@code val}.
+ */
public Builder addArg(String name, String val) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
ArgString arg = mArgStringCache.get(name.hashCode());
if (arg == null || !arg.getName().equals(name)) {
arg = new ArgString(name);
@@ -507,27 +322,79 @@
return this;
}
- @Override
+ /**
+ * Adds a flow with {@code id}.
+ */
public Builder addFlow(int id) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
Flow flow = mFlowCache.get(sFlowSupplier);
flow.setProcessFlow(id);
mExtra.addPerfettoPointer(flow);
return this;
}
- @Override
+ /**
+ * Adds a terminating flow with {@code id}.
+ */
public Builder addTerminatingFlow(int id) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
Flow flow = mFlowCache.get(sFlowSupplier);
flow.setProcessTerminatingFlow(id);
mExtra.addPerfettoPointer(flow);
return this;
}
- @Override
+ /**
+ * Adds a flow with {@code id}.
+ */
+ public Builder setFlow(int id) {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
+ mFlow.setProcessFlow(id);
+ mExtra.addPerfettoPointer(mFlow);
+ return this;
+ }
+
+ /**
+ * Adds a terminating flow with {@code id}.
+ */
+ public Builder setTerminatingFlow(int id) {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
+ mTerminatingFlow.setProcessTerminatingFlow(id);
+ mExtra.addPerfettoPointer(mTerminatingFlow);
+ return this;
+ }
+
+ /**
+ * Adds the events to a named track instead of the thread track where the
+ * event occurred.
+ */
public Builder usingNamedTrack(long parentUuid, String name) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
NamedTrack track = mNamedTrackCache.get(name.hashCode());
if (track == null || !track.getName().equals(name)) {
@@ -538,19 +405,39 @@
return this;
}
- @Override
+ /**
+ * Adds the events to a process scoped named track instead of the thread track where the
+ * event occurred.
+ */
public Builder usingProcessNamedTrack(String name) {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
return usingNamedTrack(PerfettoTrace.getProcessTrackUuid(), name);
}
- @Override
+ /**
+ * Adds the events to a thread scoped named track instead of the thread track where the
+ * event occurred.
+ */
public Builder usingThreadNamedTrack(long tid, String name) {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
return usingNamedTrack(PerfettoTrace.getThreadTrackUuid(tid), name);
}
- @Override
+ /**
+ * Adds the events to a counter track instead. This is required for
+ * setting counter values.
+ */
public Builder usingCounterTrack(long parentUuid, String name) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
CounterTrack track = mCounterTrackCache.get(name.hashCode());
if (track == null || !track.getName().equals(name)) {
@@ -561,95 +448,178 @@
return this;
}
- @Override
+ /**
+ * Adds the events to a process scoped counter track instead. This is required for
+ * setting counter values.
+ */
public Builder usingProcessCounterTrack(String name) {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
return usingCounterTrack(PerfettoTrace.getProcessTrackUuid(), name);
}
- @Override
+ /**
+ * Adds the events to a thread scoped counter track instead. This is required for
+ * setting counter values.
+ */
public Builder usingThreadCounterTrack(long tid, String name) {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
return usingCounterTrack(PerfettoTrace.getThreadTrackUuid(tid), name);
}
- @Override
+ /**
+ * Sets a long counter value on the event.
+ *
+ */
public Builder setCounter(long val) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
mCounterInt64.setValue(val);
mExtra.addPerfettoPointer(mCounterInt64);
return this;
}
- @Override
+ /**
+ * Sets a double counter value on the event.
+ *
+ */
public Builder setCounter(double val) {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
mCounterDouble.setValue(val);
mExtra.addPerfettoPointer(mCounterDouble);
return this;
}
- @Override
+ /**
+ * Adds a proto field with field id {@code id} and value {@code val}.
+ */
public Builder addField(long id, long val) {
- checkContainer();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkContainer();
+ }
FieldInt64 field = mFieldInt64Cache.get(sFieldInt64Supplier);
field.setValue(id, val);
- mCurrentContainer.addField(field);
+ mExtra.addPerfettoPointer(mCurrentContainer, field);
return this;
}
- @Override
+ /**
+ * Adds a proto field with field id {@code id} and value {@code val}.
+ */
public Builder addField(long id, double val) {
- checkContainer();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkContainer();
+ }
FieldDouble field = mFieldDoubleCache.get(sFieldDoubleSupplier);
field.setValue(id, val);
- mCurrentContainer.addField(field);
+ mExtra.addPerfettoPointer(mCurrentContainer, field);
return this;
}
- @Override
+ /**
+ * Adds a proto field with field id {@code id} and value {@code val}.
+ */
public Builder addField(long id, String val) {
- checkContainer();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkContainer();
+ }
FieldString field = mFieldStringCache.get(sFieldStringSupplier);
field.setValue(id, val);
- mCurrentContainer.addField(field);
+ mExtra.addPerfettoPointer(mCurrentContainer, field);
return this;
}
- @Override
+ /**
+ * Begins a proto field.
+ * Fields can be added from this point and there must be a corresponding
+ * {@link endProto}.
+ *
+ * The proto field is a singleton and all proto fields get added inside the
+ * one {@link beginProto} and {@link endProto} within the {@link Builder}.
+ */
public Builder beginProto() {
- checkParent();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkParent();
+ }
mProto.clearFields();
mExtra.addPerfettoPointer(mProto);
- return mBuilderCache.get(sBuilderSupplier).initInternal(this, mProto);
+ return mBuilderCache.get(sBuilderSupplier).initInternal(this, mProto, true);
}
- @Override
+ /**
+ * Ends a proto field.
+ */
public Builder endProto() {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
if (mParent == null || mCurrentContainer == null) {
throw new IllegalStateException("No proto to end");
}
return mParent;
}
- @Override
+ /**
+ * Begins a nested proto field with field id {@code id}.
+ * Fields can be added from this point and there must be a corresponding
+ * {@link endNested}.
+ */
public Builder beginNested(long id) {
- checkContainer();
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
+ if (DEBUG) {
+ checkContainer();
+ }
FieldNested field = mFieldNestedCache.get(sFieldNestedSupplier);
field.setId(id);
- mCurrentContainer.addField(field);
- return mBuilderCache.get(sBuilderSupplier).initInternal(this, field);
+ mExtra.addPerfettoPointer(mCurrentContainer, field);
+ return mBuilderCache.get(sBuilderSupplier).initInternal(this, field, true);
}
- @Override
+ /**
+ * Ends a nested proto field.
+ */
public Builder endNested() {
+ if (!mIsCategoryEnabled) {
+ return this;
+ }
if (mParent == null || mCurrentContainer == null) {
throw new IllegalStateException("No nested field to end");
}
return mParent;
}
- private Builder initInternal(Builder parent, FieldContainer container) {
+
+ private Builder initInternal(Builder parent, FieldContainer field,
+ boolean isCategoryEnabled) {
mParent = parent;
- mCurrentContainer = container;
+ mCurrentContainer = field;
+ mIsCategoryEnabled = isCategoryEnabled;
mIsBuilt = false;
return this;
@@ -682,14 +652,8 @@
* Start a {@link Builder} to build a {@link PerfettoTrackEventExtra}.
*/
public static Builder builder() {
- return sTrackEventExtra.get().mBuilderCache.get(sBuilderSupplier).initInternal(null, null);
- }
-
- /**
- * Returns a no-op {@link Builder}. Useful if a category is disabled.
- */
- public static Builder noOpBuilder() {
- return NO_OP_BUILDER;
+ return sTrackEventExtra.get().mBuilderCache.get(sBuilderSupplier).initInternal(null, null,
+ false);
}
private final RingBuffer<NamedTrack> mNamedTrackCache =
@@ -707,7 +671,7 @@
private final Pool<FieldString> mFieldStringCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private final Pool<FieldNested> mFieldNestedCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private final Pool<Flow> mFlowCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
- private final Pool<BuilderImpl> mBuilderCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+ private final Pool<Builder> mBuilderCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
@@ -735,6 +699,15 @@
*/
public void addPerfettoPointer(PerfettoPointer extra) {
native_add_arg(mPtr, extra.getPtr());
+ mPendingPointers.add(extra);
+ }
+
+ /**
+ * Adds a pointer representing a track event parameter to the {@code container}.
+ */
+ public void addPerfettoPointer(FieldContainer container, PerfettoPointer extra) {
+ container.addField(extra);
+ mPendingPointers.add(extra);
}
/**
@@ -742,8 +715,10 @@
*/
public void reset() {
native_clear_args(mPtr);
+ mPendingPointers.clear();
}
+ @android.ravenwood.annotation.RavenwoodReplace
private CounterInt64 getCounterInt64() {
if (mCounterInt64 == null) {
mCounterInt64 = new CounterInt64();
@@ -751,6 +726,7 @@
return mCounterInt64;
}
+ @android.ravenwood.annotation.RavenwoodReplace
private CounterDouble getCounterDouble() {
if (mCounterDouble == null) {
mCounterDouble = new CounterDouble();
@@ -758,6 +734,7 @@
return mCounterDouble;
}
+ @android.ravenwood.annotation.RavenwoodReplace
private Proto getProto() {
if (mProto == null) {
mProto = new Proto();
@@ -765,6 +742,22 @@
return mProto;
}
+ @android.ravenwood.annotation.RavenwoodReplace
+ private Flow getFlow() {
+ if (mFlow == null) {
+ mFlow = new Flow();
+ }
+ return mFlow;
+ }
+
+ @android.ravenwood.annotation.RavenwoodReplace
+ private Flow getTerminatingFlow() {
+ if (mTerminatingFlow == null) {
+ mTerminatingFlow = new Flow();
+ }
+ return mTerminatingFlow;
+ }
+
private static final class Flow implements PerfettoPointer {
private static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
@@ -1324,4 +1317,29 @@
// Tracing currently completely disabled under Ravenwood
return 0;
}
+
+ private CounterInt64 getCounterInt64$ravenwood() {
+ // Tracing currently completely disabled under Ravenwood
+ return null;
+ }
+
+ private CounterDouble getCounterDouble$ravenwood() {
+ // Tracing currently completely disabled under Ravenwood
+ return null;
+ }
+
+ private Proto getProto$ravenwood() {
+ // Tracing currently completely disabled under Ravenwood
+ return null;
+ }
+
+ private Flow getFlow$ravenwood() {
+ // Tracing currently completely disabled under Ravenwood
+ return null;
+ }
+
+ private Flow getTerminatingFlow$ravenwood() {
+ // Tracing currently completely disabled under Ravenwood
+ return null;
+ }
}
diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
deleted file mode 100644
index 435c34f..0000000
--- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
+++ /dev/null
@@ -1,1600 +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 android.os;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.TestApi;
-import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodRedirect;
-import android.ravenwood.annotation.RavenwoodRedirectionClass;
-import android.util.Log;
-import android.util.Printer;
-import android.util.SparseArray;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.GuardedBy;
-
-import dalvik.annotation.optimization.NeverCompile;
-
-import java.io.FileDescriptor;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.PriorityQueue;
-import java.util.concurrent.atomic.AtomicInteger;
-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()}.
- */
-@RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_ravenwood")
-public final class MessageQueue {
- private static final String TAG = "SemiConcurrentMessageQueue";
- private static final boolean DEBUG = false;
- private static final boolean TRACE = false;
-
- // True if the message queue can be quit.
- private final boolean mQuitAllowed;
-
- @SuppressWarnings("unused")
- private long mPtr; // used by native code
-
- @IntDef(value = {
- STACK_NODE_MESSAGE,
- STACK_NODE_ACTIVE,
- STACK_NODE_PARKED,
- STACK_NODE_TIMEDPARK})
- @Retention(RetentionPolicy.SOURCE)
- private @interface StackNodeType {}
-
- /*
- * Stack node types. STACK_NODE_MESSAGE indicates a node containing a message.
- * The other types indicate what state our Looper thread is in. The bottom of
- * the stack is always a single state node. Message nodes are added on top.
- */
- private static final int STACK_NODE_MESSAGE = 0;
- /*
- * Active state indicates that next() is processing messages
- */
- private static final int STACK_NODE_ACTIVE = 1;
- /*
- * Parked state indicates that the Looper thread is sleeping indefinitely (nothing to deliver)
- */
- private static final int STACK_NODE_PARKED = 2;
- /*
- * Timed Park state indicates that the Looper thread is sleeping, waiting for a message
- * deadline
- */
- private static final int STACK_NODE_TIMEDPARK = 3;
-
- /* Describes a node in the Treiber stack */
- static class StackNode {
- @StackNodeType
- private final int mType;
-
- StackNode(@StackNodeType int type) {
- mType = type;
- }
-
- @StackNodeType
- final int getNodeType() {
- return mType;
- }
-
- final boolean isMessageNode() {
- return mType == STACK_NODE_MESSAGE;
- }
- }
-
- static final class MessageNode extends StackNode implements Comparable<MessageNode> {
- private final Message mMessage;
- volatile StackNode mNext;
- StateNode mBottomOfStack;
- boolean mWokeUp;
- boolean mRemovedFromStack = false;
- final long mInsertSeq;
-
- MessageNode(@NonNull Message message, long insertSeq) {
- super(STACK_NODE_MESSAGE);
- mMessage = message;
- mInsertSeq = insertSeq;
- }
-
- long getWhen() {
- return mMessage.when;
- }
-
- boolean isRemovedFromStack() {
- return mRemovedFromStack;
- }
-
- boolean removeFromStack() {
- if (!mRemovedFromStack) {
- mRemovedFromStack = true;
- return true;
- }
- return false;
- }
-
- boolean isAsync() {
- return mMessage.isAsynchronous();
- }
-
- boolean isBarrier() {
- return mMessage.target == null;
- }
-
- @Override
- public int compareTo(@NonNull MessageNode messageNode) {
- Message other = messageNode.mMessage;
-
- int compared = Long.compare(mMessage.when, other.when);
- if (compared == 0) {
- compared = Long.compare(mInsertSeq, messageNode.mInsertSeq);
- }
- return compared;
- }
- }
-
- static class StateNode extends StackNode {
- StateNode(int type) {
- super(type);
- }
- }
-
- static final class TimedParkStateNode extends StateNode {
- long mWhenToWake;
-
- TimedParkStateNode() {
- super(STACK_NODE_TIMEDPARK);
- }
- }
-
- private static final StateNode sStackStateActive = new StateNode(STACK_NODE_ACTIVE);
- private static final StateNode sStackStateParked = new StateNode(STACK_NODE_PARKED);
- private final TimedParkStateNode mStackStateTimedPark = new TimedParkStateNode();
-
- /* This is the top of our treiber stack. */
- private static final VarHandle sState;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- sState = l.findVarHandle(MessageQueue.class, "mStateValue",
- MessageQueue.StackNode.class);
- } catch (Exception e) {
- Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
- throw new ExceptionInInitializerError(e);
- }
- }
-
- private volatile StackNode mStateValue = sStackStateParked;
- @GuardedBy("mPriorityQueue")
- private final PriorityQueue<MessageNode> mPriorityQueue =
- new PriorityQueue<MessageNode>();
- @GuardedBy("mPriorityQueue")
- private final PriorityQueue<MessageNode> mAsyncPriorityQueue =
- new PriorityQueue<MessageNode>();
-
- /*
- * This helps us ensure that messages with the same timestamp are inserted in FIFO order.
- * Increments on each insert, starting at 0. MessageNode.compareTo() will compare sequences
- * when delivery timestamps are identical.
- */
- private static final VarHandle sNextInsertSeq;
- private volatile long mNextInsertSeqValue = 0;
- /*
- * The exception to the FIFO order rule is sendMessageAtFrontOfQueue().
- * Those messages must be in LIFO order.
- * Decrements on each front of queue insert.
- */
- private static final VarHandle sNextFrontInsertSeq;
- private volatile long mNextFrontInsertSeqValue = -1;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- sNextInsertSeq = l.findVarHandle(MessageQueue.class, "mNextInsertSeqValue",
- long.class);
- sNextFrontInsertSeq = l.findVarHandle(MessageQueue.class, "mNextFrontInsertSeqValue",
- long.class);
- } catch (Exception e) {
- Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
- throw new ExceptionInInitializerError(e);
- }
-
- }
-
- /*
- * Tracks the number of queued and cancelled messages in our stack.
- *
- * On item cancellation, determine whether to wake next() to flush tombstoned messages.
- * We track queued and cancelled counts as two ints packed into a single long.
- */
- private static final class MessageCounts {
- private static VarHandle sCounts;
- private volatile long mCountsValue = 0;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- sCounts = l.findVarHandle(MessageQueue.MessageCounts.class, "mCountsValue",
- long.class);
- } catch (Exception e) {
- Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
- throw new ExceptionInInitializerError(e);
- }
- }
- /* We use a special value to indicate when next() has been woken for flush. */
- private static final long AWAKE = Long.MAX_VALUE;
- /*
- * Minimum number of messages in the stack which we need before we consider flushing
- * tombstoned items.
- */
- private static final int MESSAGE_FLUSH_THRESHOLD = 10;
-
- private static int numQueued(long val) {
- return (int) (val >>> Integer.SIZE);
- }
-
- private static int numCancelled(long val) {
- return (int) val;
- }
-
- private static long combineCounts(int queued, int cancelled) {
- return ((long) queued << Integer.SIZE) | (long) cancelled;
- }
-
- public void incrementQueued() {
- while (true) {
- long oldVal = mCountsValue;
- int queued = numQueued(oldVal);
- int cancelled = numCancelled(oldVal);
- /* Use Math.max() to avoid overflow of queued count */
- long newVal = combineCounts(Math.max(queued + 1, queued), cancelled);
-
- /* Don't overwrite 'AWAKE' state */
- if (oldVal == AWAKE || sCounts.compareAndSet(this, oldVal, newVal)) {
- break;
- }
- }
- }
-
- public boolean incrementCancelled() {
- while (true) {
- long oldVal = mCountsValue;
- if (oldVal == AWAKE) {
- return false;
- }
- int queued = numQueued(oldVal);
- int cancelled = numCancelled(oldVal);
- boolean needsPurge = queued > MESSAGE_FLUSH_THRESHOLD
- && (queued >> 1) < cancelled;
- long newVal;
- if (needsPurge) {
- newVal = AWAKE;
- } else {
- newVal = combineCounts(queued,
- Math.max(cancelled + 1, cancelled));
- }
-
- if (sCounts.compareAndSet(this, oldVal, newVal)) {
- return needsPurge;
- }
- }
- }
-
- public void clearCounts() {
- mCountsValue = 0;
- }
- }
-
- private final MessageCounts mMessageCounts = new MessageCounts();
-
- private final Object mIdleHandlersLock = new Object();
- @GuardedBy("mIdleHandlersLock")
- private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
- private IdleHandler[] mPendingIdleHandlers;
-
- private final Object mFileDescriptorRecordsLock = new Object();
- @GuardedBy("mFileDescriptorRecordsLock")
- private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
-
- private static final VarHandle sQuitting;
- private boolean mQuittingValue = false;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- sQuitting = l.findVarHandle(MessageQueue.class, "mQuittingValue", boolean.class);
- } catch (Exception e) {
- Log.wtf(TAG, "VarHandle lookup failed with exception: " + e);
- throw new ExceptionInInitializerError(e);
- }
- }
-
- // The next barrier token.
- // Barriers are indicated by messages with a null target whose arg1 field carries the token.
- private final AtomicInteger mNextBarrierToken = new AtomicInteger(1);
-
- @RavenwoodRedirect
- private static native long nativeInit();
- @RavenwoodRedirect
- private static native void nativeDestroy(long ptr);
- @RavenwoodRedirect
- private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
- @RavenwoodRedirect
- private static native void nativeWake(long ptr);
- @RavenwoodRedirect
- private static native boolean nativeIsPolling(long ptr);
- @RavenwoodRedirect
- private static native void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
-
- MessageQueue(boolean quitAllowed) {
- mQuitAllowed = quitAllowed;
- mPtr = nativeInit();
- }
-
- @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() {
- MessageNode msgNode = null;
- MessageNode asyncMsgNode = null;
-
- synchronized (mPriorityQueue) {
- msgNode = mPriorityQueue.peek();
- asyncMsgNode = mAsyncPriorityQueue.peek();
-
- final long now = SystemClock.uptimeMillis();
- if ((msgNode != null && msgNode.getWhen() <= now)
- || (asyncMsgNode != null && asyncMsgNode.getWhen() <= now)) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * 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 (mIdleHandlersLock) {
- 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 (mIdleHandlersLock) {
- 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() {
- // If the loop is quitting then it must not be idling.
- // We can assume mPtr != 0 when sQuitting is false.
- return !((boolean) sQuitting.getVolatile(this)) && nativeIsPolling(mPtr);
- }
-
- /* Helper to choose the correct queue to insert into. */
- @GuardedBy("mPriorityQueue")
- private void insertIntoPriorityQueue(MessageNode msgNode) {
- if (msgNode.isAsync()) {
- mAsyncPriorityQueue.offer(msgNode);
- } else {
- mPriorityQueue.offer(msgNode);
- }
- }
-
- @GuardedBy("mPriorityQueue")
- private boolean removeFromPriorityQueue(MessageNode msgNode) {
- if (msgNode.isAsync()) {
- return mAsyncPriorityQueue.remove(msgNode);
- } else {
- return mPriorityQueue.remove(msgNode);
- }
- }
-
- private MessageNode pickEarliestNode(MessageNode nodeA, MessageNode nodeB) {
- if (nodeA != null && nodeB != null) {
- if (nodeA.compareTo(nodeB) < 0) {
- return nodeA;
- }
- return nodeB;
- }
-
- return nodeA != null ? nodeA : nodeB;
- }
-
- /* Move any non-cancelled messages into the priority queue */
- private void drainStack(StackNode oldTop) {
- while (oldTop.isMessageNode()) {
- MessageNode oldTopMessageNode = (MessageNode) oldTop;
- if (oldTopMessageNode.removeFromStack()) {
- insertIntoPriorityQueue(oldTopMessageNode);
- }
- MessageNode inserted = oldTopMessageNode;
- oldTop = oldTopMessageNode.mNext;
- }
- }
-
- /* Set the stack state to Active, return a list of nodes to walk. */
- private StackNode swapAndSetStackStateActive() {
- while (true) {
- /* Set stack state to Active, get node list to walk later */
- StackNode current = (StackNode) sState.getVolatile(this);
- if (current == sStackStateActive
- || sState.compareAndSet(this, current, sStackStateActive)) {
- return current;
- }
- }
- }
-
- /* This is only read/written from the Looper thread */
- private int mNextPollTimeoutMillis;
- private static final AtomicLong mMessagesDelivered = new AtomicLong();
-
- private Message nextMessage() {
- int i = 0;
-
- while (true) {
- if (DEBUG) {
- Log.d(TAG, "nextMessage loop #" + i);
- i++;
- }
-
- /* This protects us from racing with remove. Enqueue can still add items. */
- synchronized (mPriorityQueue) {
-
- /*
- * Set our state to active, drain any items from the stack into our priority queues
- */
- StackNode oldTop;
- oldTop = swapAndSetStackStateActive();
- drainStack(oldTop);
-
- /*
- * The objective of this next block of code is to:
- * - find a message to return (if any is ready)
- * - find a next message we would like to return, after scheduling.
- * - we make our scheduling decision based on this next message (if it exists).
- *
- * We have two queues to juggle and the presence of barriers throws an additional
- * wrench into our plans.
- */
-
- /* Get the first node from each queue */
- MessageNode msgNode = mPriorityQueue.peek();
- MessageNode asyncMsgNode = mAsyncPriorityQueue.peek();
-
- if (DEBUG) {
- if (msgNode != null) {
- Message msg = msgNode.mMessage;
- Log.d(TAG, "Next found node what: " + msg.what + " when: " + msg.when
- + " seq: " + msgNode.mInsertSeq + "barrier: "
- + msgNode.isBarrier() + " now: "
- + SystemClock.uptimeMillis());
- }
- if (asyncMsgNode != null) {
- Message msg = asyncMsgNode.mMessage;
- Log.d(TAG, "Next found async node what: " + msg.what + " when: " + msg.when
- + " seq: " + asyncMsgNode.mInsertSeq + "barrier: "
- + asyncMsgNode.isBarrier() + " now: "
- + SystemClock.uptimeMillis());
- }
- }
-
- /*
- * the node which we will return, null if none are ready
- */
- MessageNode found = null;
- /*
- * The node from which we will determine our next wakeup time.
- * Null indicates there is no next message ready. If we found a node,
- * we can leave this null as Looper will call us again after delivering
- * the message.
- */
- MessageNode next = null;
-
- long now = SystemClock.uptimeMillis();
- /*
- * If we have a barrier we should return the async node if it exists and is
- * ready
- */
- if (msgNode != null && msgNode.isBarrier()) {
- if (asyncMsgNode != null && now >= asyncMsgNode.getWhen()) {
- found = asyncMsgNode;
- removeFromPriorityQueue(found);
- } else {
- next = asyncMsgNode;
- }
- } else { /* No barrier. */
- MessageNode earliest;
- /*
- * If we have two messages, pick the earliest option from either queue.
- * Otherwise grab whichever node is non-null. If both are null we'll fall
- * through.
- */
- earliest = pickEarliestNode(msgNode, asyncMsgNode);
-
- if (earliest != null) {
- if (now >= earliest.getWhen()) {
- found = earliest;
- removeFromPriorityQueue(found);
- } else {
- next = earliest;
- }
- }
- }
-
- if (DEBUG) {
- if (found != null) {
- Message msg = found.mMessage;
- Log.d(TAG, "Will deliver node what: " + msg.what + " when: " + msg.when
- + " seq: " + found.mInsertSeq + " barrier: "
- + found.isBarrier() + " async: " + found.isAsync()
- + " now: " + SystemClock.uptimeMillis());
- } else {
- Log.d(TAG, "No node to deliver");
- }
- if (next != null) {
- Message msg = next.mMessage;
- Log.d(TAG, "Next node what: " + msg.what + " when: " + msg.when + " seq: "
- + next.mInsertSeq + " barrier: " + next.isBarrier()
- + " async: " + next.isAsync()
- + " now: " + SystemClock.uptimeMillis());
- } else {
- Log.d(TAG, "No next node");
- }
- }
-
- /*
- * If we have a found message, we will get called again so there's no need to set
- * state.
- * In that case we can leave our state as ACTIVE.
- *
- * Otherwise we should determine how to park the thread.
- */
- StateNode nextOp = sStackStateActive;
- if (found == null) {
- if (next == null) {
- /* No message to deliver, sleep indefinitely */
- mNextPollTimeoutMillis = -1;
- nextOp = sStackStateParked;
- if (DEBUG) {
- Log.d(TAG, "nextMessage next state is StackStateParked");
- }
- } else {
- /* Message not ready, or we found one to deliver already, set a timeout */
- long nextMessageWhen = next.getWhen();
- if (nextMessageWhen > now) {
- mNextPollTimeoutMillis = (int) Math.min(nextMessageWhen - now,
- Integer.MAX_VALUE);
- } else {
- mNextPollTimeoutMillis = 0;
- }
-
- mStackStateTimedPark.mWhenToWake = now + mNextPollTimeoutMillis;
- nextOp = mStackStateTimedPark;
- if (DEBUG) {
- Log.d(TAG, "nextMessage next state is StackStateTimedParked "
- + " next timeout ms " + mNextPollTimeoutMillis
- + " mWhenToWake: " + mStackStateTimedPark.mWhenToWake
- + " now " + now);
- }
- }
- }
-
- /*
- * Try to swap our state from Active back to Park or TimedPark. If we raced with
- * enqueue, loop back around to pick up any new items.
- */
- if (sState.compareAndSet(this, sStackStateActive, nextOp)) {
- mMessageCounts.clearCounts();
- if (found != null) {
- if (TRACE) {
- Trace.setCounter("MQ.Delivered", mMessagesDelivered.incrementAndGet());
- }
- return found.mMessage;
- }
- return null;
- }
- if (found != null) {
- /*
- * Add this node back - we will be adding new nodes into our priority queue, and
- * recalculating what to return.
- */
- insertIntoPriorityQueue(found);
- }
- }
- }
- }
-
- Message next() {
- final long ptr = mPtr;
- if (ptr == 0) {
- return null;
- }
-
- mNextPollTimeoutMillis = 0;
- int pendingIdleHandlerCount = -1; // -1 only during first iteration
- while (true) {
- if (mNextPollTimeoutMillis != 0) {
- Binder.flushPendingCommands();
- }
-
- nativePollOnce(ptr, mNextPollTimeoutMillis);
-
- Message msg = nextMessage();
- if (msg != null) {
- msg.markInUse();
- return msg;
- }
-
- if ((boolean) sQuitting.getVolatile(this)) {
- return null;
- }
-
- synchronized (mIdleHandlersLock) {
- // 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.
- if (pendingIdleHandlerCount < 0
- && isIdle()) {
- pendingIdleHandlerCount = mIdleHandlers.size();
- }
- if (pendingIdleHandlerCount <= 0) {
- // No idle handlers to run. Loop and wait some more.
- 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 (mIdleHandlersLock) {
- 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.
- mNextPollTimeoutMillis = 0;
- }
- }
-
- void quit(boolean safe) {
- if (!mQuitAllowed) {
- throw new IllegalStateException("Main thread not allowed to quit.");
- }
- synchronized (mIdleHandlersLock) {
- if (sQuitting.compareAndSet(this, false, true)) {
- if (safe) {
- removeAllFutureMessages();
- } else {
- removeAllMessages();
- }
-
- // We can assume mPtr != 0 because sQuitting was previously false.
- nativeWake(mPtr);
- }
- }
- }
-
- boolean enqueueMessage(@NonNull Message msg, long when) {
- if (msg.target == null) {
- throw new IllegalArgumentException("Message must have a target.");
- }
-
- if (msg.isInUse()) {
- throw new IllegalStateException(msg + " This message is already in use.");
- }
-
- return enqueueMessageUnchecked(msg, when);
- }
-
- private boolean enqueueMessageUnchecked(@NonNull Message msg, long when) {
- if ((boolean) sQuitting.getVolatile(this)) {
- IllegalStateException e = new IllegalStateException(
- msg.target + " sending message to a Handler on a dead thread");
- Log.w(TAG, e.getMessage(), e);
- msg.recycleUnchecked();
- return false;
- }
-
- long seq = when != 0 ? ((long)sNextInsertSeq.getAndAdd(this, 1L) + 1L)
- : ((long)sNextFrontInsertSeq.getAndAdd(this, -1L) - 1L);
- /* TODO: Add a MessageNode member to Message so we can avoid this allocation */
- MessageNode node = new MessageNode(msg, seq);
- msg.when = when;
- msg.markInUse();
-
- if (DEBUG) {
- Log.d(TAG, "Insert message what: " + msg.what + " when: " + msg.when + " seq: "
- + node.mInsertSeq + " barrier: " + node.isBarrier() + " async: "
- + node.isAsync() + " now: " + SystemClock.uptimeMillis());
- }
-
- while (true) {
- StackNode old = (StackNode) sState.getVolatile(this);
- boolean wakeNeeded;
- boolean inactive;
-
- node.mNext = old;
- switch (old.getNodeType()) {
- case STACK_NODE_ACTIVE:
- /*
- * The worker thread is currently active and will process any elements added to
- * the stack before parking again.
- */
- node.mBottomOfStack = (StateNode) old;
- inactive = false;
- node.mWokeUp = true;
- wakeNeeded = false;
- break;
-
- case STACK_NODE_PARKED:
- node.mBottomOfStack = (StateNode) old;
- inactive = true;
- node.mWokeUp = true;
- wakeNeeded = true;
- break;
-
- case STACK_NODE_TIMEDPARK:
- node.mBottomOfStack = (StateNode) old;
- inactive = true;
- wakeNeeded = mStackStateTimedPark.mWhenToWake >= node.getWhen();
- node.mWokeUp = wakeNeeded;
- break;
-
- default:
- MessageNode oldMessage = (MessageNode) old;
-
- node.mBottomOfStack = oldMessage.mBottomOfStack;
- int bottomType = node.mBottomOfStack.getNodeType();
- inactive = bottomType >= STACK_NODE_PARKED;
- wakeNeeded = (bottomType == STACK_NODE_TIMEDPARK
- && mStackStateTimedPark.mWhenToWake >= node.getWhen()
- && !oldMessage.mWokeUp);
- node.mWokeUp = oldMessage.mWokeUp || wakeNeeded;
- break;
- }
- if (sState.compareAndSet(this, old, node)) {
- if (inactive) {
- if (wakeNeeded) {
- nativeWake(mPtr);
- } else {
- mMessageCounts.incrementQueued();
- }
- }
- return true;
- }
- }
- }
-
- /**
- * 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
- */
- @TestApi
- public int postSyncBarrier() {
- return postSyncBarrier(SystemClock.uptimeMillis());
- }
-
- private int postSyncBarrier(long when) {
- final int token = mNextBarrierToken.getAndIncrement();
- final Message msg = Message.obtain();
-
- msg.markInUse();
- msg.arg1 = token;
-
- if (!enqueueMessageUnchecked(msg, when)) {
- Log.wtf(TAG, "Unexpected error while adding sync barrier!");
- return -1;
- }
-
- return token;
- }
-
- private class MatchBarrierToken extends MessageCompare {
- 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
- */
- @TestApi
- public void removeSyncBarrier(int token) {
- boolean removed;
- MessageNode first;
- final MatchBarrierToken matchBarrierToken = new MatchBarrierToken(token);
-
- synchronized (mPriorityQueue) {
- try {
- /* Retain the first element to see if we are currently stuck on a barrier. */
- first = mPriorityQueue.peek();
- } catch (NoSuchElementException e) {
- /* The queue is empty */
- first = null;
- }
-
- removed = findOrRemoveMessages(null, 0, null, null, 0, matchBarrierToken, true);
- if (removed && first != null) {
- Message m = first.mMessage;
- if (m.target == null && m.arg1 == token) {
- /* Wake up next() in case it was sleeping on this barrier. */
- nativeWake(mPtr);
- }
- } else if (!removed) {
- throw new IllegalStateException("The specified message queue synchronization "
- + " barrier token has not been posted or has already been removed.");
- }
- }
- }
-
- private StateNode getStateNode(StackNode node) {
- if (node.isMessageNode()) {
- return ((MessageNode) node).mBottomOfStack;
- }
- return (StateNode) node;
- }
-
- /*
- * This class is used to find matches for hasMessages() and removeMessages()
- */
- private abstract static class MessageCompare {
- public abstract boolean compareMessage(Message m, Handler h, int what, Object object,
- Runnable r, long when);
- }
- @GuardedBy("mPriorityQueue")
- private boolean stackHasMessages(Handler h, int what, Object object, Runnable r, long when,
- MessageCompare compare, boolean removeMatches) {
- boolean found = false;
- StackNode top = (StackNode) sState.getVolatile(this);
- StateNode bottom = getStateNode(top);
-
- /* No messages to search. */
- if (!top.isMessageNode()) {
- return false;
- }
-
- /*
- * We have messages that we may tombstone. Walk the stack until we hit the bottom.
- * next() will remove them on it's next pass.
- */
- if (!(top instanceof MessageNode)) {
- Log.wtf(TAG, "Unknown node type found in Trieber stack");
- }
- MessageNode p = (MessageNode) top;
-
- while (true) {
- if (compare.compareMessage(p.mMessage, h, what, object, r, when)) {
- found = true;
- if (DEBUG) {
- Log.w(TAG, "stackHasMessages node matches");
- }
- if (removeMatches) {
- if (p.removeFromStack()) {
- p.mMessage.recycleUnchecked();
- if (mMessageCounts.incrementCancelled()) {
- nativeWake(mPtr);
- }
- }
- } else {
- return true;
- }
- }
-
- StackNode n = p.mNext;
- if (!n.isMessageNode()) {
- /* We reached the end of the stack */
- return found;
- }
- p = (MessageNode) n;
- }
- }
-
- @GuardedBy("mPriorityQueue")
- private boolean priorityQueueHasMessage(PriorityQueue queue, Handler h,
- int what, Object object, Runnable r, long when, MessageCompare compare,
- boolean removeMatches) {
- Iterator<MessageNode> iterator = queue.iterator();
- boolean found = false;
-
- while (iterator.hasNext()) {
- MessageNode msg = iterator.next();
-
- if (compare.compareMessage(msg.mMessage, h, what, object, r, when)) {
- if (removeMatches) {
- found = true;
- iterator.remove();
- msg.mMessage.recycleUnchecked();
- } else {
- return true;
- }
- }
- }
- return found;
- }
-
- private boolean findOrRemoveMessages(Handler h, int what, Object object, Runnable r, long when,
- MessageCompare compare, boolean removeMatches) {
- boolean foundInStack, foundInQueue;
-
- synchronized (mPriorityQueue) {
- foundInStack = stackHasMessages(h, what, object, r, when, compare, removeMatches);
- foundInQueue = priorityQueueHasMessage(mPriorityQueue, h, what, object, r, when,
- compare, removeMatches);
- foundInQueue |= priorityQueueHasMessage(mAsyncPriorityQueue, h, what, object, r, when,
- compare, removeMatches);
-
- return foundInStack || foundInQueue;
- }
- }
-
- private static class MatchHandlerWhatAndObject extends MessageCompare {
- @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 final MatchHandlerWhatAndObject mMatchHandlerWhatAndObject =
- new MatchHandlerWhatAndObject();
- boolean hasMessages(Handler h, int what, Object object) {
- if (h == null) {
- return false;
- }
-
- return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, false);
- }
-
- private static class MatchHandlerWhatAndObjectEquals extends MessageCompare {
- @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 final MatchHandlerWhatAndObjectEquals mMatchHandlerWhatAndObjectEquals =
- new MatchHandlerWhatAndObjectEquals();
- boolean hasEqualMessages(Handler h, int what, Object object) {
- if (h == null) {
- return false;
- }
-
- return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals,
- false);
- }
-
- private static class MatchHandlerRunnableAndObject extends MessageCompare {
- @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 final MatchHandlerRunnableAndObject mMatchHandlerRunnableAndObject =
- new MatchHandlerRunnableAndObject();
-
- boolean hasMessages(Handler h, Runnable r, Object object) {
- if (h == null) {
- return false;
- }
-
- return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, false);
- }
-
- private static class MatchHandler extends MessageCompare {
- @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 final MatchHandler mMatchHandler = new MatchHandler();
- boolean hasMessages(Handler h) {
- if (h == null) {
- return false;
- }
- return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false);
- }
-
- void removeMessages(Handler h, int what, Object object) {
- if (h == null) {
- return;
- }
- findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true);
- }
-
- void removeEqualMessages(Handler h, int what, Object object) {
- if (h == null) {
- return;
- }
- findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true);
- }
-
- void removeMessages(Handler h, Runnable r, Object object) {
- if (h == null || r == null) {
- return;
- }
- findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true);
- }
-
- private static class MatchHandlerRunnableAndObjectEquals extends MessageCompare {
- @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 final MatchHandlerRunnableAndObjectEquals mMatchHandlerRunnableAndObjectEquals =
- new MatchHandlerRunnableAndObjectEquals();
- void removeEqualMessages(Handler h, Runnable r, Object object) {
- if (h == null || r == null) {
- return;
- }
- findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true);
- }
-
- private static class MatchHandlerAndObject extends MessageCompare {
- @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 final MatchHandlerAndObject mMatchHandlerAndObject = new MatchHandlerAndObject();
- void removeCallbacksAndMessages(Handler h, Object object) {
- if (h == null) {
- return;
- }
- findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true);
- }
-
- private static class MatchHandlerAndObjectEquals extends MessageCompare {
- @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 final MatchHandlerAndObjectEquals mMatchHandlerAndObjectEquals =
- new MatchHandlerAndObjectEquals();
- void removeCallbacksAndEqualMessages(Handler h, Object object) {
- if (h == null) {
- return;
- }
- findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true);
- }
-
- private static class MatchAllMessages extends MessageCompare {
- @Override
- public boolean compareMessage(Message m, Handler h, int what, Object object, Runnable r,
- long when) {
- return true;
- }
- }
- private final MatchAllMessages mMatchAllMessages = new MatchAllMessages();
- private void removeAllMessages() {
- findOrRemoveMessages(null, -1, null, null, 0, mMatchAllMessages, true);
- }
-
- private static class MatchAllFutureMessages extends MessageCompare {
- @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 final MatchAllFutureMessages mMatchAllFutureMessages = new MatchAllFutureMessages();
- private void removeAllFutureMessages() {
- findOrRemoveMessages(null, -1, null, null, SystemClock.uptimeMillis(),
- mMatchAllFutureMessages, true);
- }
-
- @NeverCompile
- private void printPriorityQueueNodes() {
- Iterator<MessageNode> iterator = mPriorityQueue.iterator();
-
- Log.d(TAG, "* Dump priority queue");
- while (iterator.hasNext()) {
- MessageNode msgNode = iterator.next();
- Log.d(TAG, "** MessageNode what: " + msgNode.mMessage.what + " when "
- + msgNode.mMessage.when + " seq: " + msgNode.mInsertSeq);
- }
- }
-
- @NeverCompile
- private int dumpPriorityQueue(PriorityQueue<MessageNode> queue, Printer pw, String prefix,
- Handler h, int n) {
- int count = 0;
- long now = SystemClock.uptimeMillis();
-
- for (MessageNode msgNode : queue) {
- Message msg = msgNode.mMessage;
- if (h == null || h == msg.target) {
- pw.println(prefix + "Message " + (n + count) + ": " + msg.toString(now));
- }
- count++;
- }
- return count;
- }
-
- @NeverCompile
- void dump(Printer pw, String prefix, Handler h) {
- long now = SystemClock.uptimeMillis();
- int n = 0;
-
- pw.println(prefix + "(MessageQueue is using SemiConcurrent implementation)");
-
- StackNode node = (StackNode) sState.getVolatile(this);
- while (node != null) {
- if (node.isMessageNode()) {
- Message msg = ((MessageNode) node).mMessage;
- if (h == null || h == msg.target) {
- pw.println(prefix + "Message " + n + ": " + msg.toString(now));
- }
- node = ((MessageNode) node).mNext;
- } else {
- pw.println(prefix + "State: " + node);
- node = null;
- }
- n++;
- }
-
- synchronized (mPriorityQueue) {
- pw.println(prefix + "PriorityQueue Messages: ");
- n += dumpPriorityQueue(mPriorityQueue, pw, prefix, h, n);
- pw.println(prefix + "AsyncPriorityQueue Messages: ");
- n += dumpPriorityQueue(mAsyncPriorityQueue, pw, prefix, h, n);
- }
-
- pw.println(prefix + "(Total messages: " + n + ", polling=" + isPolling()
- + ", quitting=" + (boolean) sQuitting.getVolatile(this) + ")");
- }
-
- @NeverCompile
- private int dumpPriorityQueue(PriorityQueue<MessageNode> queue, ProtoOutputStream proto) {
- int count = 0;
-
- for (MessageNode msgNode : queue) {
- Message msg = msgNode.mMessage;
- msg.dumpDebug(proto, MessageQueueProto.MESSAGES);
- count++;
- }
- return count;
- }
-
- @NeverCompile
- void dumpDebug(ProtoOutputStream proto, long fieldId) {
- final long messageQueueToken = proto.start(fieldId);
-
- StackNode node = (StackNode) sState.getVolatile(this);
- while (node.isMessageNode()) {
- Message msg = ((MessageNode) node).mMessage;
- msg.dumpDebug(proto, MessageQueueProto.MESSAGES);
- node = ((MessageNode) node).mNext;
- }
-
- synchronized (mPriorityQueue) {
- dumpPriorityQueue(mPriorityQueue, proto);
- dumpPriorityQueue(mAsyncPriorityQueue, proto);
- }
-
- proto.write(MessageQueueProto.IS_POLLING_LOCKED, isPolling());
- proto.write(MessageQueueProto.IS_QUITTING, (boolean) sQuitting.getVolatile(this));
- proto.end(messageQueueToken);
- }
-
- /**
- * 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 (mFileDescriptorRecordsLock) {
- 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 (mFileDescriptorRecordsLock) {
- 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.
- 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 (mFileDescriptorRecordsLock) {
- 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 (mFileDescriptorRecordsLock) {
- 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;
- }
-
- /**
- * 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);
- }
-
- 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/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index f9935d2..1c3dd9e 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -217,7 +217,7 @@
new VendorVibrationSessionCallbackDelegate(executor, callback);
if (mService == null) {
Log.w(TAG, "Failed to start vibration session; no vibrator manager service.");
- callbackDelegate.onFinished(VendorVibrationSession.STATUS_UNKNOWN_ERROR);
+ callbackDelegate.onFinished(VendorVibrationSession.STATUS_UNSUPPORTED);
return;
}
try {
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index 9e7c9f6..d3c677b 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -4,15 +4,6 @@
# keep-sorted start block=yes newline_separated=yes
flag {
- # Holdback study for concurrent MessageQueue.
- # Do not promote beyond trunkfood.
- namespace: "system_performance"
- name: "message_queue_force_legacy"
- description: "Whether to holdback concurrent MessageQueue (force legacy)."
- bug: "336880969"
-}
-
-flag {
name: "adpf_gpu_report_actual_work_duration"
is_exported: true
namespace: "game"
diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig
index 7ceb948..0615578 100644
--- a/core/java/android/os/vibrator/flags.aconfig
+++ b/core/java/android/os/vibrator/flags.aconfig
@@ -145,3 +145,13 @@
purpose: PURPOSE_FEATURE
}
}
+
+flag {
+ namespace: "haptics"
+ name: "fix_vibration_thread_callback_handling"
+ description: "Fix how the VibrationThread handles late callbacks from the vibrator HAL"
+ bug: "395005081"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index d469a2f..ca24c0c 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -514,3 +514,12 @@
description: "Force AttributionSource.myAttributionSource() to return a default device id"
bug: "343121936"
}
+
+flag {
+ name: "grant_read_blocked_numbers_to_system_ui_intelligence"
+ is_exported: true
+ is_fixed_read_only: true
+ namespace: "permissions"
+ description: "This flag is used to add role protection to READ_BLOCKED_NUMBERS for SYSTEM_UI_INTELLIGENCE"
+ bug: "354758615"
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1a9b42e..538283e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -153,7 +153,6 @@
* Output: Nothing.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- @FlaggedApi(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String ACTION_SATELLITE_SETTING = "android.settings.SATELLITE_SETTING";
/**
@@ -13018,18 +13017,16 @@
* false/0.
* @hide
*/
- @Readable
public static final String REDACT_OTP_NOTIFICATION_WHILE_CONNECTED_TO_WIFI =
"redact_otp_on_wifi";
/**
- * Toggle for whether to immediately redact OTP notifications, or require the device to be
- * locked for 10 minutes. Defaults to false/0
+ * Time (in milliseconds) that the device should need to be locked, in order for an OTP
+ * notification to be redacted. Default is 10 minutes (600,000 ms)
* @hide
*/
- @Readable
- public static final String REDACT_OTP_NOTIFICATION_IMMEDIATELY =
- "remove_otp_redaction_delay";
+ public static final String OTP_NOTIFICATION_REDACTION_LOCK_TIME =
+ "otp_redaction_lock_time";
/**
* These entries are considered common between the personal and the managed profile,
diff --git a/core/java/android/service/credentials/CredentialProviderInfoFactory.java b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
index 3cd705a..2266e96 100644
--- a/core/java/android/service/credentials/CredentialProviderInfoFactory.java
+++ b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
@@ -88,7 +88,7 @@
int userId,
boolean isSystemProvider,
boolean isPrimary)
- throws PackageManager.NameNotFoundException {
+ throws PackageManager.NameNotFoundException, SecurityException, NullPointerException {
return create(
context,
getServiceInfoOrThrow(serviceComponent, userId),
@@ -117,7 +117,7 @@
boolean disableSystemAppVerificationForTests,
boolean isEnabled,
boolean isPrimary)
- throws SecurityException {
+ throws SecurityException, NullPointerException {
verifyProviderPermission(serviceInfo);
if (isSystemProvider) {
if (!isValidSystemProvider(
@@ -199,7 +199,7 @@
}
private static CredentialProviderInfo.Builder populateMetadata(
- @NonNull Context context, ServiceInfo serviceInfo) {
+ @NonNull Context context, ServiceInfo serviceInfo) throws NullPointerException {
requireNonNull(context, "context must not be null");
final PackageManager pm = context.getPackageManager();
CredentialProviderInfo.Builder builder = new CredentialProviderInfo.Builder(serviceInfo);
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 6f94c1b..4cbd5be 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -3131,6 +3131,7 @@
* @return null if DND is off or describeForeverCondition is false and
* DND is on forever (until turned off)
*/
+ // TODO: b/368247671 - Delete when inlining MODES_UI
public static String getDescription(Context context, boolean zenOn, ZenModeConfig config,
boolean describeForeverCondition) {
if (!zenOn || config == null) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index d05fa9e..daa4e89 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -2330,8 +2330,6 @@
}
public void onCarrierRoamingNtnModeChanged(boolean active) {
- if (!Flags.carrierEnabledSatelliteFlag()) return;
-
CarrierRoamingNtnListener listener =
(CarrierRoamingNtnListener) mTelephonyCallbackWeakRef.get();
if (listener == null) return;
diff --git a/core/java/android/text/AlteredCharSequence.java b/core/java/android/text/AlteredCharSequence.java
index 971a47d..a05c690a 100644
--- a/core/java/android/text/AlteredCharSequence.java
+++ b/core/java/android/text/AlteredCharSequence.java
@@ -24,6 +24,7 @@
* @deprecated The functionality this class offers is easily implemented outside the framework.
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AlteredCharSequence
implements CharSequence, GetChars
{
diff --git a/core/java/android/text/AndroidBidi.java b/core/java/android/text/AndroidBidi.java
index 31da799..fcdd50a 100644
--- a/core/java/android/text/AndroidBidi.java
+++ b/core/java/android/text/AndroidBidi.java
@@ -28,6 +28,7 @@
* @hide
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AndroidBidi {
/**
diff --git a/core/java/android/text/AndroidCharacter.java b/core/java/android/text/AndroidCharacter.java
index c5f1a01..37c4fdb 100644
--- a/core/java/android/text/AndroidCharacter.java
+++ b/core/java/android/text/AndroidCharacter.java
@@ -22,6 +22,7 @@
* @deprecated Use various methods from {@link android.icu.lang.UCharacter}, instead.
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AndroidCharacter
{
public static final int EAST_ASIAN_WIDTH_NEUTRAL = 0;
diff --git a/core/java/android/text/Annotation.java b/core/java/android/text/Annotation.java
index bb5d3ea..ac3e5a9 100644
--- a/core/java/android/text/Annotation.java
+++ b/core/java/android/text/Annotation.java
@@ -23,6 +23,7 @@
* TextView save/restore cycles and can be used to keep application-specific
* data that needs to be maintained for regions of text.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Annotation implements ParcelableSpan {
private final String mKey;
private final String mValue;
diff --git a/core/java/android/text/AutoGrowArray.java b/core/java/android/text/AutoGrowArray.java
index e428377..06c74c3 100644
--- a/core/java/android/text/AutoGrowArray.java
+++ b/core/java/android/text/AutoGrowArray.java
@@ -30,6 +30,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class AutoGrowArray {
private static final int MIN_CAPACITY_INCREMENT = 12;
private static final int MAX_CAPACITY_TO_BE_KEPT = 10000;
diff --git a/core/java/android/text/AutoText.java b/core/java/android/text/AutoText.java
index c5339a4..d7b0547 100644
--- a/core/java/android/text/AutoText.java
+++ b/core/java/android/text/AutoText.java
@@ -31,6 +31,7 @@
/**
* This class accesses a dictionary of corrections to frequent misspellings.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AutoText {
// struct trie {
// char c;
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index dfa172d..6d4103c 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -82,6 +82,7 @@
* first-strong estimation algorithm. It can also be configured to use a custom directionality
* estimation object.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class BidiFormatter {
/**
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 4fdcecc..2b410e6 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -45,6 +45,7 @@
* {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
* Canvas.drawText()} directly.</p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback {
/**
diff --git a/core/java/android/text/CharSequenceCharacterIterator.java b/core/java/android/text/CharSequenceCharacterIterator.java
index 9b07d29..1599be8 100644
--- a/core/java/android/text/CharSequenceCharacterIterator.java
+++ b/core/java/android/text/CharSequenceCharacterIterator.java
@@ -24,6 +24,7 @@
* An implementation of {@link java.text.CharacterIterator} that iterates over a given CharSequence.
* {@hide}
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class CharSequenceCharacterIterator implements CharacterIterator {
private final int mBeginIndex, mEndIndex;
private int mIndex;
diff --git a/core/java/android/text/ClipboardManager.java b/core/java/android/text/ClipboardManager.java
index d030910..41990f0 100644
--- a/core/java/android/text/ClipboardManager.java
+++ b/core/java/android/text/ClipboardManager.java
@@ -21,6 +21,7 @@
* {@link android.content.ClipboardManager} for the modern API.
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class ClipboardManager {
/**
* Returns the text on the clipboard. It will eventually be possible
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 6b1aef7..3b66ce0 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -53,6 +53,7 @@
* {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
* Canvas.drawText()} directly.</p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DynamicLayout extends Layout {
private static final int PRIORITY = 128;
private static final int BLOCK_MINIMUM_CHARACTER_LENGTH = 400;
diff --git a/core/java/android/text/Editable.java b/core/java/android/text/Editable.java
index a942f6c..53d819f 100644
--- a/core/java/android/text/Editable.java
+++ b/core/java/android/text/Editable.java
@@ -22,6 +22,7 @@
* to immutable text like Strings). If you make a {@link DynamicLayout}
* of an Editable, the layout will be reflowed as the text is changed.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface Editable
extends CharSequence, GetChars, Spannable, Appendable
{
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index cf0e3c2..28c37c0 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -23,6 +23,7 @@
* An utility class for Emoji.
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Emoji {
public static int COMBINING_ENCLOSING_KEYCAP = 0x20E3;
diff --git a/core/java/android/text/EmojiConsistency.java b/core/java/android/text/EmojiConsistency.java
index dfaa217..9823305 100644
--- a/core/java/android/text/EmojiConsistency.java
+++ b/core/java/android/text/EmojiConsistency.java
@@ -48,6 +48,7 @@
* </ol>
* </p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class EmojiConsistency {
/* Cannot construct */
private EmojiConsistency() { }
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 783f3b7..5a4d3a8 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -55,6 +55,7 @@
*/
@SystemApi
@TestApi
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class FontConfig implements Parcelable {
private final @NonNull List<FontFamily> mFamilies;
private final @NonNull List<Alias> mAliases;
diff --git a/core/java/android/text/GetChars.java b/core/java/android/text/GetChars.java
index 348a911..229f543 100644
--- a/core/java/android/text/GetChars.java
+++ b/core/java/android/text/GetChars.java
@@ -21,6 +21,7 @@
* getChars() method like the one in String that is faster than
* calling charAt() multiple times.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface GetChars
extends CharSequence
{
diff --git a/core/java/android/text/GraphemeClusterSegmentFinder.java b/core/java/android/text/GraphemeClusterSegmentFinder.java
index 0f6fdaf..996223d 100644
--- a/core/java/android/text/GraphemeClusterSegmentFinder.java
+++ b/core/java/android/text/GraphemeClusterSegmentFinder.java
@@ -31,6 +31,7 @@
* @see <a href="https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries">Unicode Text
* Segmentation - Grapheme Cluster Boundaries</a>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class GraphemeClusterSegmentFinder extends SegmentFinder {
private static AutoGrowArray.FloatArray sTempAdvances = null;
private final boolean[] mIsGraphemeBreak;
diff --git a/core/java/android/text/GraphicsOperations.java b/core/java/android/text/GraphicsOperations.java
index 6c15446..f7fe805 100644
--- a/core/java/android/text/GraphicsOperations.java
+++ b/core/java/android/text/GraphicsOperations.java
@@ -26,6 +26,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface GraphicsOperations extends CharSequence {
/**
* Just like {@link Canvas#drawText}.
diff --git a/core/java/android/text/Highlights.java b/core/java/android/text/Highlights.java
index 693dbcf..217a38b 100644
--- a/core/java/android/text/Highlights.java
+++ b/core/java/android/text/Highlights.java
@@ -30,6 +30,7 @@
/**
* A class that represents of the highlight of the text.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Highlights {
private final List<Pair<Paint, int[]>> mHighlights;
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index a42eece..d412071 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -17,13 +17,13 @@
package android.text;
import android.app.ActivityThread;
-import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
+import android.ravenwood.annotation.RavenwoodReplace;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan;
@@ -65,6 +65,7 @@
* This class processes HTML strings into displayable styled text.
* Not all HTML tags are supported.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Html {
/**
* Retrieves images for HTML <img> tags.
@@ -506,6 +507,15 @@
out.append("</p>\n");
}
+ @RavenwoodReplace(blockedBy = ActivityThread.class)
+ private static float getDisplayMetricsDensity() {
+ return ActivityThread.currentApplication().getResources().getDisplayMetrics().density;
+ }
+
+ private static float getDisplayMetricsDensity$ravenwood() {
+ return Resources.getSystem().getDisplayMetrics().density;
+ }
+
private static void withinParagraph(StringBuilder out, Spanned text, int start, int end) {
int next;
for (int i = start; i < end; i = next) {
@@ -559,8 +569,7 @@
AbsoluteSizeSpan s = ((AbsoluteSizeSpan) style[j]);
float sizeDip = s.getSize();
if (!s.getDip()) {
- Application application = ActivityThread.currentApplication();
- sizeDip /= application.getResources().getDisplayMetrics().density;
+ sizeDip /= getDisplayMetricsDensity();
}
// px in CSS is the equivalance of dip in Android
@@ -669,6 +678,7 @@
}
}
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
class HtmlToSpannedConverter implements ContentHandler {
private static final float[] HEADING_SIZES = {
@@ -843,6 +853,16 @@
}
}
+ @RavenwoodReplace(blockedBy = ActivityThread.class)
+ private static int getFontWeightAdjustment() {
+ return ActivityThread.currentApplication().getResources()
+ .getConfiguration().fontWeightAdjustment;
+ }
+
+ private static int getFontWeightAdjustment$ravenwood() {
+ return Resources.getSystem().getConfiguration().fontWeightAdjustment;
+ }
+
private void handleEndTag(String tag) {
if (tag.equalsIgnoreCase("br")) {
handleBr(mSpannableStringBuilder);
@@ -858,17 +878,11 @@
} else if (tag.equalsIgnoreCase("span")) {
endCssStyle(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("strong")) {
- Application application = ActivityThread.currentApplication();
- int fontWeightAdjustment =
- application.getResources().getConfiguration().fontWeightAdjustment;
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD,
- fontWeightAdjustment));
+ getFontWeightAdjustment()));
} else if (tag.equalsIgnoreCase("b")) {
- Application application = ActivityThread.currentApplication();
- int fontWeightAdjustment =
- application.getResources().getConfiguration().fontWeightAdjustment;
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD,
- fontWeightAdjustment));
+ getFontWeightAdjustment()));
} else if (tag.equalsIgnoreCase("em")) {
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
} else if (tag.equalsIgnoreCase("cite")) {
@@ -1036,11 +1050,8 @@
// Their ranges should not include the newlines at the end
Heading h = getLast(text, Heading.class);
if (h != null) {
- Application application = ActivityThread.currentApplication();
- int fontWeightAdjustment =
- application.getResources().getConfiguration().fontWeightAdjustment;
setSpanFromMark(text, h, new RelativeSizeSpan(HEADING_SIZES[h.mLevel]),
- new StyleSpan(Typeface.BOLD, fontWeightAdjustment));
+ new StyleSpan(Typeface.BOLD, getFontWeightAdjustment()));
}
endBlockElement(text);
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index 6f0628a..7f9a8a1 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -21,6 +21,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Hyphenator {
private Hyphenator() {}
diff --git a/core/java/android/text/InputFilter.java b/core/java/android/text/InputFilter.java
index 96e7bd0..ed5de03e 100644
--- a/core/java/android/text/InputFilter.java
+++ b/core/java/android/text/InputFilter.java
@@ -27,6 +27,7 @@
* InputFilters can be attached to {@link Editable}s to constrain the
* changes that can be made to them.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface InputFilter
{
/**
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index 4ebecb7..03c9c02 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -44,6 +44,7 @@
* TYPE_DATETIME_VARIATION_TIME
* </dl>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface InputType {
/**
* Mask of bits that determine the overall class
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2fa5613..44c3f9a 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -69,6 +69,7 @@
* which will be updated as the text changes.
* For text that will not change, use a {@link StaticLayout}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class Layout {
// These should match the constants in framework/base/libs/hwui/hwui/DrawTextFunctor.h
@@ -1071,13 +1072,27 @@
var newBackground = determineContrastingBackgroundColor(index);
var hasBgColorChanged = newBackground != bgPaint.getColor();
- if (lineNum != mLastLineNum || hasBgColorChanged) {
- // Skip processing if the character is a space or a tap to avoid
- // rendering an abrupt, empty rectangle.
- if (Character.isWhitespace(mText.charAt(index))) {
- return;
- }
+ // Skip processing if the character is a space or a tap to avoid
+ // rendering an abrupt, empty rectangle.
+ if (TextLine.isLineEndSpace(mText.charAt(index))) {
+ return;
+ }
+ // To avoid highlighting emoji sequences, we use Extended_Pictgraphs as a
+ // heuristic. Highlighting is skipped based on code points, not glyph type
+ // (text vs. color), so emojis with default text presentation are
+ // intentionally not highlighted (numeric representation with emoji
+ // presentation are manually excluded). Although we process ZWJ and
+ // variation selectors within emoji sequences, they should not affect
+ // highlighting due to their zero-width nature.
+ var codePoint = Character.codePointAt(mText, index);
+ var isEmoji = Character.isEmojiComponent(codePoint)
+ || Character.isExtendedPictographic(codePoint);
+ if (isEmoji && !isStandardNumber(index)) {
+ return;
+ }
+
+ if (lineNum != mLastLineNum || hasBgColorChanged) {
// Draw what we have so far, then reset the rect and update its color
drawRect();
mLineBackground.set(left, top, right, bottom);
@@ -1096,6 +1111,16 @@
drawRect();
}
+ private boolean isStandardNumber(int index) {
+ var codePoint = Character.codePointAt(mText, index);
+ var isNumberSignOrAsterisk = (codePoint >= '0' && codePoint <= '9')
+ || codePoint == '#' || codePoint == '*';
+ var isColoredGlyph = index + 1 < mText.length()
+ && Character.codePointAt(mText, index + 1) == 0xFE0F;
+
+ return isNumberSignOrAsterisk && !isColoredGlyph;
+ }
+
private void drawRect() {
if (!mLineBackground.isEmpty()) {
mLineBackground.inset(-padding, -padding);
@@ -4626,6 +4651,16 @@
* Callback for {@link #forEachCharacterBounds(int, int, int, int, CharacterBoundsListener)}
*/
private interface CharacterBoundsListener {
+ /**
+ * Called for each character with its bounds.
+ *
+ * @param index the index of the character
+ * @param lineNum the line number of the character
+ * @param left the left edge of the character
+ * @param top the top edge of the character
+ * @param right the right edge of the character
+ * @param bottom the bottom edge of the character
+ */
void onCharacterBounds(int index, int lineNum, float left, float top, float right,
float bottom);
diff --git a/core/java/android/text/LoginFilter.java b/core/java/android/text/LoginFilter.java
index 0e4eec44..94f196f 100644
--- a/core/java/android/text/LoginFilter.java
+++ b/core/java/android/text/LoginFilter.java
@@ -23,6 +23,7 @@
* handle non-BMP characters.
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class LoginFilter implements InputFilter {
private boolean mAppendInvalid; // whether to append or ignore invalid characters
/**
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index 31a2263..b2e4459 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -68,6 +68,7 @@
* @hide
*/
@TestApi
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class MeasuredParagraph {
private static final char OBJECT_REPLACEMENT_CHARACTER = '\uFFFC';
diff --git a/core/java/android/text/NoCopySpan.java b/core/java/android/text/NoCopySpan.java
index e754d76..4cd3d04 100644
--- a/core/java/android/text/NoCopySpan.java
+++ b/core/java/android/text/NoCopySpan.java
@@ -21,6 +21,7 @@
* into a new Spanned when performing a slice or copy operation on the original
* Spanned it was placed in.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface NoCopySpan {
/**
* Convenience equivalent for when you would just want a new Object() for
diff --git a/core/java/android/text/PackedIntVector.java b/core/java/android/text/PackedIntVector.java
index 3e5bf56..11dd0c3 100644
--- a/core/java/android/text/PackedIntVector.java
+++ b/core/java/android/text/PackedIntVector.java
@@ -29,6 +29,7 @@
* @hide
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PackedIntVector {
private final int mColumns;
private int mRows;
diff --git a/core/java/android/text/PackedObjectVector.java b/core/java/android/text/PackedObjectVector.java
index b777e16..beb5ea4 100644
--- a/core/java/android/text/PackedObjectVector.java
+++ b/core/java/android/text/PackedObjectVector.java
@@ -21,6 +21,7 @@
import libcore.util.EmptyArray;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
class PackedObjectVector<E>
{
private int mColumns;
diff --git a/core/java/android/text/ParcelableSpan.java b/core/java/android/text/ParcelableSpan.java
index d7c1a4b..a9a4893 100644
--- a/core/java/android/text/ParcelableSpan.java
+++ b/core/java/android/text/ParcelableSpan.java
@@ -24,6 +24,7 @@
* This can only be used by code in the framework; it is not intended for
* applications to implement their own Parcelable spans.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface ParcelableSpan extends Parcelable {
/**
* Return a special type identifier for this span class.
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index 5f6a9bd..71cacd9 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -75,6 +75,7 @@
* Note that any {@link android.text.NoCopySpan} attached to the original text won't be passed to
* PrecomputedText.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PrecomputedText implements Spannable {
private static final char LINE_FEED = '\n';
diff --git a/core/java/android/text/SegmentFinder.java b/core/java/android/text/SegmentFinder.java
index 047d07a..b7ab0e6 100644
--- a/core/java/android/text/SegmentFinder.java
+++ b/core/java/android/text/SegmentFinder.java
@@ -39,6 +39,7 @@
*
* @see Layout#getRangeForRect(RectF, SegmentFinder, Layout.TextInclusionStrategy)
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class SegmentFinder {
/**
* Return value of previousStartBoundary(int), previousEndBoundary(int), nextStartBoundary(int),
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 711578c..674b473 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -27,6 +27,7 @@
* Utility class for manipulating cursors and selections in CharSequences.
* A cursor is a selection where the start and end are at the same offset.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Selection {
private Selection() { /* cannot be instantiated */ }
diff --git a/core/java/android/text/SpanColors.java b/core/java/android/text/SpanColors.java
index fcd242b..3b6a041 100644
--- a/core/java/android/text/SpanColors.java
+++ b/core/java/android/text/SpanColors.java
@@ -27,6 +27,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SpanColors {
public static final @ColorInt int NO_COLOR_FOUND = Color.TRANSPARENT;
diff --git a/core/java/android/text/SpanSet.java b/core/java/android/text/SpanSet.java
index d464278..4ad8106 100644
--- a/core/java/android/text/SpanSet.java
+++ b/core/java/android/text/SpanSet.java
@@ -31,6 +31,7 @@
* Note that empty spans are ignored by this class.
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SpanSet<E> {
private final Class<? extends E> classType;
diff --git a/core/java/android/text/SpanWatcher.java b/core/java/android/text/SpanWatcher.java
index 01e82c8..31d6320 100644
--- a/core/java/android/text/SpanWatcher.java
+++ b/core/java/android/text/SpanWatcher.java
@@ -21,6 +21,7 @@
* will be called to notify it that other markup objects have been
* added, changed, or removed.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface SpanWatcher extends NoCopySpan {
/**
* This method is called to notify you that the specified object
diff --git a/core/java/android/text/Spannable.java b/core/java/android/text/Spannable.java
index 8315b2a..fac5131 100644
--- a/core/java/android/text/Spannable.java
+++ b/core/java/android/text/Spannable.java
@@ -21,6 +21,7 @@
* attached and detached. Not all Spannable classes have mutable text;
* see {@link Editable} for that.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface Spannable
extends Spanned
{
diff --git a/core/java/android/text/SpannableString.java b/core/java/android/text/SpannableString.java
index afb5df8..ee04a86 100644
--- a/core/java/android/text/SpannableString.java
+++ b/core/java/android/text/SpannableString.java
@@ -21,6 +21,7 @@
* markup objects can be attached and detached.
* For mutable text, see {@link SpannableStringBuilder}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SpannableString
extends SpannableStringInternal
implements CharSequence, GetChars, Spannable
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 0e61eff..f8d7283 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -35,6 +35,7 @@
/**
* This is the class for text whose content and markup can both be changed.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable,
Appendable, GraphicsOperations {
private final static String TAG = "SpannableStringBuilder";
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index f2ab1bb..90d83d5 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -27,6 +27,7 @@
import java.lang.reflect.Array;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
/* package */ abstract class SpannableStringInternal
{
/* package */ SpannableStringInternal(CharSequence source,
diff --git a/core/java/android/text/Spanned.java b/core/java/android/text/Spanned.java
index a0d54c26c..6706ffd 100644
--- a/core/java/android/text/Spanned.java
+++ b/core/java/android/text/Spanned.java
@@ -22,6 +22,7 @@
* see {@link Spannable} for mutable markup and {@link Editable} for
* mutable text.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface Spanned
extends CharSequence
{
diff --git a/core/java/android/text/SpannedString.java b/core/java/android/text/SpannedString.java
index acee3c5..a3f1ee2 100644
--- a/core/java/android/text/SpannedString.java
+++ b/core/java/android/text/SpannedString.java
@@ -22,6 +22,7 @@
* For mutable markup, see {@link SpannableString}; for mutable text,
* see {@link SpannableStringBuilder}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class SpannedString
extends SpannableStringInternal
implements CharSequence, GetChars, Spanned
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index a5d52957..8193cd2 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -55,6 +55,7 @@
* float, float, android.graphics.Paint)
* Canvas.drawText()} directly.</p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class StaticLayout extends Layout {
/*
* The break iteration is done in native code. The protocol for using the native code is as
diff --git a/core/java/android/text/TextDirectionHeuristic.java b/core/java/android/text/TextDirectionHeuristic.java
index 8a4ba42..66cea85 100644
--- a/core/java/android/text/TextDirectionHeuristic.java
+++ b/core/java/android/text/TextDirectionHeuristic.java
@@ -19,6 +19,7 @@
/**
* Interface for objects that use a heuristic for guessing at the paragraph direction by examining text.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface TextDirectionHeuristic {
/**
* Guess if a chars array is in the RTL direction or not.
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index 85260f4..3af8fb7 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -32,6 +32,7 @@
* class.
*
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TextDirectionHeuristics {
/**
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 3015791..091eb60 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -53,6 +53,7 @@
* @hide
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TextLine {
private static final boolean DEBUG = false;
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index 73825b1..ff063f2 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -25,6 +25,7 @@
* TextPaint is an extension of Paint that leaves room for some extra
* data used during text measuring and drawing.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TextPaint extends Paint {
// Special value 0 means no background paint
diff --git a/core/java/android/text/TextShaper.java b/core/java/android/text/TextShaper.java
index 6da0b63..6d17401 100644
--- a/core/java/android/text/TextShaper.java
+++ b/core/java/android/text/TextShaper.java
@@ -169,6 +169,7 @@
* @see TextShaper#shapeText(CharSequence, int, int, TextDirectionHeuristic, TextPaint,
* GlyphsConsumer)
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TextShaper {
private TextShaper() {}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 6dc82c4..042966b 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -34,6 +34,7 @@
import android.icu.util.ULocale;
import android.os.Parcel;
import android.os.Parcelable;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
import android.sysprop.DisplayProperties;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.AccessibilityClickableSpan;
@@ -85,8 +86,7 @@
import java.util.Locale;
import java.util.regex.Pattern;
-@android.ravenwood.annotation.RavenwoodKeepStaticInitializer
-@android.ravenwood.annotation.RavenwoodKeepPartialClass
+@RavenwoodKeepWholeClass
public class TextUtils {
private static final String TAG = "TextUtils";
@@ -147,7 +147,6 @@
private TextUtils() { /* cannot be instantiated */ }
- @android.ravenwood.annotation.RavenwoodKeep
public static void getChars(CharSequence s, int start, int end,
char[] dest, int destoff) {
Class<? extends CharSequence> c = s.getClass();
@@ -166,12 +165,10 @@
}
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int indexOf(CharSequence s, char ch) {
return indexOf(s, ch, 0);
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int indexOf(CharSequence s, char ch, int start) {
Class<? extends CharSequence> c = s.getClass();
@@ -181,7 +178,6 @@
return indexOf(s, ch, start, s.length());
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int indexOf(CharSequence s, char ch, int start, int end) {
Class<? extends CharSequence> c = s.getClass();
@@ -219,12 +215,10 @@
return -1;
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int lastIndexOf(CharSequence s, char ch) {
return lastIndexOf(s, ch, s.length() - 1);
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int lastIndexOf(CharSequence s, char ch, int last) {
Class<? extends CharSequence> c = s.getClass();
@@ -234,7 +228,6 @@
return lastIndexOf(s, ch, 0, last);
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int lastIndexOf(CharSequence s, char ch,
int start, int last) {
if (last < 0)
@@ -280,17 +273,14 @@
return -1;
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int indexOf(CharSequence s, CharSequence needle) {
return indexOf(s, needle, 0, s.length());
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int indexOf(CharSequence s, CharSequence needle, int start) {
return indexOf(s, needle, start, s.length());
}
- @android.ravenwood.annotation.RavenwoodKeep
public static int indexOf(CharSequence s, CharSequence needle,
int start, int end) {
int nlen = needle.length();
@@ -318,7 +308,6 @@
return -1;
}
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean regionMatches(CharSequence one, int toffset,
CharSequence two, int ooffset,
int len) {
@@ -351,7 +340,6 @@
* in that it does not preserve any style runs in the source sequence,
* allowing a more efficient implementation.
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static String substring(CharSequence source, int start, int end) {
if (source instanceof String)
return ((String) source).substring(start, end);
@@ -424,7 +412,6 @@
* calling object.toString(). If tokens is null, a NullPointerException will be thrown. If
* tokens is an empty array, an empty string will be returned.
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static String join(@NonNull CharSequence delimiter, @NonNull Object[] tokens) {
final int length = tokens.length;
if (length == 0) {
@@ -448,7 +435,6 @@
* calling object.toString(). If tokens is null, a NullPointerException will be thrown. If
* tokens is empty, an empty string will be returned.
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static String join(@NonNull CharSequence delimiter, @NonNull Iterable tokens) {
final Iterator<?> it = tokens.iterator();
if (!it.hasNext()) {
@@ -481,7 +467,6 @@
*
* @throws NullPointerException if expression or text is null
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static String[] split(String text, String expression) {
if (text.length() == 0) {
return EmptyArray.STRING;
@@ -507,7 +492,6 @@
*
* @throws NullPointerException if expression or text is null
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static String[] split(String text, Pattern pattern) {
if (text.length() == 0) {
return EmptyArray.STRING;
@@ -545,7 +529,6 @@
* be returned for the empty string after that delimeter. That is, splitting <tt>"a,b,"</tt> on
* comma will return <tt>"a", "b"</tt>, not <tt>"a", "b", ""</tt>.
*/
- @android.ravenwood.annotation.RavenwoodKeepWholeClass
public static class SimpleStringSplitter implements StringSplitter, Iterator<String> {
private String mString;
private char mDelimiter;
@@ -609,31 +592,26 @@
* @param str the string to be examined
* @return true if str is null or zero length
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isEmpty(@Nullable CharSequence str) {
return str == null || str.length() == 0;
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodKeep
public static String nullIfEmpty(@Nullable String str) {
return isEmpty(str) ? null : str;
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodKeep
public static String emptyIfNull(@Nullable String str) {
return str == null ? "" : str;
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodKeep
public static String firstNotEmpty(@Nullable String a, @NonNull String b) {
return !isEmpty(a) ? a : Preconditions.checkStringNotEmpty(b);
}
/** {@hide} */
- @android.ravenwood.annotation.RavenwoodKeep
public static int length(@Nullable String s) {
return s != null ? s.length() : 0;
}
@@ -642,7 +620,6 @@
* @return interned string if it's null.
* @hide
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static String safeIntern(String s) {
return (s != null) ? s.intern() : null;
}
@@ -652,7 +629,6 @@
* spaces and ASCII control characters were trimmed from the start and end,
* as by {@link String#trim}.
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static int getTrimmedLength(CharSequence s) {
int len = s.length();
@@ -677,7 +653,6 @@
* @param b second CharSequence to check
* @return true if a and b are equal
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean equals(@Nullable CharSequence a, @Nullable CharSequence b) {
if (a == b) return true;
int length;
@@ -1713,7 +1688,6 @@
return true;
}
- @android.ravenwood.annotation.RavenwoodKeep
/* package */ static char[] obtain(int len) {
char[] buf;
@@ -1728,7 +1702,6 @@
return buf;
}
- @android.ravenwood.annotation.RavenwoodKeep
/* package */ static void recycle(char[] temp) {
if (temp.length > 1000)
return;
@@ -1743,7 +1716,6 @@
* @param s the string to be encoded
* @return the encoded string
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static String htmlEncode(String s) {
StringBuilder sb = new StringBuilder();
char c;
@@ -1830,7 +1802,6 @@
/**
* Returns whether the given CharSequence contains any printable characters.
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isGraphic(CharSequence str) {
final int len = str.length();
for (int cp, i=0; i<len; i+=Character.charCount(cp)) {
@@ -1857,7 +1828,6 @@
* @deprecated Use {@link #isGraphic(CharSequence)} instead.
*/
@Deprecated
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isGraphic(char c) {
int gc = Character.getType(c);
return gc != Character.CONTROL
@@ -1872,7 +1842,6 @@
/**
* Returns whether the given CharSequence contains only digits.
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isDigitsOnly(CharSequence str) {
final int len = str.length();
for (int cp, i = 0; i < len; i += Character.charCount(cp)) {
@@ -1887,7 +1856,6 @@
/**
* @hide
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isPrintableAscii(final char c) {
final int asciiFirst = 0x20;
final int asciiLast = 0x7E; // included
@@ -1898,7 +1866,6 @@
* @hide
*/
@UnsupportedAppUsage
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isPrintableAsciiOnly(final CharSequence str) {
final int len = str.length();
for (int i = 0; i < len; i++) {
@@ -1950,7 +1917,6 @@
* {@link #CAP_MODE_CHARACTERS}, {@link #CAP_MODE_WORDS}, and
* {@link #CAP_MODE_SENTENCES}.
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static int getCapsMode(CharSequence cs, int off, int reqModes) {
if (off < 0) {
return 0;
@@ -2162,7 +2128,6 @@
*
* Be careful: this code will need to be updated when vertical scripts will be supported
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static int getLayoutDirectionFromLocale(Locale locale) {
return ((locale != null && !locale.equals(Locale.ROOT)
&& ULocale.forLocale(locale).isRightToLeft())
@@ -2197,7 +2162,6 @@
* match the supported grammar described above.
* @hide
*/
- @android.ravenwood.annotation.RavenwoodKeep
public static @NonNull String formatSimple(@NonNull String format, Object... args) {
final StringBuilder sb = new StringBuilder(format);
int j = 0;
@@ -2387,7 +2351,6 @@
}
/** @hide */
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isNewline(int codePoint) {
int type = Character.getType(codePoint);
return type == Character.PARAGRAPH_SEPARATOR || type == Character.LINE_SEPARATOR
@@ -2395,19 +2358,16 @@
}
/** @hide */
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isWhitespace(int codePoint) {
return Character.isWhitespace(codePoint) || codePoint == NBSP_CODE_POINT;
}
/** @hide */
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isWhitespaceExceptNewline(int codePoint) {
return isWhitespace(codePoint) && !isNewline(codePoint);
}
/** @hide */
- @android.ravenwood.annotation.RavenwoodKeep
public static boolean isPunctuation(int codePoint) {
int type = Character.getType(codePoint);
return type == Character.CONNECTOR_PUNCTUATION
diff --git a/core/java/android/text/TextWatcher.java b/core/java/android/text/TextWatcher.java
index a0aef69..5963ca7 100644
--- a/core/java/android/text/TextWatcher.java
+++ b/core/java/android/text/TextWatcher.java
@@ -20,6 +20,7 @@
* When an object of this type is attached to an Editable, its methods will
* be called when the text is changed.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface TextWatcher extends NoCopySpan {
/**
* This method is called to notify you that, within <code>s</code>,
diff --git a/core/java/android/text/WordSegmentFinder.java b/core/java/android/text/WordSegmentFinder.java
index b0a70ea..b8702d7 100644
--- a/core/java/android/text/WordSegmentFinder.java
+++ b/core/java/android/text/WordSegmentFinder.java
@@ -33,6 +33,7 @@
* @see <a href="https://unicode.org/reports/tr29/#Word_Boundaries">Unicode Text Segmentation - Word
* Boundaries</a>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class WordSegmentFinder extends SegmentFinder {
private final CharSequence mText;
private final WordIterator mWordIterator;
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index e6dad27..ef60d30 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -63,6 +63,7 @@
* Note that the non-{@code format} methods in this class are implemented by
* {@code SimpleDateFormat}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DateFormat {
/**
* @deprecated Use a literal {@code '} instead.
diff --git a/core/java/android/text/format/DateIntervalFormat.java b/core/java/android/text/format/DateIntervalFormat.java
index 8dea322..5ec9561 100644
--- a/core/java/android/text/format/DateIntervalFormat.java
+++ b/core/java/android/text/format/DateIntervalFormat.java
@@ -37,6 +37,7 @@
* @hide
*/
@VisibleForTesting(visibility = PACKAGE)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class DateIntervalFormat {
private static final LruCache<String, android.icu.text.DateIntervalFormat> CACHED_FORMATTERS =
diff --git a/core/java/android/text/format/DateTimeFormat.java b/core/java/android/text/format/DateTimeFormat.java
index 064d717..c8dd61d 100644
--- a/core/java/android/text/format/DateTimeFormat.java
+++ b/core/java/android/text/format/DateTimeFormat.java
@@ -29,6 +29,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
class DateTimeFormat {
private static final FormatterCache CACHED_FORMATTERS = new FormatterCache();
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 518a549..12ad764 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -44,6 +44,7 @@
* This class contains various date-related utilities for creating text for things like
* elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DateUtils
{
private static final Object sLock = new Object();
diff --git a/core/java/android/text/format/DateUtilsBridge.java b/core/java/android/text/format/DateUtilsBridge.java
index 92ec9cf..752a8c0 100644
--- a/core/java/android/text/format/DateUtilsBridge.java
+++ b/core/java/android/text/format/DateUtilsBridge.java
@@ -46,6 +46,7 @@
* @hide
*/
@VisibleForTesting(visibility = PACKAGE)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class DateUtilsBridge {
/**
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 7653bdb..e7783dc 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -41,6 +41,7 @@
* Utility class to aid in formatting common values that are not covered
* by the {@link java.util.Formatter} class in {@link java.util}
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class Formatter {
/** {@hide} */
diff --git a/core/java/android/text/format/RelativeDateTimeFormatter.java b/core/java/android/text/format/RelativeDateTimeFormatter.java
index 9096469..6b940f8 100644
--- a/core/java/android/text/format/RelativeDateTimeFormatter.java
+++ b/core/java/android/text/format/RelativeDateTimeFormatter.java
@@ -42,6 +42,7 @@
* @hide
*/
@VisibleForTesting(visibility = PACKAGE)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class RelativeDateTimeFormatter {
public static final long SECOND_IN_MILLIS = 1000;
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index bac7c6c..1beb573 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -53,6 +53,7 @@
* @deprecated Use {@link java.util.GregorianCalendar} instead.
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Time {
private static final String Y_M_D_T_H_M_S_000 = "%Y-%m-%dT%H:%M:%S.000";
private static final String Y_M_D_T_H_M_S_000_Z = "%Y-%m-%dT%H:%M:%S.000Z";
diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java
index e42ad63..dd703d8 100644
--- a/core/java/android/text/format/TimeFormatter.java
+++ b/core/java/android/text/format/TimeFormatter.java
@@ -40,6 +40,7 @@
*
* <p>This class is not thread safe.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
class TimeFormatter {
// An arbitrary value outside the range representable by a char.
private static final int FORCE_LOWER_CASE = -1;
diff --git a/core/java/android/text/format/TimeMigrationUtils.java b/core/java/android/text/format/TimeMigrationUtils.java
index 17bac8d..b2f5024 100644
--- a/core/java/android/text/format/TimeMigrationUtils.java
+++ b/core/java/android/text/format/TimeMigrationUtils.java
@@ -22,6 +22,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TimeMigrationUtils {
private TimeMigrationUtils() {}
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
index 305b056..70dcc52 100644
--- a/core/java/android/text/method/AllCapsTransformationMethod.java
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -33,6 +33,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AllCapsTransformationMethod implements TransformationMethod2 {
private static final String TAG = "AllCapsTransformationMethod";
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 37474e5..6099220 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -30,6 +30,7 @@
* A movement method that provides cursor movement and selection.
* Supports displaying the context menu on DPad Center.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ArrowKeyMovementMethod extends BaseMovementMethod implements MovementMethod {
private static boolean isSelecting(Spannable buffer) {
return ((MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SHIFT_ON) == 1) ||
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index e427908..5ebfd99 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -47,6 +47,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class BaseKeyListener extends MetaKeyKeyListener
implements KeyListener {
/* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
diff --git a/core/java/android/text/method/BaseMovementMethod.java b/core/java/android/text/method/BaseMovementMethod.java
index 7a4b3a0..0c2e52e 100644
--- a/core/java/android/text/method/BaseMovementMethod.java
+++ b/core/java/android/text/method/BaseMovementMethod.java
@@ -27,6 +27,7 @@
/**
* Base classes for movement methods.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BaseMovementMethod implements MovementMethod {
@Override
public boolean canSelectArbitrarily() {
diff --git a/core/java/android/text/method/CharacterPickerDialog.java b/core/java/android/text/method/CharacterPickerDialog.java
index 7d838e0..f084d03 100644
--- a/core/java/android/text/method/CharacterPickerDialog.java
+++ b/core/java/android/text/method/CharacterPickerDialog.java
@@ -38,6 +38,7 @@
/**
* Dialog for choosing accented characters related to a base character.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class CharacterPickerDialog extends Dialog
implements OnItemClickListener, OnClickListener {
private View mView;
diff --git a/core/java/android/text/method/DateKeyListener.java b/core/java/android/text/method/DateKeyListener.java
index 0accbf6..acf1822 100644
--- a/core/java/android/text/method/DateKeyListener.java
+++ b/core/java/android/text/method/DateKeyListener.java
@@ -35,6 +35,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DateKeyListener extends NumberKeyListener
{
public int getInputType() {
diff --git a/core/java/android/text/method/DateTimeKeyListener.java b/core/java/android/text/method/DateTimeKeyListener.java
index 1593db5..a46ae45 100644
--- a/core/java/android/text/method/DateTimeKeyListener.java
+++ b/core/java/android/text/method/DateTimeKeyListener.java
@@ -35,6 +35,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DateTimeKeyListener extends NumberKeyListener
{
public int getInputType() {
diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java
index 17abed6..9eea51a 100644
--- a/core/java/android/text/method/DialerKeyListener.java
+++ b/core/java/android/text/method/DialerKeyListener.java
@@ -28,6 +28,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DialerKeyListener extends NumberKeyListener
{
@Override
diff --git a/core/java/android/text/method/DigitsKeyListener.java b/core/java/android/text/method/DigitsKeyListener.java
index d9f2dcf..c97d4af 100644
--- a/core/java/android/text/method/DigitsKeyListener.java
+++ b/core/java/android/text/method/DigitsKeyListener.java
@@ -40,6 +40,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DigitsKeyListener extends NumberKeyListener
{
private char[] mAccepted;
diff --git a/core/java/android/text/method/HideReturnsTransformationMethod.java b/core/java/android/text/method/HideReturnsTransformationMethod.java
index 40ce871..8b93b35 100644
--- a/core/java/android/text/method/HideReturnsTransformationMethod.java
+++ b/core/java/android/text/method/HideReturnsTransformationMethod.java
@@ -24,6 +24,7 @@
* to be hidden by displaying them as zero-width non-breaking space
* characters (\uFEFF).
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class HideReturnsTransformationMethod
extends ReplacementTransformationMethod {
private static char[] ORIGINAL = new char[] { '\r' };
diff --git a/core/java/android/text/method/InsertModeTransformationMethod.java b/core/java/android/text/method/InsertModeTransformationMethod.java
index 6c6576f..ace2d25 100644
--- a/core/java/android/text/method/InsertModeTransformationMethod.java
+++ b/core/java/android/text/method/InsertModeTransformationMethod.java
@@ -58,6 +58,7 @@
* the new transformed text: "hello abc\n\n world", and the highlight range will be [5, 11).
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class InsertModeTransformationMethod implements TransformationMethod, TextWatcher {
/** The start offset of the highlight range in the original text, inclusive. */
private int mStart;
diff --git a/core/java/android/text/method/KeyListener.java b/core/java/android/text/method/KeyListener.java
index ce7054c..447c4d9 100644
--- a/core/java/android/text/method/KeyListener.java
+++ b/core/java/android/text/method/KeyListener.java
@@ -34,6 +34,7 @@
* targetting Jelly Bean or later, and will only deliver it for some
* key presses to applications targetting Ice Cream Sandwich or earlier.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface KeyListener {
/**
* Return the type of text that this key listener is manipulating,
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index 9f4a0ae..484bc1a 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -33,6 +33,7 @@
* A movement method that traverses links in the text buffer and scrolls if necessary.
* Supports clicking on links with DPad Center or Enter.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class LinkMovementMethod extends ScrollingMovementMethod {
private static final int CLICK = 1;
private static final int UP = 2;
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index d1d7c96..7c9c2f1 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -71,6 +71,7 @@
* }
* </code>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class MetaKeyKeyListener {
/**
* Flag that indicates that the SHIFT key is on.
diff --git a/core/java/android/text/method/MovementMethod.java b/core/java/android/text/method/MovementMethod.java
index f6fe575..5ea439d 100644
--- a/core/java/android/text/method/MovementMethod.java
+++ b/core/java/android/text/method/MovementMethod.java
@@ -32,6 +32,7 @@
* directly by applications.
* </p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface MovementMethod {
public void initialize(TextView widget, Spannable text);
public boolean onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event);
diff --git a/core/java/android/text/method/MultiTapKeyListener.java b/core/java/android/text/method/MultiTapKeyListener.java
index 5770482..022853ab 100644
--- a/core/java/android/text/method/MultiTapKeyListener.java
+++ b/core/java/android/text/method/MultiTapKeyListener.java
@@ -36,6 +36,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class MultiTapKeyListener extends BaseKeyListener
implements SpanWatcher {
private static MultiTapKeyListener[] sInstance =
diff --git a/core/java/android/text/method/NumberKeyListener.java b/core/java/android/text/method/NumberKeyListener.java
index 2b038dd..e32ccd4 100644
--- a/core/java/android/text/method/NumberKeyListener.java
+++ b/core/java/android/text/method/NumberKeyListener.java
@@ -39,6 +39,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class NumberKeyListener extends BaseKeyListener
implements InputFilter
{
diff --git a/core/java/android/text/method/OffsetMapping.java b/core/java/android/text/method/OffsetMapping.java
index fcf3de6..99613d3 100644
--- a/core/java/android/text/method/OffsetMapping.java
+++ b/core/java/android/text/method/OffsetMapping.java
@@ -27,6 +27,7 @@
* {@link TransformationMethod} that alters the text length.
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface OffsetMapping {
/**
* The mapping strategy for a character offset.
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
index 53553be..4a61d9a 100644
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ b/core/java/android/text/method/PasswordTransformationMethod.java
@@ -33,6 +33,7 @@
import java.lang.ref.WeakReference;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PasswordTransformationMethod
implements TransformationMethod, TextWatcher
{
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index c43864d..27c58ea 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -37,6 +37,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class QwertyKeyListener extends BaseKeyListener {
private static QwertyKeyListener[] sInstance =
new QwertyKeyListener[Capitalize.values().length * 2];
diff --git a/core/java/android/text/method/ReplacementTransformationMethod.java b/core/java/android/text/method/ReplacementTransformationMethod.java
index d6f879a..05899d7 100644
--- a/core/java/android/text/method/ReplacementTransformationMethod.java
+++ b/core/java/android/text/method/ReplacementTransformationMethod.java
@@ -30,6 +30,7 @@
* array to be replaced by the corresponding characters in the
* {@link #getReplacement} array.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class ReplacementTransformationMethod
implements TransformationMethod
{
diff --git a/core/java/android/text/method/ScrollingMovementMethod.java b/core/java/android/text/method/ScrollingMovementMethod.java
index 4f422cb..2e0eda9 100644
--- a/core/java/android/text/method/ScrollingMovementMethod.java
+++ b/core/java/android/text/method/ScrollingMovementMethod.java
@@ -25,6 +25,7 @@
/**
* A movement method that interprets movement keys by scrolling the text buffer.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ScrollingMovementMethod extends BaseMovementMethod implements MovementMethod {
@Override
protected boolean left(TextView widget, Spannable buffer) {
diff --git a/core/java/android/text/method/SingleLineTransformationMethod.java b/core/java/android/text/method/SingleLineTransformationMethod.java
index 818526a..d6eff86 100644
--- a/core/java/android/text/method/SingleLineTransformationMethod.java
+++ b/core/java/android/text/method/SingleLineTransformationMethod.java
@@ -21,6 +21,7 @@
* displayed as spaces instead of causing line breaks, and causes
* carriage return characters (\r) to have no appearance.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SingleLineTransformationMethod
extends ReplacementTransformationMethod {
private static char[] ORIGINAL = new char[] { '\n', '\r' };
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
index 2eb917b..1b0ae61 100644
--- a/core/java/android/text/method/TextKeyListener.java
+++ b/core/java/android/text/method/TextKeyListener.java
@@ -43,6 +43,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TextKeyListener extends BaseKeyListener implements SpanWatcher {
private static TextKeyListener[] sInstance =
new TextKeyListener[Capitalize.values().length * 2];
diff --git a/core/java/android/text/method/TimeKeyListener.java b/core/java/android/text/method/TimeKeyListener.java
index f11f400..337611c 100644
--- a/core/java/android/text/method/TimeKeyListener.java
+++ b/core/java/android/text/method/TimeKeyListener.java
@@ -35,6 +35,7 @@
* with hardware keyboards. Software input methods have no obligation to trigger
* the methods in this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TimeKeyListener extends NumberKeyListener
{
public int getInputType() {
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index 44811cb..85aadba 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -25,6 +25,7 @@
import android.view.ViewConfiguration;
import android.widget.TextView;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Touch {
private Touch() { }
diff --git a/core/java/android/text/method/TransformationMethod.java b/core/java/android/text/method/TransformationMethod.java
index 8f3b334..5246baa 100644
--- a/core/java/android/text/method/TransformationMethod.java
+++ b/core/java/android/text/method/TransformationMethod.java
@@ -24,6 +24,7 @@
* characters of passwords with dots, or keeping the newline characters
* from causing line breaks in single-line text fields.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface TransformationMethod
{
/**
diff --git a/core/java/android/text/method/TransformationMethod2.java b/core/java/android/text/method/TransformationMethod2.java
index 8d5ec24..6e0feb419 100644
--- a/core/java/android/text/method/TransformationMethod2.java
+++ b/core/java/android/text/method/TransformationMethod2.java
@@ -23,6 +23,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface TransformationMethod2 extends TransformationMethod {
/**
* Relax the contract of TransformationMethod to allow length changes,
diff --git a/core/java/android/text/method/TranslationTransformationMethod.java b/core/java/android/text/method/TranslationTransformationMethod.java
index 43d186e..8f43d3d 100644
--- a/core/java/android/text/method/TranslationTransformationMethod.java
+++ b/core/java/android/text/method/TranslationTransformationMethod.java
@@ -33,6 +33,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TranslationTransformationMethod implements TransformationMethod2 {
private static final String TAG = "TranslationTransformationMethod";
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 2956f84..d57fa9b 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -37,6 +37,7 @@
* Also provides methods to determine word boundaries.
* {@hide}
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class WordIterator implements Selection.PositionIterator {
// Size of the window for the word iterator, should be greater than the longest word's length
private static final int WINDOW_WIDTH = 50;
diff --git a/core/java/android/text/style/AbsoluteSizeSpan.java b/core/java/android/text/style/AbsoluteSizeSpan.java
index 6d4f05a..1bc5d71 100644
--- a/core/java/android/text/style/AbsoluteSizeSpan.java
+++ b/core/java/android/text/style/AbsoluteSizeSpan.java
@@ -32,6 +32,7 @@
* <img src="{@docRoot}reference/android/images/text/style/absolutesizespan.png" />
* <figcaption>Text with text size updated.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
private final int mSize;
diff --git a/core/java/android/text/style/AccessibilityClickableSpan.java b/core/java/android/text/style/AccessibilityClickableSpan.java
index ee8d156..5741f2a 100644
--- a/core/java/android/text/style/AccessibilityClickableSpan.java
+++ b/core/java/android/text/style/AccessibilityClickableSpan.java
@@ -43,6 +43,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AccessibilityClickableSpan extends ClickableSpan
implements ParcelableSpan {
// The id of the span this one replaces
diff --git a/core/java/android/text/style/AccessibilityReplacementSpan.java b/core/java/android/text/style/AccessibilityReplacementSpan.java
index e4fc147..af3a324 100644
--- a/core/java/android/text/style/AccessibilityReplacementSpan.java
+++ b/core/java/android/text/style/AccessibilityReplacementSpan.java
@@ -31,6 +31,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AccessibilityReplacementSpan extends ReplacementSpan
implements ParcelableSpan {
diff --git a/core/java/android/text/style/AccessibilityURLSpan.java b/core/java/android/text/style/AccessibilityURLSpan.java
index e280bdf..1fb76e7 100644
--- a/core/java/android/text/style/AccessibilityURLSpan.java
+++ b/core/java/android/text/style/AccessibilityURLSpan.java
@@ -27,6 +27,7 @@
* @hide
*/
@SuppressWarnings("ParcelableCreator")
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AccessibilityURLSpan extends URLSpan implements Parcelable {
final AccessibilityClickableSpan mAccessibilityClickableSpan;
diff --git a/core/java/android/text/style/AlignmentSpan.java b/core/java/android/text/style/AlignmentSpan.java
index 31db78a..53cbd63 100644
--- a/core/java/android/text/style/AlignmentSpan.java
+++ b/core/java/android/text/style/AlignmentSpan.java
@@ -25,6 +25,7 @@
/**
* Span that allows defining the alignment of text at the paragraph level.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface AlignmentSpan extends ParagraphStyle {
/**
diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java
index 13647d9..bb04d0ff 100644
--- a/core/java/android/text/style/BackgroundColorSpan.java
+++ b/core/java/android/text/style/BackgroundColorSpan.java
@@ -34,6 +34,7 @@
* <img src="{@docRoot}reference/android/images/text/style/backgroundcolorspan.png" />
* <figcaption>Set a background color for the text.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BackgroundColorSpan extends CharacterStyle
implements UpdateAppearance, ParcelableSpan {
diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java
index f70e6c5..24ae6e2 100644
--- a/core/java/android/text/style/BulletSpan.java
+++ b/core/java/android/text/style/BulletSpan.java
@@ -63,6 +63,7 @@
* <img src="{@docRoot}reference/android/images/text/style/custombulletspan.png" />
* <figcaption>Customized BulletSpan.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BulletSpan implements LeadingMarginSpan, ParcelableSpan {
// Bullet is slightly bigger to avoid aliasing artifacts on mdpi devices.
private static final int STANDARD_BULLET_RADIUS = 4;
diff --git a/core/java/android/text/style/CharacterStyle.java b/core/java/android/text/style/CharacterStyle.java
index 5b95f1a..2ea05e6 100644
--- a/core/java/android/text/style/CharacterStyle.java
+++ b/core/java/android/text/style/CharacterStyle.java
@@ -23,6 +23,7 @@
* class. Most extend its subclass {@link MetricAffectingSpan}, but simple
* ones may just implement {@link UpdateAppearance}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class CharacterStyle {
public abstract void updateDrawState(TextPaint tp);
diff --git a/core/java/android/text/style/ClickableSpan.java b/core/java/android/text/style/ClickableSpan.java
index 238da55..9e35d75 100644
--- a/core/java/android/text/style/ClickableSpan.java
+++ b/core/java/android/text/style/ClickableSpan.java
@@ -36,6 +36,7 @@
* <img src="{@docRoot}reference/android/images/text/style/clickablespan.png" />
* <figcaption>Text with <code>ClickableSpan</code>.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
private static int sIdCounter = 0;
diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java
index 5c97426..337c49f 100644
--- a/core/java/android/text/style/ForegroundColorSpan.java
+++ b/core/java/android/text/style/ForegroundColorSpan.java
@@ -34,6 +34,7 @@
* <img src="{@docRoot}reference/android/images/text/style/foregroundcolorspan.png" />
* <figcaption>Set a text color.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ForegroundColorSpan extends CharacterStyle
implements UpdateAppearance, ParcelableSpan {
diff --git a/core/java/android/text/style/IconMarginSpan.java b/core/java/android/text/style/IconMarginSpan.java
index a6c5139..cc946e9 100644
--- a/core/java/android/text/style/IconMarginSpan.java
+++ b/core/java/android/text/style/IconMarginSpan.java
@@ -44,6 +44,7 @@
* @see DrawableMarginSpan for working with a {@link android.graphics.drawable.Drawable} instead of
* a {@link Bitmap}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class IconMarginSpan implements LeadingMarginSpan, LineHeightSpan {
@NonNull
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index 5bd2d60..60c4578 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -32,6 +32,7 @@
* LeadingMarginSpans should be attached from the first character to the last
* character of a single paragraph.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface LeadingMarginSpan
extends ParagraphStyle
{
diff --git a/core/java/android/text/style/LineBackgroundSpan.java b/core/java/android/text/style/LineBackgroundSpan.java
index 7cb9147..c2d38ce 100644
--- a/core/java/android/text/style/LineBackgroundSpan.java
+++ b/core/java/android/text/style/LineBackgroundSpan.java
@@ -28,6 +28,7 @@
/**
* Used to change the background of lines where the span is attached to.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface LineBackgroundSpan extends ParagraphStyle
{
/**
diff --git a/core/java/android/text/style/LineBreakConfigSpan.java b/core/java/android/text/style/LineBreakConfigSpan.java
index eeb6383..1af1eed 100644
--- a/core/java/android/text/style/LineBreakConfigSpan.java
+++ b/core/java/android/text/style/LineBreakConfigSpan.java
@@ -31,6 +31,7 @@
* LineBreakSpan for changing line break style of the specific region of the text.
*/
@FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class LineBreakConfigSpan implements ParcelableSpan {
private final LineBreakConfig mLineBreakConfig;
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index ae565d1..71e8932 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -30,6 +30,7 @@
/**
* The classes that affect the line height of paragraph should implement this interface.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan {
/**
* Classes that implement this should define how the height is being calculated.
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
index 489ceea..be5525a 100644
--- a/core/java/android/text/style/LocaleSpan.java
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -32,6 +32,7 @@
/**
* Changes the {@link Locale} of the text to which the span is attached.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
@NonNull
private final LocaleList mLocales;
diff --git a/core/java/android/text/style/MaskFilterSpan.java b/core/java/android/text/style/MaskFilterSpan.java
index 587d1b4..44db012 100644
--- a/core/java/android/text/style/MaskFilterSpan.java
+++ b/core/java/android/text/style/MaskFilterSpan.java
@@ -30,6 +30,7 @@
* <img src="{@docRoot}reference/android/images/text/style/maskfilterspan.png" />
* <figcaption>Text blurred with the <code>MaskFilterSpan</code>.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class MaskFilterSpan extends CharacterStyle implements UpdateAppearance {
private MaskFilter mFilter;
diff --git a/core/java/android/text/style/MetricAffectingSpan.java b/core/java/android/text/style/MetricAffectingSpan.java
index 61b7947..f30fdc1 100644
--- a/core/java/android/text/style/MetricAffectingSpan.java
+++ b/core/java/android/text/style/MetricAffectingSpan.java
@@ -23,6 +23,7 @@
* The classes that affect character-level text formatting in a way that
* changes the width or height of characters extend this class.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class MetricAffectingSpan
extends CharacterStyle
implements UpdateLayout {
diff --git a/core/java/android/text/style/NoWritingToolsSpan.java b/core/java/android/text/style/NoWritingToolsSpan.java
index 90f85aa..c7dfcfa 100644
--- a/core/java/android/text/style/NoWritingToolsSpan.java
+++ b/core/java/android/text/style/NoWritingToolsSpan.java
@@ -32,6 +32,7 @@
* tools should only rewrite the user input text, and not modify the quoted text.
*/
@FlaggedApi(FLAG_WRITING_TOOLS)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class NoWritingToolsSpan implements ParcelableSpan {
/**
diff --git a/core/java/android/text/style/ParagraphStyle.java b/core/java/android/text/style/ParagraphStyle.java
index 423156e..27c1e26 100644
--- a/core/java/android/text/style/ParagraphStyle.java
+++ b/core/java/android/text/style/ParagraphStyle.java
@@ -20,6 +20,7 @@
* The classes that affect paragraph-level text formatting implement
* this interface.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface ParagraphStyle
{
diff --git a/core/java/android/text/style/QuoteSpan.java b/core/java/android/text/style/QuoteSpan.java
index 393ede6..99c9574 100644
--- a/core/java/android/text/style/QuoteSpan.java
+++ b/core/java/android/text/style/QuoteSpan.java
@@ -57,6 +57,7 @@
* <img src="{@docRoot}reference/android/images/text/style/customquotespan.png" />
* <figcaption>Customized <code>QuoteSpan</code>.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
/**
* Default stripe width in pixels.
diff --git a/core/java/android/text/style/RasterizerSpan.java b/core/java/android/text/style/RasterizerSpan.java
index f0be50a..cf8599c 100644
--- a/core/java/android/text/style/RasterizerSpan.java
+++ b/core/java/android/text/style/RasterizerSpan.java
@@ -22,6 +22,7 @@
/**
* @removed Rasterizer is not supported for hw-accerlerated and PDF rendering
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class RasterizerSpan extends CharacterStyle implements UpdateAppearance {
private Rasterizer mRasterizer;
diff --git a/core/java/android/text/style/RelativeSizeSpan.java b/core/java/android/text/style/RelativeSizeSpan.java
index 5c91b20..38d5d38 100644
--- a/core/java/android/text/style/RelativeSizeSpan.java
+++ b/core/java/android/text/style/RelativeSizeSpan.java
@@ -34,6 +34,7 @@
* <img src="{@docRoot}reference/android/images/text/style/relativesizespan.png" />
* <figcaption>Text increased by 50% with <code>RelativeSizeSpan</code>.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
private final float mProportion;
diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java
index 9430fd3..a6fe1fe 100644
--- a/core/java/android/text/style/ReplacementSpan.java
+++ b/core/java/android/text/style/ReplacementSpan.java
@@ -23,6 +23,7 @@
import android.graphics.Paint;
import android.text.TextPaint;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class ReplacementSpan extends MetricAffectingSpan {
private CharSequence mContentDescription = null;
diff --git a/core/java/android/text/style/ScaleXSpan.java b/core/java/android/text/style/ScaleXSpan.java
index d022b07..009973e 100644
--- a/core/java/android/text/style/ScaleXSpan.java
+++ b/core/java/android/text/style/ScaleXSpan.java
@@ -36,6 +36,7 @@
* <img src="{@docRoot}reference/android/images/text/style/scalexspan.png" />
* <figcaption>Text scaled by 100% with <code>ScaleXSpan</code>.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ScaleXSpan extends MetricAffectingSpan implements ParcelableSpan {
private final float mProportion;
diff --git a/core/java/android/text/style/SpanUtils.java b/core/java/android/text/style/SpanUtils.java
index 6b4bd1a..21a96cd 100644
--- a/core/java/android/text/style/SpanUtils.java
+++ b/core/java/android/text/style/SpanUtils.java
@@ -30,6 +30,7 @@
/**
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SpanUtils {
private SpanUtils() {} // Do not instantiate
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
index e8ec3c6..39cd279 100644
--- a/core/java/android/text/style/SpellCheckSpan.java
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -28,6 +28,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SpellCheckSpan implements ParcelableSpan {
private boolean mSpellCheckInProgress;
diff --git a/core/java/android/text/style/StrikethroughSpan.java b/core/java/android/text/style/StrikethroughSpan.java
index 65ee347..3654870 100644
--- a/core/java/android/text/style/StrikethroughSpan.java
+++ b/core/java/android/text/style/StrikethroughSpan.java
@@ -32,6 +32,7 @@
* <img src="{@docRoot}reference/android/images/text/style/strikethroughspan.png" />
* <figcaption>Strikethrough text.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class StrikethroughSpan extends CharacterStyle
implements UpdateAppearance, ParcelableSpan {
diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java
index 378682b..c01e134 100644
--- a/core/java/android/text/style/StyleSpan.java
+++ b/core/java/android/text/style/StyleSpan.java
@@ -44,6 +44,7 @@
* <img src="{@docRoot}reference/android/images/text/style/stylespan.png" />
* <figcaption>Text styled bold and italic with the <code>StyleSpan</code>.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
private final int mStyle;
diff --git a/core/java/android/text/style/SubscriptSpan.java b/core/java/android/text/style/SubscriptSpan.java
index 729a9ad..54c765d 100644
--- a/core/java/android/text/style/SubscriptSpan.java
+++ b/core/java/android/text/style/SubscriptSpan.java
@@ -37,6 +37,7 @@
* Note: Since the span affects the position of the text, if the text is on the last line of a
* TextView, it may appear cut.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SubscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
/**
diff --git a/core/java/android/text/style/SuggestionRangeSpan.java b/core/java/android/text/style/SuggestionRangeSpan.java
index 1eee99a..640fae4 100644
--- a/core/java/android/text/style/SuggestionRangeSpan.java
+++ b/core/java/android/text/style/SuggestionRangeSpan.java
@@ -27,6 +27,7 @@
* A SuggestionRangeSpan is used to show which part of an EditText is affected by a suggestion
* popup window.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpan {
private int mBackgroundColor;
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 0cf96f6..d819062 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -48,6 +48,7 @@
*
* @see TextView#isSuggestionsEnabled()
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
private static final String TAG = "SuggestionSpan";
diff --git a/core/java/android/text/style/SuperscriptSpan.java b/core/java/android/text/style/SuperscriptSpan.java
index 5610223..d3b339c 100644
--- a/core/java/android/text/style/SuperscriptSpan.java
+++ b/core/java/android/text/style/SuperscriptSpan.java
@@ -35,6 +35,7 @@
* TextView, it may appear cut. This can be avoided by decreasing the text size with an {@link
* AbsoluteSizeSpan}
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SuperscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
/**
* Creates a {@link SuperscriptSpan}.
diff --git a/core/java/android/text/style/TabStopSpan.java b/core/java/android/text/style/TabStopSpan.java
index 8128475..e6733a2 100644
--- a/core/java/android/text/style/TabStopSpan.java
+++ b/core/java/android/text/style/TabStopSpan.java
@@ -24,6 +24,7 @@
* the leading margin of the line. <code>TabStopSpan</code> will only affect the first tab
* encountered on the first line of the text.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface TabStopSpan extends ParagraphStyle {
/**
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index 245a9db..7ede349 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -58,6 +58,7 @@
* @attr ref android.R.styleable#TextAppearance_fontVariationSettings
*
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
private final String mFamilyName;
private final int mStyle;
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index e0d4ec1..6d776d1 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -42,6 +42,7 @@
* The inner classes are there for convenience and provide builders for each
* TtsSpan type.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TtsSpan implements ParcelableSpan {
private final String mType;
private final PersistableBundle mArgs;
diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java
index bdfc772..86f7f76 100644
--- a/core/java/android/text/style/TypefaceSpan.java
+++ b/core/java/android/text/style/TypefaceSpan.java
@@ -50,6 +50,7 @@
* <figcaption>Text with <code>TypefaceSpan</code>s constructed based on a font from resource and
* from a font family.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
@Nullable
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
index 9969d29..f06627d 100644
--- a/core/java/android/text/style/URLSpan.java
+++ b/core/java/android/text/style/URLSpan.java
@@ -41,6 +41,7 @@
* <img src="{@docRoot}reference/android/images/text/style/urlspan.png" />
* <figcaption>Text with <code>URLSpan</code>.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class URLSpan extends ClickableSpan implements ParcelableSpan {
private final String mURL;
diff --git a/core/java/android/text/style/UnderlineSpan.java b/core/java/android/text/style/UnderlineSpan.java
index 075e70b..b3bb142 100644
--- a/core/java/android/text/style/UnderlineSpan.java
+++ b/core/java/android/text/style/UnderlineSpan.java
@@ -32,6 +32,7 @@
* <img src="{@docRoot}reference/android/images/text/style/underlinespan.png" />
* <figcaption>Underlined text.</figcaption>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class UnderlineSpan extends CharacterStyle
implements UpdateAppearance, ParcelableSpan {
diff --git a/core/java/android/text/style/UpdateAppearance.java b/core/java/android/text/style/UpdateAppearance.java
index 7112347..7b0a6d3 100644
--- a/core/java/android/text/style/UpdateAppearance.java
+++ b/core/java/android/text/style/UpdateAppearance.java
@@ -22,5 +22,6 @@
* that if the class also impacts size or other metrics, it should instead
* implement {@link UpdateLayout}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface UpdateAppearance {
}
diff --git a/core/java/android/text/style/UpdateLayout.java b/core/java/android/text/style/UpdateLayout.java
index 591075e..5af4141 100644
--- a/core/java/android/text/style/UpdateLayout.java
+++ b/core/java/android/text/style/UpdateLayout.java
@@ -22,4 +22,5 @@
* this interface. This interface also includes {@link UpdateAppearance}
* since such a change implicitly also impacts the appearance.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface UpdateLayout extends UpdateAppearance { }
diff --git a/core/java/android/text/style/WrapTogetherSpan.java b/core/java/android/text/style/WrapTogetherSpan.java
index 11721a8..cf74c1b 100644
--- a/core/java/android/text/style/WrapTogetherSpan.java
+++ b/core/java/android/text/style/WrapTogetherSpan.java
@@ -16,6 +16,7 @@
package android.text.style;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface WrapTogetherSpan
extends ParagraphStyle
{
diff --git a/core/java/android/text/util/Rfc822Token.java b/core/java/android/text/util/Rfc822Token.java
index 2f207db..d6e987b 100644
--- a/core/java/android/text/util/Rfc822Token.java
+++ b/core/java/android/text/util/Rfc822Token.java
@@ -22,6 +22,7 @@
* This class stores an RFC 822-like name, address, and comment,
* and provides methods to convert them to quoted strings.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Rfc822Token {
@Nullable
private String mName, mAddress, mComment;
diff --git a/core/java/android/text/util/Rfc822Tokenizer.java b/core/java/android/text/util/Rfc822Tokenizer.java
index 68334e4..8a9252a 100644
--- a/core/java/android/text/util/Rfc822Tokenizer.java
+++ b/core/java/android/text/util/Rfc822Tokenizer.java
@@ -27,6 +27,7 @@
* a string of addresses (such as might be typed into such a field)
* into a series of Rfc822Tokens.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Rfc822Tokenizer implements MultiAutoCompleteTextView.Tokenizer {
/**
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index a4c3ed9..5910434d 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -260,9 +260,11 @@
Certificate[][] nonstreamingCerts = null;
int v3BlockId = APK_SIGNATURE_SCHEME_DEFAULT;
- // If V4 contains additional signing blocks then we need to always run v2/v3 verifier
- // to figure out which block they use.
- if (verifyFull || signingInfos.signingInfoBlocks.length > 0) {
+ // We need to always run v2/v3 verifier to figure out which block they use so we can
+ // return the past signers as well as the current one - the rotation chain is important
+ // for many callers who verify the signature origin as well as the apk integrity.
+ if (android.content.pm.Flags.alwaysLoadPastCertsV4()
+ || verifyFull || signingInfos.signingInfoBlocks.length > 0) {
try {
// v4 is an add-on and requires v2 or v3 signature to validate against its
// certificate and digest
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index f315f55..3229fc6 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -50,6 +50,7 @@
import android.view.accessibility.AccessibilityRequestPreparer;
import android.view.accessibility.Flags;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import android.view.accessibility.IWindowSurfaceInfoCallback;
import android.window.ScreenCapture;
import com.android.internal.R;
@@ -631,6 +632,25 @@
}
}
+ /**
+ * Provide info for taking a screenshot of this app window.
+ */
+ public void getWindowSurfaceInfoClientThread(IWindowSurfaceInfoCallback callback) {
+ Message message = PooledLambda.obtainMessage(
+ AccessibilityInteractionController::getWindowSurfaceInfoUiThread,
+ this, callback);
+ mHandler.sendMessage(message);
+ }
+
+ private void getWindowSurfaceInfoUiThread(IWindowSurfaceInfoCallback callback) {
+ try {
+ callback.provideWindowSurfaceInfo(mViewRootImpl.getWindowFlags(), Process.myUid(),
+ mViewRootImpl.getSurfaceControl());
+ } catch (RemoteException re) {
+ // ignore - the other side will time out
+ }
+ }
+
public void findFocusClientThread(long accessibilityNodeId, int focusType,
Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 231aa68..3f45e29 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -108,6 +108,7 @@
private final String mOwnerPackageName;
private final Resources mResources;
private DisplayAdjustments mDisplayAdjustments;
+ private boolean mRefreshRateChangesRegistered;
@UnsupportedAppUsage
private DisplayInfo mDisplayInfo; // never null
@@ -1217,6 +1218,10 @@
*/
public float getRefreshRate() {
synchronized (mLock) {
+ if (!mRefreshRateChangesRegistered) {
+ DisplayManagerGlobal.getInstance().registerForRefreshRateChanges();
+ mRefreshRateChangesRegistered = true;
+ }
updateDisplayInfoLocked();
return mDisplayInfo.getRefreshRate();
}
@@ -1601,7 +1606,7 @@
.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
| DisplayManagerGlobal
.INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
- ActivityThread.currentPackageName());
+ ActivityThread.currentPackageName(), /* isEventFilterImplicit */ true);
}
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index c174fbe..3659e78 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1299,7 +1299,11 @@
// Handle the pending show request for other insets types since the IME insets
// has being requested hidden.
handlePendingControlRequest(statsToken);
- getImeSourceConsumer().removeSurface();
+ if (!Flags.refactorInsetsController()) {
+ // the surface can't be removed until the end of the animation. This is handled by
+ // IMMS after the window was requested to be hidden.
+ getImeSourceConsumer().removeSurface();
+ }
}
applyAnimation(typesReady, false /* show */, fromIme, false /* skipsCallbacks */,
statsToken);
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index df680c0..fe868e1 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -223,8 +223,14 @@
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (notificationsRedesignTemplates()) {
- mTopLineTranslation = measureCenterTranslation(mTopLineView);
- mExpandButtonTranslation = measureCenterTranslation(mExpandButton);
+ // TODO: b/378660052 - These should never be null in practice, consider using
+ // requireViewById() in the onFinishInflate.
+ if (mTopLineView != null) {
+ mTopLineTranslation = measureCenterTranslation(mTopLineView);
+ }
+ if (mExpandButton != null) {
+ mExpandButtonTranslation = measureCenterTranslation(mExpandButton);
+ }
}
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0903d22..c4347f0 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -3080,6 +3080,21 @@
}
/**
+ * Changes the default ApplyToken.
+ *
+ * ApplyToken is used to determine the order in which Transactions are applied.
+ * Transactions applied with the same ApplyToken will be applied in the order
+ * they were queued in SurfaceFlinger. Transactions are sent via binder so the
+ * caller should be aware of the order in which binder calls are executed in
+ * SurfaceFlinger. This along with the ApplyToken will determine the order
+ * in which Transactions are applied. Transactions with different apply tokens
+ * will be applied in arbitrary order regardless of when they were queued in
+ * SurfaceFlinger.
+ *
+ * Caller must keep track of the previous ApplyToken if they want to restore it.
+ *
+ * Note each buffer producer should have its own ApplyToken in order to ensure
+ * that Transactions are not delayed by Transactions from other buffer producers.
*
* @hide
*/
@@ -3088,6 +3103,7 @@
}
/**
+ * Returns the default ApplyToken.
*
* @hide
*/
@@ -3096,8 +3112,10 @@
}
/**
- * Apply the transaction, clearing it's state, and making it usable
+ * Apply the transaction, clearing its state, and making it usable
* as a new transaction.
+ *
+ * This method will also increment the transaction ID for debugging purposes.
*/
public void apply() {
apply(/*sync*/ false);
@@ -3116,7 +3134,7 @@
/**
- * Clear the transaction object, without applying it.
+ * Clear the transaction object, without applying it. The transction ID is preserved.
*
* @hide
*/
@@ -3375,6 +3393,9 @@
* If two siblings share the same Z order the ordering is undefined. Surfaces
* with a negative Z will be placed below the parent surface.
*
+ * Calling setLayer after setRelativeLayer will reset the relative layer
+ * in the same transaction.
+ *
* @param sc The SurfaceControl to set the Z order on
* @param z The Z-order
* @return This Transaction.
@@ -3392,6 +3413,22 @@
}
/**
+ * Set the Z-order for a given SurfaceControl, relative to the specified SurfaceControl.
+ * The SurfaceControl with a negative z will be placed below the relativeTo
+ * SurfaceControl and the SurfaceControl with a positive z will be placed above the
+ * relativeTo SurfaceControl.
+ *
+ * Calling setLayer will reset the relative layer. Calling setRelativeLayer after setLayer
+ * will override the setLayer call.
+ *
+ * If a layer is set to be relative to a layer that is destroyed, the layer will be
+ * offscreen until setLayer is called or setRelativeLayer is called with a valid
+ * SurfaceControl.
+ *
+ * @param sc The SurfaceControl to set the Z order on
+ * @param relativeTo The SurfaceControl to set the Z order relative to
+ * @param z The Z-order
+ * @return This Transaction.
* @hide
*/
public Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo, int z) {
@@ -3405,6 +3442,9 @@
}
/**
+ * The hint from the buffer producer as to what portion of the layer is
+ * transparent.
+ *
* @hide
*/
public Transaction setTransparentRegionHint(SurfaceControl sc, Region transparentRegion) {
@@ -3438,6 +3478,10 @@
}
/**
+ * Sets the input channel for a given SurfaceControl. The position and order of the
+ * SurfaceControl in conjunction with the touchable region in the InputWindowHandle
+ * determines the hit region.
+ *
* @hide
*/
public Transaction setInputWindowInfo(SurfaceControl sc, InputWindowHandle handle) {
@@ -3549,6 +3593,8 @@
* surface. If no crop is specified and the surface has no buffer, the surface bounds is
* only constrained by the size of its parent bounds.
*
+ * To unset the crop, pass in an invalid Rect (0, 0, -1, -1)
+ *
* @param sc SurfaceControl to set crop of.
* @param crop Bounds of the crop to apply.
* @hide
@@ -3578,6 +3624,8 @@
* surface. If no crop is specified and the surface has no buffer, the surface bounds is
* only constrained by the size of its parent bounds.
*
+ * To unset the crop, pass in an invalid Rect (0, 0, -1, -1)
+ *
* @param sc SurfaceControl to set crop of.
* @param crop Bounds of the crop to apply.
* @return this This transaction for chaining
@@ -3625,6 +3673,8 @@
* surface. If no crop is specified and the surface has no buffer, the surface bounds is
* only constrained by the size of its parent bounds.
*
+ * To unset the crop, pass in an invalid Rect (0, 0, -1, -1)
+ *
* @param sc SurfaceControl to set crop of.
* @param crop Bounds of the crop to apply.
* @return this This transaction for chaining
@@ -3643,7 +3693,12 @@
}
/**
- * Sets the corner radius of a {@link SurfaceControl}.
+ * Sets the corner radius of a {@link SurfaceControl}. This corner radius is applied to the
+ * SurfaceControl and its children. The API expects a crop to be set on the SurfaceControl
+ * to ensure that the corner radius is applied to the correct region. If the crop does not
+ * intersect with the SurfaceControl's visible content, the corner radius will not be
+ * applied.
+ *
* @param sc SurfaceControl
* @param cornerRadius Corner radius in pixels.
* @return Itself.
@@ -3753,6 +3808,9 @@
}
/**
+ * Associates a layer with a display. The layer will be drawn on the display with the
+ * specified layer stack. If the layer is not a root layer, this call has no effect.
+ *
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O)
@@ -3791,6 +3849,7 @@
/**
* Fills the surface with the specified color.
+ *
* @param color A float array with three values to represent r, g, b in range [0..1]. An
* invalid color will remove the color fill.
* @hide
@@ -3809,8 +3868,9 @@
/**
* Removes color fill.
- * @hide
- */
+ *
+ * @hide
+ */
public Transaction unsetColor(SurfaceControl sc) {
checkPreconditions(sc);
if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
@@ -3898,6 +3958,8 @@
}
/**
+ * Sets the surface to render contents of the display to.
+ *
* @hide
*/
public Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
@@ -3916,6 +3978,9 @@
}
/**
+ * Sets the layer stack of the display.
+ *
+ * All layers with the same layer stack will be drawn on this display.
* @hide
*/
public Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index dd32947..b98f4db 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.flags.Flags.FLAG_DEPRECATE_SURFACE_VIEW_Z_ORDER_APIS;
import static android.view.flags.Flags.FLAG_SURFACE_VIEW_GET_SURFACE_PACKAGE;
import static android.view.flags.Flags.FLAG_SURFACE_VIEW_SET_COMPOSITION_ORDER;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
@@ -812,7 +813,12 @@
* window is attached to the window manager.
*
* <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
+ *
+ * @deprecated Use {@link #setCompositionOrder(int)} instead. It provides more
+ * control over the Z ordering behavior.
*/
+ @Deprecated
+ @FlaggedApi(FLAG_DEPRECATE_SURFACE_VIEW_Z_ORDER_APIS)
public void setZOrderMediaOverlay(boolean isMediaOverlay) {
mRequestedSubLayer = isMediaOverlay
? APPLICATION_MEDIA_OVERLAY_SUBLAYER : APPLICATION_MEDIA_SUBLAYER;
@@ -834,7 +840,12 @@
* <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
*
* @param onTop Whether to show the surface on top of this view's window.
+ *
+ * @deprecated Use {@link #setCompositionOrder(int)} instead. It provides more
+ * control over the Z ordering behavior.
*/
+ @Deprecated
+ @FlaggedApi(FLAG_DEPRECATE_SURFACE_VIEW_Z_ORDER_APIS)
public void setZOrderOnTop(boolean onTop) {
// In R and above we allow dynamic layer changes.
final boolean allowDynamicChange = getContext().getApplicationInfo().targetSdkVersion
@@ -866,7 +877,11 @@
* @return Whether the Z ordering changed.
*
* @hide
+ *
+ * @deprecated Use {@link #setCompositionOrder(int)} instead. It provides more control
+ * over the Z ordering behavior.
*/
+ @Deprecated
public boolean setZOrderedOnTop(boolean onTop, boolean allowDynamicChange) {
final int subLayer;
if (onTop) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0866e0d..c048d79 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -66,6 +66,7 @@
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
import static com.android.window.flags.Flags.FLAG_DELEGATE_UNHANDLED_DRAGS;
import static com.android.window.flags.Flags.FLAG_SUPPORTS_DRAG_ASSISTANT_TO_MULTIWINDOW;
+import static com.android.window.flags.Flags.reduceChangedExclusionRectsMsgs;
import static java.lang.Math.max;
@@ -247,6 +248,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
@@ -12888,15 +12890,20 @@
if (rects.isEmpty() && mListenerInfo == null) return;
final ListenerInfo info = getListenerInfo();
+ final boolean rectsChanged = !reduceChangedExclusionRectsMsgs()
+ || !Objects.equals(info.mSystemGestureExclusionRects, rects);
if (info.mSystemGestureExclusionRects != null) {
- info.mSystemGestureExclusionRects.clear();
- info.mSystemGestureExclusionRects.addAll(rects);
+ if (rectsChanged) {
+ info.mSystemGestureExclusionRects.clear();
+ info.mSystemGestureExclusionRects.addAll(rects);
+ }
} else {
info.mSystemGestureExclusionRects = new ArrayList<>(rects);
}
-
- updatePositionUpdateListener();
- postUpdate(this::updateSystemGestureExclusionRects);
+ if (rectsChanged) {
+ updatePositionUpdateListener();
+ postUpdate(this::updateSystemGestureExclusionRects);
+ }
}
private void updatePositionUpdateListener() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6b6147a..9498407 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -136,6 +136,7 @@
import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay;
import static com.android.window.flags.Flags.enableWindowContextResourcesUpdateOnConfigChange;
import static com.android.window.flags.Flags.predictiveBackSwipeEdgeNoneApi;
+import static com.android.window.flags.Flags.reduceChangedExclusionRectsMsgs;
import static com.android.window.flags.Flags.setScPropertiesInClient;
import android.Manifest;
@@ -152,8 +153,6 @@
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
-import android.app.UiModeManager;
-import android.app.UiModeManager.ForceInvertStateChangeListener;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.app.servertransaction.WindowStateTransactionItem;
@@ -169,6 +168,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.database.ContentObserver;
import android.graphics.BLASTBufferQueue;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -214,6 +214,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.Vibrator;
+import android.provider.Settings;
import android.sysprop.DisplayProperties;
import android.sysprop.ViewProperties;
import android.text.TextUtils;
@@ -254,6 +255,7 @@
import android.view.accessibility.IAccessibilityEmbeddedConnection;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import android.view.accessibility.IWindowSurfaceInfoCallback;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.autofill.AutofillManager;
@@ -468,8 +470,10 @@
private CompatOnBackInvokedCallback mCompatOnBackInvokedCallback;
@Nullable
- private ForceInvertStateChangeListener mForceInvertStateChangeListener;
+ private ContentObserver mForceInvertObserver;
+ private static final int INVALID_VALUE = Integer.MIN_VALUE;
+ private int mForceInvertEnabled = INVALID_VALUE;
/**
* Callback for notifying about global configuration changes.
*/
@@ -551,8 +555,6 @@
@UiContext
public final Context mContext;
- private UiModeManager mUiModeManager;
-
@UnsupportedAppUsage
final IWindowSession mWindowSession;
@NonNull Display mDisplay;
@@ -1254,7 +1256,6 @@
public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
WindowLayout windowLayout) {
mContext = context;
- mUiModeManager = context.getSystemService(UiModeManager.class);
mWindowSession = session;
mWindowLayout = windowLayout;
mDisplay = display;
@@ -1803,6 +1804,23 @@
}
}
+ private boolean isForceInvertEnabled() {
+ if (mForceInvertEnabled == INVALID_VALUE) {
+ reloadForceInvertEnabled();
+ }
+ return mForceInvertEnabled == 1;
+ }
+
+ private void reloadForceInvertEnabled() {
+ if (forceInvertColor()) {
+ mForceInvertEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+ /* def= */ 0,
+ UserHandle.myUserId());
+ }
+ }
+
/**
* Register any kind of listeners if setView was success.
*/
@@ -1834,11 +1852,21 @@
mBasePackageName);
if (forceInvertColor()) {
- if (mForceInvertStateChangeListener == null) {
- mForceInvertStateChangeListener =
- forceInvertState -> updateForceDarkMode();
- mUiModeManager.addForceInvertStateChangeListener(mExecutor,
- mForceInvertStateChangeListener);
+ if (mForceInvertObserver == null) {
+ mForceInvertObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ reloadForceInvertEnabled();
+ updateForceDarkMode();
+ }
+ };
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED
+ ),
+ false,
+ mForceInvertObserver,
+ UserHandle.myUserId());
}
}
}
@@ -1856,10 +1884,9 @@
.unregisterDisplayListener(mDisplayListener);
if (forceInvertColor()) {
- if (mForceInvertStateChangeListener != null) {
- mUiModeManager.removeForceInvertStateChangeListener(
- mForceInvertStateChangeListener);
- mForceInvertStateChangeListener = null;
+ if (mForceInvertObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(mForceInvertObserver);
+ mForceInvertObserver = null;
}
}
@@ -2046,25 +2073,21 @@
return getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
}
- /**
- * Determines the type of force dark to apply, considering force inversion, system night mode,
- * and app-specific settings (including developer opt-outs).
- *
- * @return A {@link ForceDarkType.ForceDarkTypeDef} constant indicating the force dark type.
- */
+ /** Returns true if force dark should be enabled according to various settings */
@VisibleForTesting
public @ForceDarkType.ForceDarkTypeDef int determineForceDarkType() {
if (forceInvertColor()) {
// Force invert ignores all developer opt-outs.
// We also ignore dark theme, since the app developer can override the user's preference
- // for dark mode in configuration.uiMode. Instead, we assume that both force invert and
- // the system's dark theme are enabled.
- if (mUiModeManager.getForceInvertState() == UiModeManager.FORCE_INVERT_TYPE_DARK) {
+ // for dark mode in configuration.uiMode. Instead, we assume that the force invert
+ // setting will be enabled at the same time dark theme is in the Settings app.
+ if (isForceInvertEnabled()) {
return ForceDarkType.FORCE_INVERT_COLOR_DARK;
}
}
boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
+
if (useAutoDark) {
boolean forceDarkAllowedDefault =
SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false);
@@ -6052,8 +6075,12 @@
}
void updateSystemGestureExclusionRectsForView(View view) {
+ boolean msgInQueue = reduceChangedExclusionRectsMsgs()
+ && mGestureExclusionTracker.isWaitingForComputeChanges();
mGestureExclusionTracker.updateRectsForView(view);
- mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED);
+ if (!msgInQueue) {
+ mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED);
+ }
}
void systemGestureExclusionChanged() {
@@ -6097,8 +6124,12 @@
* the root's view hierarchy.
*/
public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ boolean msgInQueue = reduceChangedExclusionRectsMsgs()
+ && mGestureExclusionTracker.isWaitingForComputeChanges();
mGestureExclusionTracker.setRootRects(rects);
- mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED);
+ if (!msgInQueue) {
+ mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED);
+ }
}
/**
@@ -12285,6 +12316,15 @@
}
}
+ @Override
+ public void getWindowSurfaceInfo(IWindowSurfaceInfoCallback callback) {
+ ViewRootImpl viewRootImpl = mViewRootImpl.get();
+ if (viewRootImpl != null && viewRootImpl.mView != null) {
+ viewRootImpl.getAccessibilityInteractionController()
+ .getWindowSurfaceInfoClientThread(callback);
+ }
+ }
+
public void attachAccessibilityOverlayToWindow(
SurfaceControl sc,
int interactionId,
diff --git a/core/java/android/view/ViewRootRectTracker.java b/core/java/android/view/ViewRootRectTracker.java
index 152729b..0bef325 100644
--- a/core/java/android/view/ViewRootRectTracker.java
+++ b/core/java/android/view/ViewRootRectTracker.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.graphics.Rect;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import java.lang.ref.WeakReference;
@@ -32,8 +33,10 @@
/**
* Abstract class to track a collection of rects reported by the views under the same
* {@link ViewRootImpl}.
+ * @hide
*/
-class ViewRootRectTracker {
+@VisibleForTesting
+public class ViewRootRectTracker {
private final Function<View, List<Rect>> mRectCollector;
private boolean mViewsChanged = false;
private boolean mRootRectsChanged = false;
@@ -41,11 +44,18 @@
private List<ViewInfo> mViewInfos = new ArrayList<>();
private List<Rect> mRects = Collections.emptyList();
+ // Keeps track of whether updateRectsForView has been called but there was no subsequent call
+ // on computeChanges yet. Since updateRectsForView is called when sending a message and
+ // computeChanges when it is received, this tracks whether such message is in the queue already
+ private boolean mWaitingForComputeChanges = false;
+
/**
* @param rectCollector given a view returns a list of the rects of interest for this
* ViewRootRectTracker
+ * @hide
*/
- ViewRootRectTracker(Function<View, List<Rect>> rectCollector) {
+ @VisibleForTesting
+ public ViewRootRectTracker(Function<View, List<Rect>> rectCollector) {
mRectCollector = rectCollector;
}
@@ -70,6 +80,7 @@
mViewInfos.add(new ViewInfo(view));
mViewsChanged = true;
}
+ mWaitingForComputeChanges = true;
}
/**
@@ -92,6 +103,7 @@
* @return {@code true} if there were changes, {@code false} otherwise.
*/
public boolean computeChanges() {
+ mWaitingForComputeChanges = false;
boolean changed = mRootRectsChanged;
final Iterator<ViewInfo> i = mViewInfos.iterator();
final List<Rect> rects = new ArrayList<>(mRootRects);
@@ -121,6 +133,10 @@
return false;
}
+ public boolean isWaitingForComputeChanges() {
+ return mWaitingForComputeChanges;
+ }
+
/**
* Returns a List of all Rects from all visible Views in the global (root) coordinate system.
* This list is only updated when calling {@link #computeChanges()} or
@@ -140,6 +156,7 @@
Preconditions.checkNotNull(rects, "rects must not be null");
mRootRects = rects;
mRootRectsChanged = true;
+ mWaitingForComputeChanges = true;
}
@NonNull
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index e3ea6b22..a952967 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -1290,7 +1290,8 @@
int newTop = Math.max(0, insets.top - top);
int newRight = Math.max(0, insets.right - right);
int newBottom = Math.max(0, insets.bottom - bottom);
- if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
+ if (newLeft == insets.left && newTop == insets.top
+ && newRight == insets.right && newBottom == insets.bottom) {
return insets;
}
return Insets.of(newLeft, newTop, newRight, newBottom);
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index a43acf9..ca024fd 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -23,6 +23,7 @@
import android.view.SurfaceControl;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import android.view.accessibility.IWindowSurfaceInfoCallback;
import android.window.ScreenCapture;
/**
@@ -67,5 +68,7 @@
in ScreenCapture.ScreenCaptureListener listener,
IAccessibilityInteractionConnectionCallback callback);
+ void getWindowSurfaceInfo(IWindowSurfaceInfoCallback callback);
+
void attachAccessibilityOverlayToWindow(in SurfaceControl sc, int interactionId, in IAccessibilityInteractionConnectionCallback callback);
}
diff --git a/core/java/android/view/accessibility/IWindowSurfaceInfoCallback.aidl b/core/java/android/view/accessibility/IWindowSurfaceInfoCallback.aidl
new file mode 100644
index 0000000..370f185
--- /dev/null
+++ b/core/java/android/view/accessibility/IWindowSurfaceInfoCallback.aidl
@@ -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 android.view.accessibility;
+
+import android.view.SurfaceControl;
+
+/**
+ * Callback for an app to provide AbstractAccessibilityServiceConnection with window and surface
+ * information necessary for system_server to take a screenshot of the app window.
+ * @hide
+ */
+oneway interface IWindowSurfaceInfoCallback {
+
+ /**
+ * Provide info from ViewRootImpl for taking a screenshot of this app window.
+ *
+ * @param windowFlags the window flags of ViewRootImpl
+ * @param processUid the process (kernel) uid, NOT the user ID, required for
+ SurfaceFlinger screenshots
+ * @param surfaceControl the surface of ViewRootImpl
+ */
+ @RequiresNoPermission
+ void provideWindowSurfaceInfo(int windowFlags, int processUid,
+ in SurfaceControl surfaceControl);
+}
diff --git a/core/java/android/view/flags/view_flags.aconfig b/core/java/android/view/flags/view_flags.aconfig
index f6fdec9..d06f885 100644
--- a/core/java/android/view/flags/view_flags.aconfig
+++ b/core/java/android/view/flags/view_flags.aconfig
@@ -129,6 +129,14 @@
}
flag {
+ name: "deprecate_surface_view_z_order_apis"
+ namespace: "window_surfaces"
+ description: "Deprecate SurfaceView z order control APIs."
+ bug: "341021569"
+ is_fixed_read_only: true
+}
+
+flag {
name: "use_refactored_round_scrollbar"
namespace: "wear_frameworks"
description: "Use refactored round scrollbar."
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 56f0415..0b34600 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -466,6 +466,26 @@
private static final long USE_ASYNC_SHOW_HIDE_METHOD = 352594277L; // This is a bug id.
/**
+ * Always return {@code true} when {@link #hideSoftInputFromWindow(IBinder, int)} and
+ * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver, int, ImeTracker.Token)} is
+ * called.
+ * <p>
+ * Apps can incorrectly rely on the return value of
+ * {@link #hideSoftInputFromWindow(IBinder, int)} to guess whether the IME was hidden.
+ * However, it was never a guarantee that the IME will actually hide.
+ * Therefore, it was recommended using the {@link View.OnApplyWindowInsetsListener}.
+ * <p>
+ * Starting Android {@link Build.VERSION_CODES.BAKLAVA}, the return value will always be
+ * true, independent from whether the request was eventually sent to system server or not.
+ * Apps that need to know when the IME visibility changes should use
+ * {@link View.OnApplyWindowInsetsListener}. For apps that target earlier releases, it
+ * returns an estimate ({@code true} if the IME was showing before).
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.BAKLAVA)
+ private static final long ALWAYS_RETURN_TRUE_HIDE_SOFT_INPUT_FROM_WINDOW = 395521150L; // bug id
+
+ /**
* If {@code true}, avoid calling the
* {@link com.android.server.inputmethod.InputMethodManagerService InputMethodManagerService}
* by skipping the call to {@link IInputMethodManager#startInputOrWindowGainedFocus}
@@ -512,6 +532,7 @@
final H mH;
// Our generic input connection if the current target does not have its own.
+ @NonNull
private final RemoteInputConnectionImpl mFallbackInputConnection;
private final int mDisplayId;
@@ -2531,9 +2552,14 @@
*
* @param windowToken The token of the window that is making the request,
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
- * @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note:
- * this does not return result of the request. For result use {@link ResultReceiver} in
- * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)} instead.
+ * @return <p>For apps targeting Android {@link Build.VERSION_CODES.BAKLAVA}, onwards, it
+ * will always return {@code true}. To see when the IME is hidden, use
+ * {@link View.OnApplyWindowInsetsListener} and verify the provided {@link WindowInsets} for
+ * the visibility of IME.
+ *
+ * <p>For apps targeting releases before Android Baklava: returns {@code true} if a request
+ * was sent to system_server, {@code false} otherwise. Note: This does not return the result
+ * of that request (i.e. whether the IME was actually hidden).
*/
public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags) {
return hideSoftInputFromWindow(windowToken, flags, null);
@@ -2563,7 +2589,8 @@
* {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
* {@link #RESULT_HIDDEN}.
* @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note:
- * this does not return result of the request. For result use {@param resultReceiver} instead.
+ * This does not return the result of that request (i.e. whether the IME was actually hidden).
+ * For result use {@param resultReceiver} instead.
*
* @deprecated The {@link ResultReceiver} is not a reliable way of determining whether the
* Input Method is actually shown or hidden. If result is needed, use
@@ -2603,7 +2630,10 @@
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
ImeTracker.forLatency().onHideFailed(statsToken,
ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
- return false;
+ // with the flag enabled and targeting Android Baklava onwards, the return value
+ // should be always true (was false before).
+ return Flags.refactorInsetsController() && CompatChanges.isChangeEnabled(
+ ALWAYS_RETURN_TRUE_HIDE_SOFT_INPUT_FROM_WINDOW);
}
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
@@ -2618,15 +2648,18 @@
// under us. The current input has been closed before (from checkFocus).
ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);
- return false;
+ // with the flag enabled and targeting Android Baklava onwards, the
+ // return value should be always true (was false before).
+ return Flags.refactorInsetsController() && CompatChanges.isChangeEnabled(
+ ALWAYS_RETURN_TRUE_HIDE_SOFT_INPUT_FROM_WINDOW);
}
ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_VIEW_HANDLER_AVAILABLE);
+ final boolean imeReqVisible =
+ (viewRootImpl.getInsetsController().getRequestedVisibleTypes()
+ & WindowInsets.Type.ime()) != 0;
if (resultReceiver != null) {
- final boolean imeReqVisible =
- (viewRootImpl.getInsetsController().getRequestedVisibleTypes()
- & WindowInsets.Type.ime()) != 0;
resultReceiver.send(
!imeReqVisible ? InputMethodManager.RESULT_UNCHANGED_HIDDEN
: InputMethodManager.RESULT_HIDDEN, null);
@@ -2642,8 +2675,16 @@
viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime(),
false /* fromIme */, statsToken);
}
+ if (!CompatChanges.isChangeEnabled(
+ ALWAYS_RETURN_TRUE_HIDE_SOFT_INPUT_FROM_WINDOW)) {
+ // if the IME was not visible before, the additional hide won't change
+ // anything.
+ return imeReqVisible;
+ }
}
- return true;
+ // Targeting Android Baklava onwards, this method will always return true.
+ return CompatChanges.isChangeEnabled(
+ ALWAYS_RETURN_TRUE_HIDE_SOFT_INPUT_FROM_WINDOW);
} else {
return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken,
statsToken, flags, resultReceiver, reason, mAsyncShowHideMethodEnabled);
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index 23da747..4aeedbb 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -101,9 +101,16 @@
ENABLE_HANDLE_INPUT_FIX(Flags::enableHandleInputFix, true),
ENABLE_HOLD_TO_DRAG_APP_HANDLE(Flags::enableHoldToDragAppHandle, true),
ENABLE_MINIMIZE_BUTTON(Flags::enableMinimizeButton, true),
+ ENABLE_MODALS_FULLSCREEN_WITH_PERMISSIONS(Flags::enableModalsFullscreenWithPermission, false),
+ ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS(
+ Flags::enableOpaqueBackgroundForTransparentWindows, false),
+ ENABLE_QUICKSWITCH_DESKTOP_SPLIT_BUGFIX(Flags::enableQuickswitchDesktopSplitBugfix, true),
ENABLE_RESIZING_METRICS(Flags::enableResizingMetrics, true),
ENABLE_RESTORE_TO_PREVIOUS_SIZE_FROM_DESKTOP_IMMERSIVE(
Flags::enableRestoreToPreviousSizeFromDesktopImmersive, true),
+ ENABLE_START_LAUNCH_TRANSITION_FROM_TASKBAR_BUGFIX(
+ Flags::enableStartLaunchTransitionFromTaskbarBugfix, true),
+ ENABLE_TASKBAR_OVERFLOW(Flags::enableTaskbarOverflow, false),
ENABLE_TASK_RESIZING_KEYBOARD_SHORTCUTS(Flags::enableTaskResizingKeyboardShortcuts, true),
ENABLE_TASK_STACK_OBSERVER_IN_SHELL(Flags::enableTaskStackObserverInShell, true),
ENABLE_THEMED_APP_HEADERS(Flags::enableThemedAppHeaders, true),
@@ -116,6 +123,8 @@
ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS(
Flags::enableWindowingTransitionHandlersObservers, false),
EXCLUDE_CAPTION_FROM_APP_BOUNDS(Flags::excludeCaptionFromAppBounds, false),
+ IGNORE_ASPECT_RATIO_RESTRICTIONS_FOR_RESIZEABLE_FREEFORM_ACTIVITIES(
+ Flags::ignoreAspectRatioRestrictionsForResizeableFreeformActivities, true),
INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC(
Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true)
// go/keep-sorted end
diff --git a/core/java/android/window/TransitionFilter.java b/core/java/android/window/TransitionFilter.java
index 61fc622..d8d2011 100644
--- a/core/java/android/window/TransitionFilter.java
+++ b/core/java/android/window/TransitionFilter.java
@@ -31,8 +31,6 @@
import android.os.Parcelable;
import android.view.WindowManager;
-import com.android.window.flags.Flags;
-
/**
* A parcelable filter that can be used for rerouting transitions to a remote. This is a local
* representation so that the transition system doesn't need to make blocking queries over
@@ -261,9 +259,7 @@
// only applies to activity/task
&& (change.getTaskInfo() != null
|| change.getActivityComponent() != null)) {
- final TransitionInfo.AnimationOptions opts =
- Flags.moveAnimationOptionsToChange() ? change.getAnimationOptions()
- : info.getAnimationOptions();
+ final TransitionInfo.AnimationOptions opts = change.getAnimationOptions();
if (opts != null) {
boolean canActuallyOverride = change.getTaskInfo() == null
|| opts.getOverrideTaskTransition();
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 4f34aa3..32175f1 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -57,8 +57,6 @@
import android.view.SurfaceControl;
import android.view.WindowManager;
-import com.android.window.flags.Flags;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -220,10 +218,6 @@
private final ArrayList<Change> mChanges = new ArrayList<>();
private final ArrayList<Root> mRoots = new ArrayList<>();
- // TODO(b/327332488): Clean-up usages after the flag is fully enabled.
- @Deprecated
- private AnimationOptions mOptions;
-
/** This is only a BEST-EFFORT id used for log correlation. DO NOT USE for any real work! */
private int mDebugId = -1;
@@ -238,7 +232,6 @@
mFlags = in.readInt();
in.readTypedList(mChanges, Change.CREATOR);
in.readTypedList(mRoots, Root.CREATOR);
- mOptions = in.readTypedObject(AnimationOptions.CREATOR);
mDebugId = in.readInt();
mTrack = in.readInt();
}
@@ -250,7 +243,6 @@
dest.writeInt(mFlags);
dest.writeTypedList(mChanges);
dest.writeTypedList(mRoots, flags);
- dest.writeTypedObject(mOptions, flags);
dest.writeInt(mDebugId);
dest.writeInt(mTrack);
}
@@ -286,18 +278,6 @@
mRoots.add(other);
}
- /**
- * @deprecated Set {@link AnimationOptions} to change. This method is only used if
- * {@link Flags#FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE} is disabled.
- */
- @Deprecated
- public void setAnimationOptions(@Nullable AnimationOptions options) {
- if (Flags.moveAnimationOptionsToChange()) {
- return;
- }
- mOptions = options;
- }
-
public @TransitionType int getType() {
return mType;
}
@@ -360,16 +340,6 @@
}
/**
- * @deprecated Use {@link Change#getAnimationOptions()} instead. This method is called only
- * if {@link Flags#FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE} is disabled.
- */
- @Deprecated
- @Nullable
- public AnimationOptions getAnimationOptions() {
- return mOptions;
- }
-
- /**
* @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom
* in Z (meaning index 0 is the top-most container).
*/
@@ -455,9 +425,6 @@
StringBuilder sb = new StringBuilder();
sb.append("{id=").append(mDebugId).append(" t=").append(transitTypeToString(mType))
.append(" f=0x").append(Integer.toHexString(mFlags)).append(" trk=").append(mTrack);
- if (mOptions != null) {
- sb.append(" opt=").append(mOptions);
- }
sb.append(" r=[");
for (int i = 0; i < mRoots.size(); ++i) {
if (i > 0) {
@@ -656,8 +623,6 @@
for (int i = 0; i < mRoots.size(); ++i) {
out.mRoots.add(mRoots.get(i).localRemoteCopy());
}
- // Doesn't have any native stuff, so no need for actual copy
- out.mOptions = mOptions;
return out;
}
@@ -860,9 +825,6 @@
* Sets {@link AnimationOptions} to override animation.
*/
public void setAnimationOptions(@Nullable AnimationOptions options) {
- if (!Flags.moveAnimationOptionsToChange()) {
- return;
- }
mAnimationOptions = options;
}
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index b137bb0..f77a366 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -16,6 +16,17 @@
}
flag {
+ name: "enable_modals_fullscreen_with_permission"
+ namespace: "lse_desktop_experience"
+ description: "Uses permissions to understand if modal fullscreen is allowed for /n"
+ "transparent activities."
+ bug: "394714626"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "include_top_transparent_fullscreen_task_in_desktop_heuristic"
namespace: "lse_desktop_experience"
description: "Whether to include any top transparent fullscreen task launched in desktop /n"
@@ -670,6 +681,16 @@
}
flag {
+ name: "enable_opaque_background_for_transparent_windows"
+ namespace: "lse_desktop_experience"
+ description: "Whether an opaque background should be forcefully set for windows with only transparent background."
+ bug: "397219542"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "enable_desktop_mode_through_dev_option"
namespace: "lse_desktop_experience"
description: "Enables support for desktop mode through developer options for devices eligible for desktop mode."
@@ -694,6 +715,13 @@
}
flag {
+ name: "enable_activity_embedding_support_for_connected_displays"
+ namespace: "lse_desktop_experience"
+ description: "Enables activity embedding support for connected displays, including enabling AE optimization for Settings."
+ bug: "369438353"
+}
+
+flag {
name: "enable_full_screen_window_on_removing_split_screen_stage_bugfix"
namespace: "lse_desktop_experience"
description: "Enables clearing the windowing mode of a freeform window when removing the task from the split screen stage."
@@ -753,3 +781,17 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_taskbar_overflow"
+ namespace: "lse_desktop_experience"
+ description: "Show recent apps in the taskbar overflow."
+ bug: "368119679"
+}
+
+flag {
+ name: "enable_projected_display_desktop_mode"
+ namespace: "lse_desktop_experience"
+ description: "Enable Desktop Mode on Projected Mode devices but constrained to the external display."
+ bug: "384568161"
+}
\ No newline at end of file
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 25dc672..a4d128f 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -40,6 +40,17 @@
}
flag {
+ name: "cache_window_style"
+ namespace: "windowing_frontend"
+ description: "Cache common window styles"
+ bug: "350394503"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "edge_to_edge_by_default"
namespace: "windowing_frontend"
description: "Make app go edge-to-edge by default when targeting SDK 35 or greater"
@@ -417,6 +428,17 @@
}
flag {
+ name: "reduce_changed_exclusion_rects_msgs"
+ namespace: "windowing_frontend"
+ description: "Don't send MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED when there is no change"
+ bug: "388231176"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "keep_app_window_hide_while_locked"
namespace: "windowing_frontend"
description: "Do not let app window visible while device is locked"
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 54d0eef..6e45d3d 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -62,16 +62,6 @@
flag {
namespace: "windowing_sdk"
- name: "move_animation_options_to_change"
- description: "Move AnimationOptions from TransitionInfo to each Change"
- bug: "327332488"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- namespace: "windowing_sdk"
name: "rear_display_disable_force_desktop_system_decorations"
description: "Block system decorations from being added to a rear display when desktop mode is forced"
bug: "346103150"
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 3bdf3d6..c009fc3 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1875,9 +1875,7 @@
Bundle b = new Bundle();
// Add userHandle based badge to the stackedAppDialogBox.
b.putParcelable(ChooserTargetActionsDialogFragment.USER_HANDLE_KEY,
- getResolveInfoUserHandle(
- targetInfo.getResolveInfo(),
- mChooserMultiProfilePagerAdapter.getCurrentUserHandle()));
+ targetInfo.getResolveInfo().userHandle);
b.putObject(ChooserStackedAppDialogFragment.MULTI_DRI_KEY,
mti);
b.putInt(ChooserStackedAppDialogFragment.WHICH_KEY, which);
@@ -2457,10 +2455,7 @@
// compares using resolveInfo.userHandle
mComparator = Comparator.comparing(DisplayResolveInfo::getDisplayLabel, collator)
.thenComparingInt(displayResolveInfo ->
- getResolveInfoUserHandle(
- displayResolveInfo.getResolveInfo(),
- // TODO: User resolveInfo.userHandle, once its available.
- UserHandle.SYSTEM).getIdentifier());
+ displayResolveInfo.getResolveInfo().userHandle.getIdentifier());
}
@Override
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index b3e828d..d38689c 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -362,8 +362,7 @@
}
String resolvedTarget = info.getResolvedComponentName().getPackageName()
+ '#' + info.getDisplayLabel()
- + '#' + ResolverActivity.getResolveInfoUserHandle(
- info.getResolveInfo(), getUserHandle()).getIdentifier();
+ + '#' + info.getResolveInfo().userHandle.getIdentifier();
DisplayResolveInfo multiDri = consolidated.get(resolvedTarget);
if (multiDri == null) {
consolidated.put(resolvedTarget, info);
diff --git a/core/java/com/android/internal/app/MediaRouteControllerContentManager.java b/core/java/com/android/internal/app/MediaRouteControllerContentManager.java
new file mode 100644
index 0000000..3a8b94f
--- /dev/null
+++ b/core/java/com/android/internal/app/MediaRouteControllerContentManager.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.media.MediaRouter;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import com.android.internal.R;
+
+/**
+ * This class manages the content display within the media route controller UI.
+ */
+public class MediaRouteControllerContentManager {
+ /**
+ * A delegate interface that a MediaRouteController UI should implement. It allows the content
+ * manager to inform the UI of any UI changes that need to be made in response to content
+ * updates.
+ */
+ public interface Delegate {
+ /**
+ * Updates the title of the media route device
+ */
+ void setMediaRouteDeviceTitle(CharSequence title);
+
+ /**
+ * Updates the icon of the media route device
+ */
+ void setMediaRouteDeviceIcon(Drawable icon);
+
+ /**
+ * Dismiss the UI to transition to a different workflow.
+ */
+ void dismissView();
+ }
+
+ private final Context mContext;
+ private final Delegate mDelegate;
+
+ // Time to wait before updating the volume when the user lets go of the seek bar
+ // to allow the route provider time to propagate the change and publish a new
+ // route descriptor.
+ private static final int VOLUME_UPDATE_DELAY_MILLIS = 250;
+
+ private final MediaRouter mRouter;
+ private final MediaRouteControllerContentManager.MediaRouterCallback mCallback;
+ private final MediaRouter.RouteInfo mRoute;
+
+ private Drawable mMediaRouteButtonDrawable;
+ private final int[] mMediaRouteConnectingState = { R.attr.state_checked, R.attr.state_enabled };
+ private final int[] mMediaRouteOnState = { R.attr.state_activated, R.attr.state_enabled };
+ private Drawable mCurrentIconDrawable;
+
+ private boolean mAttachedToWindow;
+
+ private LinearLayout mVolumeLayout;
+ private SeekBar mVolumeSlider;
+ private boolean mVolumeSliderTouched;
+
+ public MediaRouteControllerContentManager(Context context, Delegate delegate) {
+ mContext = context;
+ mDelegate = delegate;
+ mRouter = context.getSystemService(MediaRouter.class);
+ mCallback = new MediaRouteControllerContentManager.MediaRouterCallback();
+ mRoute = mRouter.getSelectedRoute();
+ }
+
+ /**
+ * Starts binding all the views (volume layout, slider, etc.) using the
+ * given container view.
+ */
+ public void bindViews(View containerView) {
+ mDelegate.setMediaRouteDeviceTitle(mRoute.getName());
+ mVolumeLayout = containerView.findViewById(R.id.media_route_volume_layout);
+ mVolumeSlider = containerView.findViewById(R.id.media_route_volume_slider);
+ mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ private final Runnable mStopTrackingTouch = new Runnable() {
+ @Override
+ public void run() {
+ if (mVolumeSliderTouched) {
+ mVolumeSliderTouched = false;
+ updateVolume();
+ }
+ }
+ };
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ if (mVolumeSliderTouched) {
+ mVolumeSlider.removeCallbacks(mStopTrackingTouch);
+ } else {
+ mVolumeSliderTouched = true;
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Defer resetting mVolumeSliderTouched to allow the media route provider
+ // a little time to settle into its new state and publish the final
+ // volume update.
+ mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ mRoute.requestSetVolume(progress);
+ }
+ }
+ });
+
+ mMediaRouteButtonDrawable = obtainMediaRouteButtonDrawable();
+ }
+
+ /**
+ * Called when this UI is attached to a window..
+ */
+ public void onAttachedToWindow() {
+ mAttachedToWindow = true;
+ mRouter.addCallback(0, mCallback, MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
+ update();
+ }
+
+ /**
+ * Called when this UI is detached from a window..
+ */
+ public void onDetachedFromWindow() {
+ mRouter.removeCallback(mCallback);
+ mAttachedToWindow = false;
+ }
+
+ /**
+ * Updates all the views to reflect new states.
+ */
+ public void update() {
+ if (!mRoute.isSelected() || mRoute.isDefault()) {
+ mDelegate.dismissView();
+ }
+
+ mDelegate.setMediaRouteDeviceTitle(mRoute.getName());
+ updateVolume();
+
+ Drawable icon = getIconDrawable();
+ if (icon != mCurrentIconDrawable) {
+ mCurrentIconDrawable = icon;
+ if (icon instanceof AnimationDrawable animDrawable) {
+ if (!mAttachedToWindow && !mRoute.isConnecting()) {
+ // When the route is already connected before the view is attached, show the
+ // last frame of the connected animation immediately.
+ if (animDrawable.isRunning()) {
+ animDrawable.stop();
+ }
+ icon = animDrawable.getFrame(animDrawable.getNumberOfFrames() - 1);
+ } else if (!animDrawable.isRunning()) {
+ animDrawable.start();
+ }
+ }
+ mDelegate.setMediaRouteDeviceIcon(icon);
+ }
+ }
+
+ private void updateVolume() {
+ if (!mVolumeSliderTouched) {
+ if (isVolumeControlAvailable()) {
+ mVolumeLayout.setVisibility(View.VISIBLE);
+ mVolumeSlider.setMax(mRoute.getVolumeMax());
+ mVolumeSlider.setProgress(mRoute.getVolume());
+ } else {
+ mVolumeLayout.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ /**
+ * Callback function to triggered after the disconnect button is clicked.
+ */
+ public void onDisconnectButtonClick() {
+ if (mRoute.isSelected()) {
+ if (mRoute.isBluetooth()) {
+ mRouter.getDefaultRoute().select();
+ } else {
+ mRouter.getFallbackRoute().select();
+ }
+ }
+ mDelegate.dismissView();
+ }
+
+ private boolean isVolumeControlAvailable() {
+ return mRoute.getVolumeHandling() == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
+ }
+
+ private Drawable obtainMediaRouteButtonDrawable() {
+ TypedValue value = new TypedValue();
+ if (!mContext.getTheme().resolveAttribute(R.attr.mediaRouteButtonStyle, value, true)) {
+ return null;
+ }
+ int[] drawableAttrs = new int[] { R.attr.externalRouteEnabledDrawable };
+ TypedArray a = mContext.obtainStyledAttributes(value.data, drawableAttrs);
+ Drawable drawable = a.getDrawable(0);
+ a.recycle();
+ return drawable;
+ }
+
+ private Drawable getIconDrawable() {
+ if (!(mMediaRouteButtonDrawable instanceof StateListDrawable)) {
+ return mMediaRouteButtonDrawable;
+ } else if (mRoute.isConnecting()) {
+ StateListDrawable stateListDrawable = (StateListDrawable) mMediaRouteButtonDrawable;
+ stateListDrawable.setState(mMediaRouteConnectingState);
+ return stateListDrawable.getCurrent();
+ } else {
+ StateListDrawable stateListDrawable = (StateListDrawable) mMediaRouteButtonDrawable;
+ stateListDrawable.setState(mMediaRouteOnState);
+ return stateListDrawable.getCurrent();
+ }
+ }
+
+ private final class MediaRouterCallback extends MediaRouter.SimpleCallback {
+ @Override
+ public void onRouteUnselected(MediaRouter router, int type, MediaRouter.RouteInfo info) {
+ update();
+ }
+
+ @Override
+ public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
+ update();
+ }
+
+ @Override
+ public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
+ if (route == mRoute) {
+ updateVolume();
+ }
+ }
+
+ @Override
+ public void onRouteGrouped(MediaRouter router, MediaRouter.RouteInfo info,
+ MediaRouter.RouteGroup group, int index) {
+ update();
+ }
+
+ @Override
+ public void onRouteUngrouped(MediaRouter router, MediaRouter.RouteInfo info,
+ MediaRouter.RouteGroup group) {
+ update();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/app/MediaRouteControllerDialog.java b/core/java/com/android/internal/app/MediaRouteControllerDialog.java
index 621ec50..5899963 100644
--- a/core/java/com/android/internal/app/MediaRouteControllerDialog.java
+++ b/core/java/com/android/internal/app/MediaRouteControllerDialog.java
@@ -21,20 +21,11 @@
import android.app.MediaRouteButton;
import android.content.Context;
import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
import android.media.MediaRouter;
-import android.media.MediaRouter.RouteGroup;
-import android.media.MediaRouter.RouteInfo;
import android.os.Bundle;
-import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.SeekBar;
import com.android.internal.R;
@@ -49,153 +40,50 @@
*
* TODO: Move this back into the API, as in the support library media router.
*/
-public class MediaRouteControllerDialog extends AlertDialog {
- // Time to wait before updating the volume when the user lets go of the seek bar
- // to allow the route provider time to propagate the change and publish a new
- // route descriptor.
- private static final int VOLUME_UPDATE_DELAY_MILLIS = 250;
-
+public class MediaRouteControllerDialog extends AlertDialog implements
+ MediaRouteControllerContentManager.Delegate {
+ // TODO(b/360050020): Eventually these 2 variables should be in the content manager instead of
+ // here. So these should be removed when the migration is completed.
private final MediaRouter mRouter;
- private final MediaRouterCallback mCallback;
private final MediaRouter.RouteInfo mRoute;
- private Drawable mMediaRouteButtonDrawable;
- private int[] mMediaRouteConnectingState = { R.attr.state_checked, R.attr.state_enabled };
- private int[] mMediaRouteOnState = { R.attr.state_activated, R.attr.state_enabled };
- private Drawable mCurrentIconDrawable;
-
- private boolean mVolumeControlEnabled = true;
- private LinearLayout mVolumeLayout;
- private SeekBar mVolumeSlider;
- private boolean mVolumeSliderTouched;
-
- private View mControlView;
- private boolean mAttachedToWindow;
+ private final MediaRouteControllerContentManager mContentManager;
public MediaRouteControllerDialog(Context context, int theme) {
super(context, theme);
+ mContentManager = new MediaRouteControllerContentManager(context, this);
mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
- mCallback = new MediaRouterCallback();
mRoute = mRouter.getSelectedRoute();
}
- /**
- * Gets the route that this dialog is controlling.
- */
- public MediaRouter.RouteInfo getRoute() {
- return mRoute;
- }
-
- /**
- * Provides the subclass an opportunity to create a view that will
- * be included within the body of the dialog to offer additional media controls
- * for the currently playing content.
- *
- * @param savedInstanceState The dialog's saved instance state.
- * @return The media control view, or null if none.
- */
- public View onCreateMediaControlView(Bundle savedInstanceState) {
- return null;
- }
-
- /**
- * Returns whether to enable the volume slider and volume control using the volume keys
- * when the route supports it.
- */
- public boolean isVolumeControlEnabled() {
- return mVolumeControlEnabled;
- }
-
@Override
protected void onCreate(Bundle savedInstanceState) {
- setTitle(mRoute.getName());
Resources res = getContext().getResources();
setButton(BUTTON_NEGATIVE, res.getString(R.string.media_route_controller_disconnect),
- (dialogInterface, id) -> {
- if (mRoute.isSelected()) {
- if (mRoute.isBluetooth()) {
- mRouter.getDefaultRoute().select();
- } else {
- mRouter.getFallbackRoute().select();
- }
- }
- dismiss();
- });
+ (dialogInterface, id) -> mContentManager.onDisconnectButtonClick());
View customView = getLayoutInflater().inflate(R.layout.media_route_controller_dialog, null);
setView(customView, 0, 0, 0, 0);
+ mContentManager.bindViews(customView);
super.onCreate(savedInstanceState);
View customPanelView = getWindow().findViewById(R.id.customPanel);
if (customPanelView != null) {
customPanelView.setMinimumHeight(0);
}
- mVolumeLayout = customView.findViewById(R.id.media_route_volume_layout);
- mVolumeSlider = customView.findViewById(R.id.media_route_volume_slider);
- mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- private final Runnable mStopTrackingTouch = new Runnable() {
- @Override
- public void run() {
- if (mVolumeSliderTouched) {
- mVolumeSliderTouched = false;
- updateVolume();
- }
- }
- };
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- if (mVolumeSliderTouched) {
- mVolumeSlider.removeCallbacks(mStopTrackingTouch);
- } else {
- mVolumeSliderTouched = true;
- }
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- // Defer resetting mVolumeSliderTouched to allow the media route provider
- // a little time to settle into its new state and publish the final
- // volume update.
- mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (fromUser) {
- mRoute.requestSetVolume(progress);
- }
- }
- });
-
- mMediaRouteButtonDrawable = obtainMediaRouteButtonDrawable();
- if (update()) {
- mControlView = onCreateMediaControlView(savedInstanceState);
- FrameLayout controlFrame =
- customView.findViewById(R.id.media_route_control_frame);
- if (mControlView != null) {
- controlFrame.addView(mControlView);
- controlFrame.setVisibility(View.VISIBLE);
- } else {
- controlFrame.setVisibility(View.GONE);
- }
- }
+ mContentManager.update();
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
- mAttachedToWindow = true;
-
- mRouter.addCallback(0, mCallback, MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
- update();
+ mContentManager.onAttachedToWindow();
}
@Override
public void onDetachedFromWindow() {
- mRouter.removeCallback(mCallback);
- mAttachedToWindow = false;
-
+ mContentManager.onDetachedFromWindow();
super.onDetachedFromWindow();
}
@@ -218,106 +106,18 @@
return super.onKeyUp(keyCode, event);
}
- private boolean update() {
- if (!mRoute.isSelected() || mRoute.isDefault()) {
- dismiss();
- return false;
- }
-
- setTitle(mRoute.getName());
- updateVolume();
-
- Drawable icon = getIconDrawable();
- if (icon != mCurrentIconDrawable) {
- mCurrentIconDrawable = icon;
- if (icon instanceof AnimationDrawable animDrawable) {
- if (!mAttachedToWindow && !mRoute.isConnecting()) {
- // When the route is already connected before the view is attached, show the
- // last frame of the connected animation immediately.
- if (animDrawable.isRunning()) {
- animDrawable.stop();
- }
- icon = animDrawable.getFrame(animDrawable.getNumberOfFrames() - 1);
- } else if (!animDrawable.isRunning()) {
- animDrawable.start();
- }
- }
- setIcon(icon);
- }
- return true;
+ @Override
+ public void setMediaRouteDeviceTitle(CharSequence title) {
+ setTitle(title);
}
- private Drawable obtainMediaRouteButtonDrawable() {
- Context context = getContext();
- TypedValue value = new TypedValue();
- if (!context.getTheme().resolveAttribute(R.attr.mediaRouteButtonStyle, value, true)) {
- return null;
- }
- int[] drawableAttrs = new int[] { R.attr.externalRouteEnabledDrawable };
- TypedArray a = context.obtainStyledAttributes(value.data, drawableAttrs);
- Drawable drawable = a.getDrawable(0);
- a.recycle();
- return drawable;
+ @Override
+ public void setMediaRouteDeviceIcon(Drawable icon) {
+ setIcon(icon);
}
- private Drawable getIconDrawable() {
- if (!(mMediaRouteButtonDrawable instanceof StateListDrawable)) {
- return mMediaRouteButtonDrawable;
- } else if (mRoute.isConnecting()) {
- StateListDrawable stateListDrawable = (StateListDrawable) mMediaRouteButtonDrawable;
- stateListDrawable.setState(mMediaRouteConnectingState);
- return stateListDrawable.getCurrent();
- } else {
- StateListDrawable stateListDrawable = (StateListDrawable) mMediaRouteButtonDrawable;
- stateListDrawable.setState(mMediaRouteOnState);
- return stateListDrawable.getCurrent();
- }
- }
-
- private void updateVolume() {
- if (!mVolumeSliderTouched) {
- if (isVolumeControlAvailable()) {
- mVolumeLayout.setVisibility(View.VISIBLE);
- mVolumeSlider.setMax(mRoute.getVolumeMax());
- mVolumeSlider.setProgress(mRoute.getVolume());
- } else {
- mVolumeLayout.setVisibility(View.GONE);
- }
- }
- }
-
- private boolean isVolumeControlAvailable() {
- return mVolumeControlEnabled && mRoute.getVolumeHandling() ==
- MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
- }
-
- private final class MediaRouterCallback extends MediaRouter.SimpleCallback {
- @Override
- public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
- update();
- }
-
- @Override
- public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
- update();
- }
-
- @Override
- public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
- if (route == mRoute) {
- updateVolume();
- }
- }
-
- @Override
- public void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group,
- int index) {
- update();
- }
-
- @Override
- public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
- update();
- }
+ @Override
+ public void dismissView() {
+ dismiss();
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index db65d31..eaf1573 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1605,8 +1605,7 @@
// In case cloned apps are present, we would want to start those apps in cloned user
// space, which will not be same as adaptor's userHandle. resolveInfo.userHandle
// identifies the correct user space in such cases.
- UserHandle activityUserHandle = getResolveInfoUserHandle(
- cti.getResolveInfo(), mMultiProfilePagerAdapter.getCurrentUserHandle());
+ UserHandle activityUserHandle = cti.getResolveInfo().userHandle;
safelyStartActivityAsUser(cti, activityUserHandle, null);
}
@@ -2399,11 +2398,7 @@
&& Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName)
// Comparing against resolveInfo.userHandle in case cloned apps are present,
// as they will have the same activityInfo.
- && Objects.equals(
- getResolveInfoUserHandle(lhs,
- mMultiProfilePagerAdapter.getActiveListAdapter().getUserHandle()),
- getResolveInfoUserHandle(rhs,
- mMultiProfilePagerAdapter.getActiveListAdapter().getUserHandle()));
+ && Objects.equals(lhs.userHandle, rhs.userHandle);
}
protected String getMetricsCategory() {
@@ -2686,18 +2681,6 @@
return userList;
}
- /**
- * This function is temporary in nature, and its usages will be replaced with just
- * resolveInfo.userHandle, once it is available, once sharesheet is stable.
- */
- public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo,
- UserHandle predictedHandle) {
- if (resolveInfo.userHandle == null) {
- Log.e(TAG, "ResolveInfo with null UserHandle found: " + resolveInfo);
- }
- return resolveInfo.userHandle;
- }
-
private boolean privateSpaceEnabled() {
return mIsIntentPicker && android.os.Flags.allowPrivateProfile()
&& android.multiuser.Flags.allowResolverSheetForPrivateSpace()
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index de7ad34..54c0e61 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -747,8 +747,7 @@
Drawable loadIconForResolveInfo(ResolveInfo ri) {
// Load icons based on userHandle from ResolveInfo. If in work profile/clone profile, icons
// should be badged.
- return makePresentationGetter(ri)
- .getIcon(ResolverActivity.getResolveInfoUserHandle(ri, getUserHandle()));
+ return makePresentationGetter(ri).getIcon(ri.userHandle);
}
void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) {
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 454323b..a0f45b0 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -257,15 +257,11 @@
@Override
public void surfaceDestroyed() {
-
- // Wait a while to give the system a chance for the remaining
- // frames to arrive, then force finish the session.
- mHandler.postDelayed(() -> {
+ mHandler.post(() -> {
if (!mMetricsFinalized) {
end(REASON_END_SURFACE_DESTROYED);
- finish();
}
- }, 50);
+ });
}
};
// This callback has a reference to FrameTracker,
@@ -367,9 +363,9 @@
// Send a flush jank data transaction.
if (mSurfaceControl != null && mSurfaceControl.isValid()) {
SurfaceControl.Transaction.sendSurfaceFlushJankData(mSurfaceControl);
- if (mJankDataListenerRegistration != null) {
- mJankDataListenerRegistration.flush();
- }
+ }
+ if (mJankDataListenerRegistration != null) {
+ mJankDataListenerRegistration.flush();
}
long delay;
@@ -650,6 +646,8 @@
Log.w(TAG, "Missing SF jank callback for vsyncId: " + info.frameVsyncId
+ ", CUJ=" + name);
}
+ } else if (Flags.useSfFrameDuration() && info.surfaceControlCallbackFired) {
+ maxFrameTimeNanos = Math.max(info.totalDurationNanos, maxFrameTimeNanos);
}
}
maxSuccessiveMissedFramesCount = Math.max(
diff --git a/core/java/com/android/internal/os/ApplicationSharedMemory.java b/core/java/com/android/internal/os/ApplicationSharedMemory.java
index e6ea29e..4c491c8 100644
--- a/core/java/com/android/internal/os/ApplicationSharedMemory.java
+++ b/core/java/com/android/internal/os/ApplicationSharedMemory.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.util.Log;
+
import com.android.internal.annotations.VisibleForTesting;
import dalvik.annotation.optimization.CriticalNative;
@@ -324,4 +325,35 @@
*/
@FastNative
private static native long nativeGetSystemNonceBlock(long ptr);
+
+ /**
+ * Perform a one-time write of cached SDK feature versions.
+ *
+ * @throws IllegalStateException if the feature versions have already been written or the ashmem
+ * is immutable.
+ * @throws IllegalArgumentException if the provided feature version array is too large.
+ */
+ public void writeSystemFeaturesCache(@NonNull int[] featureVersions) {
+ checkMutable();
+ nativeWriteSystemFeaturesCache(mPtr, featureVersions);
+ }
+
+ /**
+ * Read the cached SDK feature versions previously written to shared memory.
+ *
+ * Note: The result should generally be cached elsewhere for global reuse.
+ */
+ // TODO(b/326623529): Consider using a MappedByteBuffer or equivalent to avoid needing a
+ // Java copy of the cached data for potentially frequent reads. Alternatively, the JNI query
+ // lookup for a given feature could be cheap enough to avoid the cached Java copy entirely.
+ public @NonNull int[] readSystemFeaturesCache() {
+ checkMapped();
+ return nativeReadSystemFeaturesCache(mPtr);
+ }
+
+ @FastNative
+ private static native void nativeWriteSystemFeaturesCache(long ptr, int[] cache);
+
+ @FastNative
+ private static native int[] nativeReadSystemFeaturesCache(long ptr);
}
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index 2931bd2..5e9c87a 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -16,6 +16,8 @@
package com.android.internal.os;
+import android.annotation.CheckResult;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
@@ -155,8 +157,9 @@
/**
* Adds the supplied values to the current accumulated values in the counter.
+ * Null `values` parameter is interpreted as an array of zeros.
*/
- public void incrementValues(long[] values, long timestampMs) {
+ public void incrementValues(@Nullable long[] values, long timestampMs) {
native_incrementValues(mNativeObject, values, timestampMs);
}
@@ -194,7 +197,8 @@
/**
* Populates the array with the accumulated counts for the specified state.
*/
- public void getCounts(long[] counts, int state) {
+ @CheckResult
+ public boolean getCounts(long[] counts, int state) {
if (state < 0 || state >= mStateCount) {
throw new IllegalArgumentException(
"State: " + state + ", outside the range: [0-" + mStateCount + "]");
@@ -203,7 +207,7 @@
throw new IllegalArgumentException(
"Invalid array length: " + counts.length + ", expected: " + mLength);
}
- native_getCounts(mNativeObject, counts, state);
+ return native_getCounts(mNativeObject, counts, state);
}
@Override
@@ -280,7 +284,8 @@
@FastNative
@RavenwoodRedirect
- private static native void native_getCounts(long nativeObject, long[] counts, int state);
+ @CheckResult
+ private static native boolean native_getCounts(long nativeObject, long[] counts, int state);
@FastNative
@RavenwoodRedirect
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter_ravenwood.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter_ravenwood.java
index 7030d8e..403e8c1 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter_ravenwood.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter_ravenwood.java
@@ -16,6 +16,7 @@
package com.android.internal.os;
+import android.annotation.Nullable;
import android.os.BadParcelableException;
import android.os.Parcel;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
@@ -147,10 +148,12 @@
mLastUpdateTimestampMs = timestampMs;
}
- public void incrementValues(long[] delta, long timestampMs) {
+ public void incrementValues(@Nullable long[] delta, long timestampMs) {
long[] values = Arrays.copyOf(mValues, mValues.length);
- for (int i = 0; i < mArrayLength; i++) {
- values[i] += delta[i];
+ if (delta != null) {
+ for (int i = 0; i < mArrayLength; i++) {
+ values[i] += delta[i];
+ }
}
updateValue(values, timestampMs);
}
@@ -165,8 +168,20 @@
}
}
- public void getValues(long[] values, int state) {
- System.arraycopy(mStates[state].mCounter, 0, values, 0, mArrayLength);
+ public boolean getValues(long[] values, int state) {
+ long[] counts = mStates[state].mCounter;
+ boolean allZeros = true;
+ for (int i = 0; i < counts.length; i++) {
+ if (counts[i] != 0) {
+ allZeros = false;
+ break;
+ }
+ }
+ if (allZeros) {
+ return false;
+ }
+ System.arraycopy(counts, 0, values, 0, mArrayLength);
+ return true;
}
public void reset() {
@@ -304,7 +319,8 @@
getInstance(targetInstanceId).copyStatesFrom(getInstance(sourceInstanceId));
}
- public static void native_incrementValues(long instanceId, long[] delta, long timestampMs) {
+ public static void native_incrementValues(long instanceId, @Nullable long[] delta,
+ long timestampMs) {
getInstance(instanceId).incrementValues(delta, timestampMs);
}
@@ -312,8 +328,8 @@
getInstance(instanceId).addCounts(counts);
}
- public static void native_getCounts(long instanceId, long[] counts, int state) {
- getInstance(instanceId).getValues(counts, state);
+ public static boolean native_getCounts(long instanceId, long[] counts, int state) {
+ return getInstance(instanceId).getValues(counts, state);
}
public static void native_reset(long instanceId) {
diff --git a/core/java/com/android/internal/os/PowerStats.java b/core/java/com/android/internal/os/PowerStats.java
index aafef6c..6c69e2c 100644
--- a/core/java/com/android/internal/os/PowerStats.java
+++ b/core/java/com/android/internal/os/PowerStats.java
@@ -128,6 +128,7 @@
* Extra parameters specific to the power component, e.g. the availability of power
* monitors.
*/
+ @NonNull
public final PersistableBundle extras;
private PowerStatsFormatter mDeviceStatsFormatter;
@@ -269,20 +270,41 @@
stateStatsArrayLength, uidStatsArrayLength, extras);
}
+ @SuppressWarnings("deprecation")
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Descriptor)) return false;
Descriptor that = (Descriptor) o;
- return powerComponentId == that.powerComponentId
- && statsArrayLength == that.statsArrayLength
- && stateLabels.contentEquals(that.stateLabels)
- && stateStatsArrayLength == that.stateStatsArrayLength
- && uidStatsArrayLength == that.uidStatsArrayLength
- && Objects.equals(name, that.name)
- && extras.size() == that.extras.size() // Unparcel the Parcel if not yet
- && Bundle.kindofEquals(extras,
- that.extras); // Since the Parcel is now unparceled, do a deep comparison
+ if (powerComponentId != that.powerComponentId
+ || statsArrayLength != that.statsArrayLength
+ || !stateLabels.contentEquals(that.stateLabels)
+ || stateStatsArrayLength != that.stateStatsArrayLength
+ || uidStatsArrayLength != that.uidStatsArrayLength
+ || !Objects.equals(name, that.name)) {
+ return false;
+ }
+
+ // Getting the size has the side-effect of unparceling the Bundle if not yet
+ if (extras.size() != that.extras.size()) {
+ return false;
+ }
+
+ if (Bundle.kindofEquals(extras, that.extras)) {
+ return true;
+ }
+
+ // Since `kindofEquals` does not deep-compare arrays, we do that separately, albeit at
+ // the expense of creating an iterator and using a deprecated API, `bundle.get`.
+ // There is no performance concern, because the situation where PowerStatsDescriptors
+ // are changed in an incompatible way are exceedingly rare, occurring at most
+ // once per power component after a system upgrade.
+ for (String key : extras.keySet()) {
+ if (!Objects.deepEquals(extras.get(key), that.extras.get(key))) {
+ return false;
+ }
+ }
+ return true;
}
/**
diff --git a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
index b57acf3..b19967a 100644
--- a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
+++ b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
@@ -261,7 +261,12 @@
// Default value is false for when the flag is not found.
// Note: Unlike with the old storage, with AconfigPackage, we don't have a way to
// know if the flag is not found or if it's found but the value is false.
- value = aconfigPackage.getBooleanFlagValue(flagName, false);
+ try {
+ value = aconfigPackage.getBooleanFlagValue(flagName, false);
+ } catch (Exception e) {
+ Slog.e(LOG_TAG, "Failed to read Aconfig flag value for " + flagPackageAndName, e);
+ return null;
+ }
}
if (DEBUG) {
Slog.v(LOG_TAG, "Aconfig flag value for " + flagPackageAndName + " = " + value);
diff --git a/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java
index 7ee22f3..69c0480 100644
--- a/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java
@@ -157,7 +157,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(this.name);
+ sForInternedString.parcel(this.name, dest, flags);
dest.writeInt(this.getIcon());
dest.writeInt(this.getLabelRes());
dest.writeCharSequence(this.getNonLocalizedLabel());
@@ -175,7 +175,7 @@
// We use the boot classloader for all classes that we load.
final ClassLoader boot = Object.class.getClassLoader();
//noinspection ConstantConditions
- this.name = in.readString();
+ this.name = sForInternedString.unparcel(in);
this.icon = in.readInt();
this.labelRes = in.readInt();
this.nonLocalizedLabel = in.readCharSequence();
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index d73e2d4..4d77096 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -471,6 +471,20 @@
}
/**
+ * This is similar to {@link #isOptingOutEdgeToEdgeEnforcement} but the caller needs to check
+ * whether the app declares style to opt out.
+ */
+ public static boolean isOptOutEdgeToEdgeEnabled(ApplicationInfo info, boolean local) {
+ final boolean disabled = Flags.disableOptOutEdgeToEdge()
+ && (local
+ // Calling this doesn't require a permission.
+ ? CompatChanges.isChangeEnabled(DISABLE_OPT_OUT_EDGE_TO_EDGE)
+ // Calling this requires permissions.
+ : info.isChangeEnabled(DISABLE_OPT_OUT_EDGE_TO_EDGE));
+ return !disabled;
+ }
+
+ /**
* Returns whether the given application is opting out edge-to-edge enforcement.
*
* @param info The application to query.
@@ -480,13 +494,7 @@
*/
public static boolean isOptingOutEdgeToEdgeEnforcement(ApplicationInfo info, boolean local,
TypedArray windowStyle) {
- final boolean disabled = Flags.disableOptOutEdgeToEdge()
- && (local
- // Calling this doesn't require a permission.
- ? CompatChanges.isChangeEnabled(DISABLE_OPT_OUT_EDGE_TO_EDGE)
- // Calling this requires permissions.
- : info.isChangeEnabled(DISABLE_OPT_OUT_EDGE_TO_EDGE));
- return !disabled && windowStyle.getBoolean(
+ return isOptOutEdgeToEdgeEnabled(info, local) && windowStyle.getBoolean(
R.styleable.Window_windowOptOutEdgeToEdgeEnforcement, false /* default */);
}
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 93be3b0..2d98994 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -322,7 +322,7 @@
PrintWriter pw = shell.getOutPrintWriter();
if (android.tracing.Flags.clientSideProtoLogging()) {
- pw.println("Command deprecated. Please use 'cmd protolog' instead.");
+ pw.println("Command deprecated. Please use 'cmd protolog_configuration' instead.");
return -1;
}
diff --git a/core/java/com/android/internal/protolog/ProtoLogCommandHandler.java b/core/java/com/android/internal/protolog/ProtoLogCommandHandler.java
index 82d8d34..6d4a408 100644
--- a/core/java/com/android/internal/protolog/ProtoLogCommandHandler.java
+++ b/core/java/com/android/internal/protolog/ProtoLogCommandHandler.java
@@ -145,11 +145,11 @@
switch (cmd) {
case "enable" -> {
- mProtoLogConfigurationService.enableProtoLogToLogcat(processGroups());
+ mProtoLogConfigurationService.enableProtoLogToLogcat(pw, processGroups());
return 0;
}
case "disable" -> {
- mProtoLogConfigurationService.disableProtoLogToLogcat(processGroups());
+ mProtoLogConfigurationService.disableProtoLogToLogcat(pw, processGroups());
return 0;
}
default -> {
diff --git a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
index d65aaae..a19690b 100644
--- a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
+++ b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
+import java.io.PrintWriter;
+
public interface ProtoLogConfigurationService extends IProtoLogConfigurationService {
/**
* Get the list of groups clients have registered to the protolog service.
@@ -37,11 +39,11 @@
* Enable logging target groups to logcat.
* @param groups we want to enable logging them to logcat for.
*/
- void enableProtoLogToLogcat(@NonNull String... groups);
+ void enableProtoLogToLogcat(@NonNull PrintWriter pw, @NonNull String... groups);
/**
* Disable logging target groups to logcat.
* @param groups we want to disable from being logged to logcat.
*/
- void disableProtoLogToLogcat(@NonNull String... groups);
+ void disableProtoLogToLogcat(@NonNull PrintWriter pw, @NonNull String... groups);
}
diff --git a/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java b/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java
index f83359d..ac1022f 100644
--- a/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java
@@ -44,6 +44,7 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -183,8 +184,8 @@
* @param groups we want to enable logging them to logcat for.
*/
@Override
- public void enableProtoLogToLogcat(@NonNull String... groups) {
- toggleProtoLogToLogcat(true, groups);
+ public void enableProtoLogToLogcat(@NonNull PrintWriter pw, @NonNull String... groups) {
+ toggleProtoLogToLogcat(pw, true, groups);
}
/**
@@ -192,8 +193,8 @@
* @param groups we want to disable from being logged to logcat.
*/
@Override
- public void disableProtoLogToLogcat(@NonNull String... groups) {
- toggleProtoLogToLogcat(false, groups);
+ public void disableProtoLogToLogcat(@NonNull PrintWriter pw, @NonNull String... groups) {
+ toggleProtoLogToLogcat(pw, false, groups);
}
/**
@@ -249,7 +250,9 @@
}
}
- private void toggleProtoLogToLogcat(boolean enabled, @NonNull String[] groups) {
+ private void toggleProtoLogToLogcat(
+ @NonNull PrintWriter pw, boolean enabled, @NonNull String[] groups
+ ) {
final var clientToGroups = new HashMap<IProtoLogClient, Set<String>>();
for (String group : groups) {
@@ -257,8 +260,10 @@
if (clients == null) {
// No clients associated to this group
- Log.w(LOG_TAG, "Attempting to toggle log to logcat for group " + group
- + " with no registered clients.");
+ var warning = "Attempting to toggle log to logcat for group " + group
+ + " with no registered clients. This is a no-op.";
+ Log.w(LOG_TAG, warning);
+ pw.println("WARNING: " + warning);
continue;
}
@@ -270,8 +275,14 @@
for (IProtoLogClient client : clientToGroups.keySet()) {
try {
- client.toggleLogcat(enabled, clientToGroups.get(client).toArray(new String[0]));
+ final var clientGroups = clientToGroups.get(client).toArray(new String[0]);
+ pw.println("Toggling logcat logging for client " + client.toString()
+ + " to " + enabled + " for groups: ["
+ + String.join(", ", clientGroups) + "]");
+ client.toggleLogcat(enabled, clientGroups);
+ pw.println("- Done");
} catch (RemoteException e) {
+ pw.println("- Failed");
throw new RuntimeException(
"Failed to toggle logcat status for groups on client", e);
}
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index f443b0a..c120e67d 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -22,6 +22,7 @@
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_BACK_SYSTEM_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL_UNLOCKED;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FACE_WAKE_AND_UNLOCK;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
@@ -266,6 +267,15 @@
*/
public static final int ACTION_SHADE_WINDOW_DISPLAY_CHANGE = 29;
+ /**
+ * Applicable when the user drags a full screen app's handle into the desktop drop zone to enter
+ * desktop mode. This measure the time from when the user releases their finger in the drop zone
+ * to when the animation for entering desktop mode visually begins. During this period, the
+ * home task and app headers for each window are initialized. Both have historically been
+ * expensive. See b/381396057 and b/360452034 respectively.
+ */
+ public static final int ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG = 30;
+
private static final int[] ACTIONS_ALL = {
ACTION_EXPAND_PANEL,
ACTION_TOGGLE_RECENTS,
@@ -297,6 +307,7 @@
ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN,
ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
+ ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG,
};
/** @hide */
@@ -331,10 +342,10 @@
ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN,
ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
+ ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface Action {
- }
+ public @interface Action {}
@VisibleForTesting
public static final int[] STATSD_ACTION = new int[] {
@@ -368,6 +379,7 @@
UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
+ UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG,
};
private final Object mLock = new Object();
@@ -568,6 +580,8 @@
return "ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME";
case UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHADE_WINDOW_DISPLAY_CHANGE:
return "ACTION_SHADE_WINDOW_DISPLAY_CHANGE";
+ case UIACTION_LATENCY_REPORTED__ACTION__ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG:
+ return "ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG";
default:
throw new IllegalArgumentException("Invalid action");
}
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 641ecc9..ce46da1 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -250,7 +250,8 @@
mPeopleHelper.animateViewForceHidden(mImportanceRingView, forceHidden);
mPeopleHelper.animateViewForceHidden(mIcon, forceHidden);
});
- mConversationText = findViewById(R.id.conversation_text);
+ mConversationText = findViewById(notificationsRedesignTemplates()
+ ? R.id.title : R.id.conversation_text);
mExpandButtonContainer = findViewById(R.id.expand_button_container);
mExpandButtonContainerA11yContainer =
findViewById(R.id.expand_button_a11y_container);
@@ -716,17 +717,10 @@
}
private void updateImageMessages() {
- View newMessage = null;
- if (mIsCollapsed && !mGroups.isEmpty()) {
-
- // When collapsed, we're displaying the image message in a dedicated container
- // on the right of the layout instead of inline. Let's add the isolated image there
- MessagingGroup messagingGroup = mGroups.getLast();
- MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
- if (isolatedMessage != null) {
- newMessage = isolatedMessage.getView();
- }
+ if (mImageMessageContainer == null) {
+ return;
}
+ View newMessage = getNewImageMessage();
// Remove all messages that don't belong into the image layout
View previousMessage = mImageMessageContainer.getChildAt(0);
if (previousMessage != newMessage) {
@@ -738,6 +732,20 @@
mImageMessageContainer.setVisibility(newMessage != null ? VISIBLE : GONE);
}
+ @Nullable
+ private View getNewImageMessage() {
+ if (mIsCollapsed && !mGroups.isEmpty()) {
+ // When collapsed, we're displaying the image message in a dedicated container
+ // on the right of the layout instead of inline. Let's add the isolated image there
+ MessagingGroup messagingGroup = mGroups.getLast();
+ MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
+ if (isolatedMessage != null) {
+ return isolatedMessage.getView();
+ }
+ }
+ return null;
+ }
+
public void bindFacePile(ImageView bottomBackground, ImageView bottomView, ImageView topView) {
applyNotificationBackgroundColor(bottomBackground);
// Let's find the two last conversations:
@@ -841,6 +849,10 @@
}
private void updateAppName() {
+ if (notificationsRedesignTemplates()) {
+ return;
+ }
+
mAppName.setVisibility(mIsCollapsed ? GONE : VISIBLE);
}
@@ -1533,6 +1545,10 @@
}
private void updateExpandButton() {
+ if (notificationsRedesignTemplates()) {
+ return;
+ }
+
int buttonGravity;
ViewGroup newContainer;
if (mIsCollapsed) {
@@ -1565,6 +1581,10 @@
}
private void updateContentEndPaddings() {
+ if (notificationsRedesignTemplates()) {
+ return;
+ }
+
// Let's make sure the conversation header can't run into the expand button when we're
// collapsed and update the paddings of the content
int headerPaddingEnd;
@@ -1593,6 +1613,10 @@
}
private void onAppNameVisibilityChanged() {
+ if (notificationsRedesignTemplates()) {
+ return;
+ }
+
boolean appNameGone = mAppName.getVisibility() == GONE;
if (appNameGone != mAppNameGone) {
mAppNameGone = appNameGone;
@@ -1601,10 +1625,18 @@
}
private void updateAppNameDividerVisibility() {
+ if (notificationsRedesignTemplates()) {
+ return;
+ }
+
mAppNameDivider.setVisibility(mAppNameGone ? GONE : VISIBLE);
}
public void updateExpandability(boolean expandable, @Nullable OnClickListener onClickListener) {
+ if (notificationsRedesignTemplates()) {
+ return;
+ }
+
mExpandable = expandable;
if (expandable) {
mExpandButtonContainer.setVisibility(VISIBLE);
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 31d9770..b9a603cc 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -449,12 +449,8 @@
}
private void updateIconVisibility() {
- if (Flags.notificationsRedesignTemplates() && !mIsInConversation) {
- // We don't show any icon (other than the app icon) in the collapsed form. For
- // conversations, keeping this container helps with aligning the message to the icon
- // when collapsed, but the old messaging style already has this alignment built into
- // the template like all other layouts. Conversations are special because we use the
- // same base layout for both the collapsed and expanded views.
+ if (Flags.notificationsRedesignTemplates()) {
+ // We don't show any icon (other than the app or person icon) in the collapsed form.
mMessagingIconContainer.setVisibility(mSingleLine ? GONE : VISIBLE);
}
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index e9d920c..eb22e7c 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -121,22 +121,38 @@
setMessagingClippingDisabled(false);
}
- @RemotableViewMethod
+ @RemotableViewMethod(asyncImpl = "setAvatarReplacementAsync")
public void setAvatarReplacement(Icon icon) {
mAvatarReplacement = icon;
}
- @RemotableViewMethod
+ /**
+ * @hide
+ */
+ public Runnable setAvatarReplacementAsync(Icon icon) {
+ mAvatarReplacement = icon;
+ return () -> {};
+ }
+
+ @RemotableViewMethod(asyncImpl = "setNameReplacementAsync")
public void setNameReplacement(CharSequence nameReplacement) {
mNameReplacement = nameReplacement;
}
/**
+ * @hide
+ */
+ public Runnable setNameReplacementAsync(CharSequence nameReplacement) {
+ mNameReplacement = nameReplacement;
+ return () -> {};
+ }
+
+ /**
* Set this layout to show the collapsed representation.
*
* @param isCollapsed is it collapsed
*/
- @RemotableViewMethod
+ @RemotableViewMethod(asyncImpl = "setIsCollapsedAsync")
public void setIsCollapsed(boolean isCollapsed) {
mIsCollapsed = isCollapsed;
}
@@ -145,7 +161,6 @@
* setDataAsync needs to do different stuff for the collapsed vs expanded view, so store the
* collapsed state early.
*/
- @RemotableViewMethod(asyncImpl = "setIsCollapsedAsync")
public Runnable setIsCollapsedAsync(boolean isCollapsed) {
mIsCollapsed = isCollapsed;
return () -> {};
@@ -161,12 +176,20 @@
*
* @param conversationTitle the conversation title
*/
- @RemotableViewMethod
+ @RemotableViewMethod(asyncImpl = "setConversationTitleAsync")
public void setConversationTitle(CharSequence conversationTitle) {
mConversationTitle = conversationTitle;
}
/**
+ * @hide
+ */
+ public Runnable setConversationTitleAsync(CharSequence conversationTitle) {
+ mConversationTitle = conversationTitle;
+ return ()->{};
+ }
+
+ /**
* Set Messaging data
* @param extras Bundle contains messaging data
*/
@@ -314,19 +337,10 @@
}
private void updateImageMessages() {
- View newMessage = null;
if (mImageMessageContainer == null) {
return;
}
- if (mIsCollapsed && !mGroups.isEmpty()) {
- // When collapsed, we're displaying the image message in a dedicated container
- // on the right of the layout instead of inline. Let's add the isolated image there
- MessagingGroup messagingGroup = mGroups.getLast();
- MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
- if (isolatedMessage != null) {
- newMessage = isolatedMessage.getView();
- }
- }
+ View newMessage = getNewImageMessage();
// Remove all messages that don't belong into the image layout
View previousMessage = mImageMessageContainer.getChildAt(0);
if (previousMessage != newMessage) {
@@ -345,6 +359,20 @@
}
}
+ @Nullable
+ private View getNewImageMessage() {
+ if (mIsCollapsed && !mGroups.isEmpty()) {
+ // When collapsed, we're displaying the image message in a dedicated container
+ // on the right of the layout instead of inline. Let's add the isolated image there
+ MessagingGroup messagingGroup = mGroups.getLast();
+ MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
+ if (isolatedMessage != null) {
+ return isolatedMessage.getView();
+ }
+ }
+ return null;
+ }
+
private void removeGroups(ArrayList<MessagingGroup> oldGroups) {
int size = oldGroups.size();
for (int i = 0; i < size; i++) {
@@ -417,22 +445,44 @@
return mPeopleHelper.createAvatarSymbol(senderName, symbol, layoutColor);
}
- @RemotableViewMethod
+ @RemotableViewMethod(asyncImpl = "setLayoutColorAsync")
public void setLayoutColor(int color) {
mLayoutColor = color;
}
- @RemotableViewMethod
+ /**
+ * @hide
+ */
+ public Runnable setLayoutColorAsync(int color) {
+ mLayoutColor = color;
+ return () -> {};
+ }
+
+ @RemotableViewMethod(asyncImpl = "setIsOneToOneAsync")
public void setIsOneToOne(boolean oneToOne) {
mIsOneToOne = oneToOne;
}
- @RemotableViewMethod
+ /**
+ * @hide
+ */
+ public Runnable setIsOneToOneAsync(boolean oneToOne) {
+ mIsOneToOne = oneToOne;
+ return () -> {};
+ }
+
+ @RemotableViewMethod(asyncImpl = "setSenderTextColorAsync")
public void setSenderTextColor(int color) {
mSenderTextColor = color;
}
-
+ /**
+ * @hide
+ */
+ public Runnable setSenderTextColorAsync(int color) {
+ mSenderTextColor = color;
+ return () -> {};
+ }
/**
* @param color the color of the notification background
*/
@@ -441,11 +491,19 @@
// Nothing to do with this
}
- @RemotableViewMethod
+ @RemotableViewMethod(asyncImpl = "setMessageTextColorAsync")
public void setMessageTextColor(int color) {
mMessageTextColor = color;
}
+ /**
+ * @hide
+ */
+ public Runnable setMessageTextColorAsync(int color) {
+ mMessageTextColor = color;
+ return () -> {};
+ }
+
public void setUser(Person user) {
mUser = user;
if (mUser.getIcon() == null) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 06702e2..92a841f 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -76,6 +76,9 @@
srcs: [
"android_animation_PropertyValuesHolder.cpp",
"android_content_res_ApkAssets.cpp",
+ "android_media_ImageReader.cpp",
+ "android_media_PublicFormatUtils.cpp",
+ "android_media_Utils.cpp",
"android_os_SystemClock.cpp",
"android_os_SystemProperties.cpp",
"android_text_AndroidCharacter.cpp",
@@ -134,10 +137,7 @@
"android_app_ActivityThread.cpp",
"android_app_NativeActivity.cpp",
"android_app_admin_SecurityLog.cpp",
- "android_media_ImageReader.cpp",
"android_media_ImageWriter.cpp",
- "android_media_PublicFormatUtils.cpp",
- "android_media_Utils.cpp",
"android_opengl_EGL14.cpp",
"android_opengl_EGL15.cpp",
"android_opengl_EGLExt.cpp",
@@ -489,6 +489,7 @@
"libsqlite",
"libgui_window_info_static",
"libbinder",
+ "libbinder_ndk",
"libhidlbase", // libhwbinder is in here
],
version_script: "platform/linux/libandroid_runtime_export.txt",
diff --git a/core/jni/android_app_PropertyInvalidatedCache.cpp b/core/jni/android_app_PropertyInvalidatedCache.cpp
index 12585d5..6267522 100644
--- a/core/jni/android_app_PropertyInvalidatedCache.cpp
+++ b/core/jni/android_app_PropertyInvalidatedCache.cpp
@@ -35,7 +35,7 @@
return kMaxNonce;
}
-size_t NonceStore::getMaxByte() const {
+int32_t NonceStore::getMaxByte() const {
return kMaxByte;
}
@@ -68,13 +68,13 @@
}
// Copy the byte block to the target and return the current hash.
-int32_t NonceStore::getByteBlock(block_t* block, size_t len) const {
+int32_t NonceStore::getByteBlock(block_t* block, int32_t len) const {
memcpy(block, (void*) byteBlock(), std::min(kMaxByte, len));
return mByteHash;
}
// Set the byte block and the hash.
-void NonceStore::setByteBlock(int hash, const block_t* block, size_t len) {
+void NonceStore::setByteBlock(int hash, const block_t* block, int32_t len) {
memcpy((void*) byteBlock(), block, len = std::min(kMaxByte, len));
mByteHash = hash;
}
diff --git a/core/jni/android_app_PropertyInvalidatedCache.h b/core/jni/android_app_PropertyInvalidatedCache.h
index 54a4ac6..1d75182 100644
--- a/core/jni/android_app_PropertyInvalidatedCache.h
+++ b/core/jni/android_app_PropertyInvalidatedCache.h
@@ -27,8 +27,12 @@
* location. Fields with a variable location are found via offsets. The offsets make this
* object position-independent, which is required because it is in shared memory and would be
* mapped into different virtual addresses for different processes.
+ *
+ * This structure is shared between 64-bit and 32-bit processes. Therefore it is imperative
+ * that the structure not use any datatypes that are architecture-dependent (like size_t).
+ * Additionally, care must be taken to avoid unexpected padding in the structure.
*/
-class NonceStore {
+class alignas(8) NonceStore {
protected:
// A convenient typedef. The jbyteArray element type is jbyte, which the compiler treats as
// signed char.
@@ -43,23 +47,27 @@
// The value of an unset field.
static constexpr int UNSET = 0;
- // The size of the nonce array.
+ // The size of the nonce array. This and the following sizes are int32_t to
+ // be ABI independent.
const int32_t kMaxNonce;
// The size of the byte array.
- const size_t kMaxByte;
+ const int32_t kMaxByte;
// The offset to the nonce array.
- const size_t mNonceOffset;
+ const int32_t mNonceOffset;
// The offset to the byte array.
- const size_t mByteOffset;
+ const int32_t mByteOffset;
// The byte block hash. This is fixed and at a known offset, so leave it in the base class.
volatile std::atomic<int32_t> mByteHash;
+ // A 4-byte padd that makes the size of this structure a multiple of 8 bytes.
+ const int32_t _pad = 0;
+
// The constructor is protected! It only makes sense when called from a subclass.
- NonceStore(int kMaxNonce, size_t kMaxByte, volatile nonce_t* nonce, volatile block_t* block) :
+ NonceStore(int kMaxNonce, int kMaxByte, volatile nonce_t* nonce, volatile block_t* block) :
kMaxNonce(kMaxNonce),
kMaxByte(kMaxByte),
mNonceOffset(offset(this, const_cast<nonce_t*>(nonce))),
@@ -70,7 +78,7 @@
// These provide run-time access to the sizing parameters.
int getMaxNonce() const;
- size_t getMaxByte() const;
+ int getMaxByte() const;
// Fetch a nonce, returning UNSET if the index is out of range. This method specifically
// does not throw or generate an error if the index is out of range; this allows the method
@@ -86,10 +94,10 @@
int32_t getHash() const;
// Copy the byte block to the target and return the current hash.
- int32_t getByteBlock(block_t* block, size_t len) const;
+ int32_t getByteBlock(block_t* block, int32_t len) const;
// Set the byte block and the hash.
- void setByteBlock(int hash, const block_t* block, size_t len);
+ void setByteBlock(int hash, const block_t* block, int32_t len);
private:
@@ -113,6 +121,12 @@
}
};
+// Assert that the size of the object is fixed, independent of the CPU architecture. There are
+// four int32_t fields and one atomic<int32_t>, which sums to 20 bytes total. This assertion
+// uses a constant instead of computing the size of the objects in the compiler, to avoid
+// different answers on different architectures.
+static_assert(sizeof(NonceStore) == 24);
+
/**
* A cache nonce block contains an array of std::atomic<int64_t> and an array of bytes. The
* byte array has an associated hash. This class provides methods to read and write the fields
@@ -126,20 +140,22 @@
* The template is parameterized by the number of nonces it supports and the number of bytes in
* the string block.
*/
-template<int maxNonce, size_t maxByte> class CacheNonce : public NonceStore {
+template<int MAX_NONCE, int MAX_BYTE> class CacheNonce : public NonceStore {
// The array of nonces
- volatile nonce_t mNonce[maxNonce];
+ volatile nonce_t mNonce[MAX_NONCE];
// The byte array. This is not atomic but it is guarded by the mByteHash.
- volatile block_t mByteBlock[maxByte];
+ volatile block_t mByteBlock[MAX_BYTE];
public:
+ // Export the parameters for use in compiler assertions.
+ static constexpr int kMaxNonceCount = MAX_NONCE;
+ static constexpr int kMaxByteCount = MAX_BYTE;
+
// Construct and initialize the memory.
- CacheNonce() :
- NonceStore(maxNonce, maxByte, &mNonce[0], &mByteBlock[0])
- {
- for (int i = 0; i < maxNonce; i++) {
+ CacheNonce() : NonceStore(MAX_NONCE, MAX_BYTE, &mNonce[0], &mByteBlock[0]) {
+ for (int i = 0; i < MAX_NONCE; i++) {
mNonce[i] = UNSET;
}
mByteHash = UNSET;
@@ -155,4 +171,10 @@
typedef CacheNonce</* max nonce */ 128, /* byte block size */ 8192> SystemCacheNonce;
// LINT.ThenChange(/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java:system_nonce_config)
+// Verify that there is no padding in the final class.
+static_assert(sizeof(SystemCacheNonce) ==
+ sizeof(NonceStore)
+ + SystemCacheNonce::kMaxNonceCount*8
+ + SystemCacheNonce::kMaxByteCount);
+
} // namespace android.app.PropertyInvalidatedCache
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index a526783..1a7490e6 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -26,6 +26,7 @@
#include <nativehelper/JNIHelp.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
#include "core_jni_helpers.h"
@@ -124,7 +125,7 @@
static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName,
jboolean updateDestinationFrame) {
ScopedUtfChars name(env, jName);
- sp<BLASTBufferQueue> queue = new BLASTBufferQueue(name.c_str(), updateDestinationFrame);
+ sp<BLASTBufferQueue> queue = sp<BLASTBufferQueue>::make(name.c_str(), updateDestinationFrame);
queue->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(queue.get());
}
diff --git a/core/jni/android_media_ImageReader.cpp b/core/jni/android_media_ImageReader.cpp
index 20b9c57..a34cb39 100644
--- a/core/jni/android_media_ImageReader.cpp
+++ b/core/jni/android_media_ImageReader.cpp
@@ -25,13 +25,22 @@
#include <android_runtime/android_view_Surface.h>
#include <com_android_graphics_libgui_flags.h>
#include <cutils/atomic.h>
+#ifdef __ANDROID__
#include <grallocusage/GrallocUsageConversion.h>
+#else
+#define GRALLOC_USAGE_PROTECTED 0
+#define GRALLOC_USAGE_SW_READ_OFTEN 0
+#define GRALLOC_USAGE_SW_WRITE_OFTEN 0
+#endif
#include <gui/BufferItemConsumer.h>
#include <gui/Surface.h>
#include <inttypes.h>
#include <jni.h>
+#include <jni_wrappers.h>
#include <nativehelper/JNIHelp.h>
+#ifdef __ANDROID__
#include <private/android/AHardwareBufferHelpers.h>
+#endif
#include <stdint.h>
#include <ui/Rect.h>
#include <utils/List.h>
@@ -393,8 +402,12 @@
String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
width, height, nativeHalFormat, maxImages, getpid(),
createProcessUniqueId());
+#ifdef __ANDROID__
uint64_t consumerUsage =
android_hardware_HardwareBuffer_convertToGrallocUsageBits(ndkUsage);
+#else
+ uint64_t consumerUsage = 0;
+#endif
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
sp<BufferItemConsumer> bufferConsumer = new BufferItemConsumer(consumerUsage, maxImages,
@@ -773,6 +786,7 @@
return true;
}
+#ifdef __ANDROID__
static void ImageReader_unlockGraphicBuffer(JNIEnv* env, jobject /*thiz*/,
jobject buffer) {
sp<GraphicBuffer> graphicBuffer =
@@ -856,6 +870,7 @@
return imagePlanes;
}
+#endif
static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
int numPlanes, int halReaderFormat, uint64_t ndkReaderUsage)
@@ -964,6 +979,7 @@
}
}
+#ifdef __ANDROID__
static jobject Image_getHardwareBuffer(JNIEnv* env, jobject thiz) {
BufferItem* buffer = Image_getBufferItem(env, thiz);
if (buffer == nullptr) {
@@ -976,45 +992,48 @@
// to link against libandroid.so
return android_hardware_HardwareBuffer_createFromAHardwareBuffer(env, b);
}
+#endif
} // extern "C"
// ----------------------------------------------------------------------------
-static const JNINativeMethod gImageReaderMethods[] = {
- {"nativeClassInit", "()V", (void*)ImageReader_classInit },
- {"nativeInit", "(Ljava/lang/Object;IIIJII)V", (void*)ImageReader_init },
- {"nativeClose", "()V", (void*)ImageReader_close },
- {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
- {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup },
- {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface },
- {"nativeDetachImage", "(Landroid/media/Image;Z)I", (void*)ImageReader_detachImage },
- {"nativeCreateImagePlanes",
- "(ILandroid/graphics/GraphicBuffer;IIIIII)[Landroid/media/ImageReader$ImagePlane;",
- (void*)ImageReader_createImagePlanes },
- {"nativeUnlockGraphicBuffer",
- "(Landroid/graphics/GraphicBuffer;)V", (void*)ImageReader_unlockGraphicBuffer },
- {"nativeDiscardFreeBuffers", "()V", (void*)ImageReader_discardFreeBuffers }
-};
+static const JNINativeMethod gImageReaderMethods[] =
+ {{"nativeClassInit", "()V", (void*)ImageReader_classInit},
+ {"nativeInit", "(Ljava/lang/Object;IIIJII)V", (void*)ImageReader_init},
+ {"nativeClose", "()V", (void*)ImageReader_close},
+ {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease},
+ {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup},
+ {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface},
+ {"nativeDetachImage", "(Landroid/media/Image;Z)I", (void*)ImageReader_detachImage},
+#ifdef __ANDROID__
+ {"nativeCreateImagePlanes",
+ "(ILandroid/graphics/GraphicBuffer;IIIIII)[Landroid/media/ImageReader$ImagePlane;",
+ (void*)ImageReader_createImagePlanes},
+ {"nativeUnlockGraphicBuffer", "(Landroid/graphics/GraphicBuffer;)V",
+ (void*)ImageReader_unlockGraphicBuffer},
+#endif
+ {"nativeDiscardFreeBuffers", "()V", (void*)ImageReader_discardFreeBuffers}};
static const JNINativeMethod gImageMethods[] = {
- {"nativeCreatePlanes", "(IIJ)[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
- (void*)Image_createSurfacePlanes },
- {"nativeGetWidth", "()I", (void*)Image_getWidth },
- {"nativeGetHeight", "()I", (void*)Image_getHeight },
- {"nativeGetFormat", "(I)I", (void*)Image_getFormat },
- {"nativeGetFenceFd", "()I", (void*)Image_getFenceFd },
- {"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
- (void*)Image_getHardwareBuffer },
+ {"nativeCreatePlanes", "(IIJ)[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
+ (void*)Image_createSurfacePlanes},
+ {"nativeGetWidth", "()I", (void*)Image_getWidth},
+ {"nativeGetHeight", "()I", (void*)Image_getHeight},
+ {"nativeGetFormat", "(I)I", (void*)Image_getFormat},
+ {"nativeGetFenceFd", "()I", (void*)Image_getFenceFd},
+#ifdef __ANDROID__
+ {"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
+ (void*)Image_getHardwareBuffer},
+#endif
};
int register_android_media_ImageReader(JNIEnv *env) {
+ int ret1 = RegisterMethodsOrDie(env, "android/media/ImageReader", gImageReaderMethods,
+ NELEM(gImageReaderMethods));
- int ret1 = AndroidRuntime::registerNativeMethods(env,
- "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
-
- int ret2 = AndroidRuntime::registerNativeMethods(env,
- "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
+ int ret2 = RegisterMethodsOrDie(env, "android/media/ImageReader$SurfaceImage", gImageMethods,
+ NELEM(gImageMethods));
return (ret1 || ret2);
}
diff --git a/core/jni/android_media_PublicFormatUtils.cpp b/core/jni/android_media_PublicFormatUtils.cpp
index 04494ad..bcdf654 100644
--- a/core/jni/android_media_PublicFormatUtils.cpp
+++ b/core/jni/android_media_PublicFormatUtils.cpp
@@ -16,10 +16,10 @@
#define LOG_TAG "PublicFormatUtils_JNI"
-#include <utils/misc.h>
-#include <ui/PublicFormat.h>
-#include <android_runtime/AndroidRuntime.h>
#include <jni.h>
+#include <jni_wrappers.h>
+#include <ui/PublicFormat.h>
+#include <utils/misc.h>
using namespace android;
@@ -53,7 +53,6 @@
};
int register_android_media_PublicFormatUtils(JNIEnv *env) {
- return AndroidRuntime::registerNativeMethods(env,
- "android/media/PublicFormatUtils", gMethods, NELEM(gMethods));
+ return RegisterMethodsOrDie(env, "android/media/PublicFormatUtils", gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_media_Utils.cpp b/core/jni/android_media_Utils.cpp
index e8f8644..e484141 100644
--- a/core/jni/android_media_Utils.cpp
+++ b/core/jni/android_media_Utils.cpp
@@ -19,10 +19,12 @@
#include "android_media_Utils.h"
+#ifdef __ANDROID__ // Layoutlib does not support hardware
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
#include <ui/GraphicBufferMapper.h>
#include <ui/GraphicTypes.h>
+#endif
#include <utils/Log.h>
#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
@@ -34,7 +36,13 @@
// -----------Utility functions used by ImageReader/Writer JNI-----------------
+#ifdef __ANDROID__
using AidlPixelFormat = aidl::android::hardware::graphics::common::PixelFormat;
+#else
+namespace AidlPixelFormat {
+const int32_t YCBCR_P210 = 60;
+}
+#endif
enum {
IMAGE_MAX_NUM_PLANES = 3,
@@ -517,6 +525,7 @@
return OK;
}
+#ifdef __ANDROID__
static status_t extractP010Gralloc4PlaneLayout(
sp<GraphicBuffer> buffer, void *pData, int format, LockedImage *outputImage) {
using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
@@ -663,6 +672,7 @@
outputImage->chromaStep = 4;
return OK;
}
+#endif
status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
const Rect& rect, int fenceFd, LockedImage* outputImage) {
@@ -701,6 +711,7 @@
ALOGE("Lock buffer failed!");
return res;
}
+#ifdef __ANDROID__
if (isPossibly10BitYUV(format)) {
if (format == HAL_PIXEL_FORMAT_YCBCR_P010 &&
OK == extractP010Gralloc4PlaneLayout(buffer, pData, format, outputImage)) {
@@ -713,6 +724,7 @@
return OK;
}
}
+#endif
}
outputImage->data = reinterpret_cast<uint8_t*>(pData);
diff --git a/core/jni/android_os_PerfettoTrackEventExtra.cpp b/core/jni/android_os_PerfettoTrackEventExtra.cpp
index b8bdc8c..18f05ca 100644
--- a/core/jni/android_os_PerfettoTrackEventExtra.cpp
+++ b/core/jni/android_os_PerfettoTrackEventExtra.cpp
@@ -23,7 +23,8 @@
#include <nativehelper/utils.h>
#include <tracing_sdk.h>
-static constexpr ssize_t kMaxStrLen = 4096;
+#include <list>
+
namespace android {
template <typename T>
inline static T* toPointer(jlong ptr) {
@@ -35,24 +36,145 @@
return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
}
+/**
+ * @brief A thread-safe utility class for converting Java UTF-16 strings to ASCII in JNI
+ * environment.
+ *
+ * StringBuffer provides efficient conversion of Java strings to ASCII with optimized memory
+ * handling.
+ * It uses a two-tiered buffering strategy:
+ * 1. A fast path using pre-allocated thread-local buffers for strings up to 128 characters
+ * 2. A fallback path using dynamic allocation for longer strings
+ *
+ * Non-ASCII characters (>255) are replaced with '?' during conversion. The class maintains
+ * thread safety through thread-local storage and provides zero-copy string views for optimal
+ * performance.
+ *
+ * Memory Management:
+ * - Uses fixed-size thread-local buffers for both UTF-16 and ASCII characters
+ * - Overflow strings are stored in a thread-local list to maintain valid string views
+ * - Avoids unnecessary allocations in the common case of small strings
+ *
+ * Usage example:
+ * @code
+ * JNIEnv* env = ...;
+ * jstring java_string = ...;
+ * std::string_view ascii = StringBuffer::utf16_to_ascii(env, java_string);
+ * // Use the ASCII string...
+ * StringBuffer::reset(); // Clean up when done
+ * @endcode
+ *
+ * Thread Safety: All methods are thread-safe due to thread-local storage.
+ */
+class StringBuffer {
+private:
+ static constexpr size_t BASE_SIZE = 128;
+ // Temporarily stores the UTF-16 characters retrieved from the Java
+ // string before they are converted to ASCII.
+ static thread_local inline char char_buffer[BASE_SIZE];
+ // For fast-path conversions when the resulting ASCII string fits within
+ // the pre-allocated space. All ascii strings in a trace event will be stored
+ // here until emitted.
+ static thread_local inline jchar jchar_buffer[BASE_SIZE];
+ // When the fast-path conversion is not possible (because char_buffer
+ // doesn't have enough space), the converted ASCII string is stored
+ // in this list. We use list here to avoid moving the strings on resize
+ // with vector. This way, we can give out string_views from the stored strings.
+ // The additional overhead from list node allocations is fine cos we are already
+ // in an extremely unlikely path here and there are other bigger problems if here.
+ static thread_local inline std::list<std::string> overflow_strings;
+ // current offset into the char_buffer.
+ static thread_local inline size_t current_offset{0};
+ // This allows us avoid touching the overflow_strings directly in the fast path.
+ // Touching it causes some thread local init routine to run which shows up in profiles.
+ static thread_local inline bool is_overflow_strings_empty = true;
+
+ static void copy_utf16_to_ascii(const jchar* src, size_t len, char* dst, JNIEnv* env,
+ jstring str) {
+ std::transform(src, src + len, dst,
+ [](jchar c) { return (c <= 0xFF) ? static_cast<char>(c) : '?'; });
+
+ if (src != jchar_buffer) {
+ // We hit the slow path to populate src, so we have to release.
+ env->ReleaseStringCritical(str, src);
+ }
+ }
+
+public:
+ static void reset() {
+ if (!is_overflow_strings_empty) {
+ overflow_strings.clear();
+ is_overflow_strings_empty = true;
+ }
+ current_offset = 0;
+ }
+
+ // Converts a Java string (jstring) to an ASCII string_view. Characters
+ // outside the ASCII range (0-255) are replaced with '?'.
+ //
+ // @param env The JNI environment.
+ // @param val The Java string to convert.
+ // @return A string_view representing the ASCII version of the string.
+ // Returns an empty string_view if the input is null or empty.
+ static std::string_view utf16_to_ascii(JNIEnv* env, jstring val) {
+ if (!val) return "";
+
+ const jsize len = env->GetStringLength(val);
+ if (len == 0) return "";
+
+ const jchar* temp_buffer;
+
+ // Fast path: Enough space in jchar_buffer
+ if (static_cast<size_t>(len) <= BASE_SIZE) {
+ env->GetStringRegion(val, 0, len, jchar_buffer);
+ temp_buffer = jchar_buffer;
+ } else {
+ // Slow path: Fallback to asking ART for the string which will likely
+ // allocate and return a copy.
+ temp_buffer = env->GetStringCritical(val, nullptr);
+ }
+
+ const size_t next_offset = current_offset + len + 1;
+ // Fast path: Enough space in char_buffer
+ if (BASE_SIZE > next_offset) {
+ const size_t start_offset = current_offset;
+
+ copy_utf16_to_ascii(temp_buffer, len, char_buffer + current_offset, env, val);
+ char_buffer[current_offset + len] = '\0';
+
+ auto res = std::string_view(char_buffer + current_offset, len);
+ current_offset = next_offset;
+ return res;
+ } else {
+ // Slow path: Not enough space in char_buffer. Use overflow_strings.
+ // This will cause a string alloc but should be very unlikely to hit.
+ std::string& str = overflow_strings.emplace_back(len + 1, '\0');
+
+ copy_utf16_to_ascii(temp_buffer, len, str.data(), env, val);
+ is_overflow_strings_empty = false;
+ return std::string_view(str);
+ }
+ }
+};
+
static jlong android_os_PerfettoTrackEventExtraArgInt64_init(JNIEnv* env, jclass, jstring name) {
- ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
- return toJLong(new tracing_perfetto::DebugArg<int64_t>(name_chars.c_str()));
+ return toJLong(new tracing_perfetto::DebugArg<int64_t>(
+ StringBuffer::utf16_to_ascii(env, name).data()));
}
static jlong android_os_PerfettoTrackEventExtraArgBool_init(JNIEnv* env, jclass, jstring name) {
- ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
- return toJLong(new tracing_perfetto::DebugArg<bool>(name_chars.c_str()));
+ return toJLong(
+ new tracing_perfetto::DebugArg<bool>(StringBuffer::utf16_to_ascii(env, name).data()));
}
static jlong android_os_PerfettoTrackEventExtraArgDouble_init(JNIEnv* env, jclass, jstring name) {
- ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
- return toJLong(new tracing_perfetto::DebugArg<double>(name_chars.c_str()));
+ return toJLong(
+ new tracing_perfetto::DebugArg<double>(StringBuffer::utf16_to_ascii(env, name).data()));
}
static jlong android_os_PerfettoTrackEventExtraArgString_init(JNIEnv* env, jclass, jstring name) {
- ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
- return toJLong(new tracing_perfetto::DebugArg<const char*>(name_chars.c_str()));
+ return toJLong(new tracing_perfetto::DebugArg<const char*>(
+ StringBuffer::utf16_to_ascii(env, name).data()));
}
static jlong android_os_PerfettoTrackEventExtraArgInt64_delete() {
@@ -109,11 +231,9 @@
static void android_os_PerfettoTrackEventExtraArgString_set_value(JNIEnv* env, jclass, jlong ptr,
jstring val) {
- ScopedUtfChars val_chars = GET_UTF_OR_RETURN_VOID(env, val);
-
tracing_perfetto::DebugArg<const char*>* arg =
toPointer<tracing_perfetto::DebugArg<const char*>>(ptr);
- arg->set_value(strdup(val_chars.c_str()));
+ arg->set_value(StringBuffer::utf16_to_ascii(env, val).data());
}
static jlong android_os_PerfettoTrackEventExtraFieldInt64_init() {
@@ -186,11 +306,9 @@
static void android_os_PerfettoTrackEventExtraFieldString_set_value(JNIEnv* env, jclass, jlong ptr,
jlong id, jstring val) {
- ScopedUtfChars val_chars = GET_UTF_OR_RETURN_VOID(env, val);
-
tracing_perfetto::ProtoField<const char*>* field =
toPointer<tracing_perfetto::ProtoField<const char*>>(ptr);
- field->set_value(id, strdup(val_chars.c_str()));
+ field->set_value(id, StringBuffer::utf16_to_ascii(env, val).data());
}
static void android_os_PerfettoTrackEventExtraFieldNested_add_field(jlong field_ptr,
@@ -231,8 +349,9 @@
static jlong android_os_PerfettoTrackEventExtraNamedTrack_init(JNIEnv* env, jclass, jlong id,
jstring name, jlong parent_uuid) {
- ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
- return toJLong(new tracing_perfetto::NamedTrack(id, parent_uuid, name_chars.c_str()));
+ return toJLong(
+ new tracing_perfetto::NamedTrack(id, parent_uuid,
+ StringBuffer::utf16_to_ascii(env, name).data()));
}
static jlong android_os_PerfettoTrackEventExtraNamedTrack_delete() {
@@ -246,9 +365,10 @@
static jlong android_os_PerfettoTrackEventExtraCounterTrack_init(JNIEnv* env, jclass, jstring name,
jlong parent_uuid) {
- ScopedUtfChars name_chars = GET_UTF_OR_RETURN(env, name);
-
- return toJLong(new tracing_perfetto::RegisteredTrack(1, parent_uuid, name_chars.c_str(), true));
+ return toJLong(
+ new tracing_perfetto::RegisteredTrack(1, parent_uuid,
+ StringBuffer::utf16_to_ascii(env, name).data(),
+ true));
}
static jlong android_os_PerfettoTrackEventExtraCounterTrack_delete() {
@@ -318,11 +438,11 @@
static void android_os_PerfettoTrackEventExtra_emit(JNIEnv* env, jclass, jint type, jlong cat_ptr,
jstring name, jlong extra_ptr) {
- ScopedUtfChars name_chars = GET_UTF_OR_RETURN_VOID(env, name);
-
tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(cat_ptr);
- tracing_perfetto::trace_event(type, category->get(), name_chars.c_str(),
+ tracing_perfetto::trace_event(type, category->get(),
+ StringBuffer::utf16_to_ascii(env, name).data(),
toPointer<tracing_perfetto::Extra>(extra_ptr));
+ StringBuffer::reset();
}
static jlong android_os_PerfettoTrackEventExtraProto_init() {
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index b2649a4..a73ff42 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -424,6 +424,15 @@
assetmanager->SetDefaultLocale(default_locale_int);
}
+static void NativeSetOverlayConstraints(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr,
+ jint displayId, jint deviceId) {
+ ATRACE_NAME("AssetManager::SetDisplayIdAndDeviceId");
+
+ auto assetmanager = LockAndStartAssetManager(ptr);
+ assetmanager->SetOverlayConstraints(static_cast<int32_t>(displayId),
+ static_cast<int32_t>(deviceId));
+}
+
static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr,
jboolean includeOverlays,
jboolean includeLoaders) {
@@ -1554,6 +1563,7 @@
{"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;ZZ)V", (void*)NativeSetApkAssets},
{"nativeSetConfiguration", "(JIILjava/lang/String;[Ljava/lang/String;IIIIIIIIIIIIIIIIZ)V",
(void*)NativeSetConfiguration},
+ {"nativeSetOverlayConstraints", "(JII)V", (void*)NativeSetOverlayConstraints},
{"nativeGetAssignedPackageIdentifiers", "(JZZ)Landroid/util/SparseArray;",
(void*)NativeGetAssignedPackageIdentifiers},
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index b99b0ef..a8e51a7 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -765,28 +765,28 @@
std::vector<int32_t> dimensions;
std::vector<int32_t> sizes;
std::vector<int32_t> samplingKeys;
- int32_t fd = -1;
+ base::unique_fd fd;
if (jdimensionArray) {
jsize numLuts = env->GetArrayLength(jdimensionArray);
- ScopedIntArrayRW joffsets(env, joffsetArray);
+ ScopedIntArrayRO joffsets(env, joffsetArray);
if (joffsets.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from joffsetArray");
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRO from joffsetArray");
return;
}
- ScopedIntArrayRW jdimensions(env, jdimensionArray);
+ ScopedIntArrayRO jdimensions(env, jdimensionArray);
if (jdimensions.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jdimensionArray");
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRO from jdimensionArray");
return;
}
- ScopedIntArrayRW jsizes(env, jsizeArray);
+ ScopedIntArrayRO jsizes(env, jsizeArray);
if (jsizes.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsizeArray");
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRO from jsizeArray");
return;
}
- ScopedIntArrayRW jsamplingKeys(env, jsamplingKeyArray);
+ ScopedIntArrayRO jsamplingKeys(env, jsamplingKeyArray);
if (jsamplingKeys.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsamplingKeyArray");
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRO from jsamplingKeyArray");
return;
}
@@ -796,15 +796,15 @@
sizes = std::vector<int32_t>(jsizes.get(), jsizes.get() + numLuts);
samplingKeys = std::vector<int32_t>(jsamplingKeys.get(), jsamplingKeys.get() + numLuts);
- ScopedFloatArrayRW jbuffers(env, jbufferArray);
+ ScopedFloatArrayRO jbuffers(env, jbufferArray);
if (jbuffers.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedFloatArrayRW from jbufferArray");
+ jniThrowRuntimeException(env, "Failed to get ScopedFloatArrayRO from jbufferArray");
return;
}
// create the shared memory and copy jbuffers
size_t bufferSize = jbuffers.size() * sizeof(float);
- fd = ashmem_create_region("lut_shared_mem", bufferSize);
+ fd.reset(ashmem_create_region("lut_shared_mem", bufferSize));
if (fd < 0) {
jniThrowRuntimeException(env, "ashmem_create_region() failed");
return;
@@ -820,7 +820,7 @@
}
}
- transaction->setLuts(ctrl, base::unique_fd(fd), offsets, dimensions, sizes, samplingKeys);
+ transaction->setLuts(ctrl, std::move(fd), offsets, dimensions, sizes, samplingKeys);
}
static void nativeSetPictureProfileId(JNIEnv* env, jclass clazz, jlong transactionObj,
diff --git a/core/jni/com_android_internal_os_ApplicationSharedMemory.cpp b/core/jni/com_android_internal_os_ApplicationSharedMemory.cpp
index cc1687c..71d1694 100644
--- a/core/jni/com_android_internal_os_ApplicationSharedMemory.cpp
+++ b/core/jni/com_android_internal_os_ApplicationSharedMemory.cpp
@@ -23,18 +23,67 @@
#include <string.h>
#include <sys/mman.h>
+#include <array>
#include <atomic>
#include <cstddef>
#include <new>
-#include "core_jni_helpers.h"
-
#include "android_app_PropertyInvalidatedCache.h"
+#include "core_jni_helpers.h"
namespace {
using namespace android::app::PropertyInvalidatedCache;
+class alignas(8) SystemFeaturesCache {
+public:
+ // We only need enough space to handle the official set of SDK-defined system features (~200).
+ // TODO(b/326623529): Reuse the exact value defined by PackageManager.SDK_FEATURE_COUNT.
+ static constexpr int32_t kMaxSystemFeatures = 512;
+
+ void writeSystemFeatures(JNIEnv* env, jintArray jfeatures) {
+ if (featuresLength.load(std::memory_order_seq_cst) > 0) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "SystemFeaturesCache already written.");
+ return;
+ }
+
+ int32_t jfeaturesLength = env->GetArrayLength(jfeatures);
+ if (jfeaturesLength > kMaxSystemFeatures) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "SystemFeaturesCache only supports %d elements (vs %d requested).",
+ kMaxSystemFeatures, jfeaturesLength);
+ return;
+ }
+ env->GetIntArrayRegion(jfeatures, 0, jfeaturesLength, features.data());
+ featuresLength.store(jfeaturesLength, std::memory_order_seq_cst);
+ }
+
+ jintArray readSystemFeatures(JNIEnv* env) const {
+ jint jfeaturesLength = static_cast<jint>(featuresLength.load(std::memory_order_seq_cst));
+ jintArray jfeatures = env->NewIntArray(jfeaturesLength);
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+
+ env->SetIntArrayRegion(jfeatures, 0, jfeaturesLength, features.data());
+ return jfeatures;
+ }
+
+private:
+ // A fixed length array of feature versions, with |featuresLength| dictating the actual size
+ // of features that have been written.
+ std::array<int32_t, kMaxSystemFeatures> features = {};
+ // The atomic acts as a barrier that precedes reads and follows writes, ensuring a
+ // consistent view of |features| across processes. Note that r/w synchronization *within* a
+ // process is handled at a higher level.
+ std::atomic<int64_t> featuresLength = 0;
+};
+
+static_assert(sizeof(SystemFeaturesCache) ==
+ sizeof(int32_t) * SystemFeaturesCache::kMaxSystemFeatures + sizeof(int64_t),
+ "Unexpected SystemFeaturesCache size");
+
// Atomics should be safe to use across processes if they are lock free.
static_assert(std::atomic<int64_t>::is_always_lock_free == true,
"atomic<int64_t> is not always lock free");
@@ -69,14 +118,25 @@
latestNetworkTimeUnixEpochMillisAtZeroElapsedRealtimeMillis = offset;
}
+ // The fixed size cache storage for SDK-defined system features.
+ SystemFeaturesCache systemFeaturesCache;
+
// The nonce storage for pic. The sizing is suitable for the system server module.
SystemCacheNonce systemPic;
};
-// Update the expected value when modifying the members of SharedMemory.
+// Update the expected values when modifying the members of SharedMemory.
// The goal of this assertion is to ensure that the data structure is the same size across 32-bit
// and 64-bit systems.
-static_assert(sizeof(SharedMemory) == 8 + sizeof(SystemCacheNonce), "Unexpected SharedMemory size");
+// TODO(b/396674280): Add an additional fixed size check for SystemCacheNonce after resolving
+// ABI discrepancies.
+static_assert(sizeof(SharedMemory) == 8 + sizeof(SystemFeaturesCache) + sizeof(SystemCacheNonce),
+ "Unexpected SharedMemory size");
+static_assert(offsetof(SharedMemory, systemFeaturesCache) == sizeof(int64_t),
+ "Unexpected SystemFeaturesCache offset in SharedMemory");
+static_assert(offsetof(SharedMemory, systemPic) ==
+ offsetof(SharedMemory, systemFeaturesCache) + sizeof(SystemFeaturesCache),
+ "Unexpected SystemCachceNonce offset in SharedMemory");
static jint nativeCreate(JNIEnv* env, jclass) {
// Create anonymous shared memory region
@@ -146,6 +206,16 @@
return reinterpret_cast<jlong>(&sharedMemory->systemPic);
}
+static void nativeWriteSystemFeaturesCache(JNIEnv* env, jclass*, jlong ptr, jintArray jfeatures) {
+ SharedMemory* sharedMemory = reinterpret_cast<SharedMemory*>(ptr);
+ sharedMemory->systemFeaturesCache.writeSystemFeatures(env, jfeatures);
+}
+
+static jintArray nativeReadSystemFeaturesCache(JNIEnv* env, jclass*, jlong ptr) {
+ SharedMemory* sharedMemory = reinterpret_cast<SharedMemory*>(ptr);
+ return sharedMemory->systemFeaturesCache.readSystemFeatures(env);
+}
+
static const JNINativeMethod gMethods[] = {
{"nativeCreate", "()I", (void*)nativeCreate},
{"nativeMap", "(IZ)J", (void*)nativeMap},
@@ -156,7 +226,9 @@
(void*)nativeSetLatestNetworkTimeUnixEpochMillisAtZeroElapsedRealtimeMillis},
{"nativeGetLatestNetworkTimeUnixEpochMillisAtZeroElapsedRealtimeMillis", "(J)J",
(void*)nativeGetLatestNetworkTimeUnixEpochMillisAtZeroElapsedRealtimeMillis},
- {"nativeGetSystemNonceBlock", "(J)J", (void*) nativeGetSystemNonceBlock},
+ {"nativeGetSystemNonceBlock", "(J)J", (void*)nativeGetSystemNonceBlock},
+ {"nativeWriteSystemFeaturesCache", "(J[I)V", (void*)nativeWriteSystemFeaturesCache},
+ {"nativeReadSystemFeaturesCache", "(J)[I", (void*)nativeReadSystemFeaturesCache},
};
static const char kApplicationSharedMemoryClassName[] =
diff --git a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
index 7ffe0ed..7d94ef8 100644
--- a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
+++ b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
@@ -97,7 +97,13 @@
static void native_incrementValues(JNIEnv *env, jclass, jlong nativePtr, jlongArray values,
jlong timestamp) {
auto *counter = reinterpret_cast<LongArrayMultiStateCounter *>(nativePtr);
- counter->incrementValue(JavaUint64Array(env, values), timestamp);
+ if (values != nullptr) {
+ counter->incrementValue(JavaUint64Array(env, values), timestamp);
+ } else {
+ // Pass an empty Uint64Array, which is equivalent to an array of zeros.
+ // This is done to ensure that the timestamp is still updated in the counter.
+ counter->incrementValue(Uint64Array(), timestamp);
+ }
}
static void native_addCounts(JNIEnv *env, jclass, jlong nativePtr, jlongArray values) {
@@ -110,17 +116,26 @@
counter->reset();
}
-static void native_getCounts(JNIEnv *env, jclass, jlong nativePtr, jlongArray values, jint state) {
+static bool native_getCounts(JNIEnv *env, jclass, jlong nativePtr, jlongArray values, jint state) {
auto *counter = reinterpret_cast<LongArrayMultiStateCounter *>(nativePtr);
- ScopedLongArrayRW scopedArray(env, values);
auto *data = counter->getCount(state).data();
- auto size = env->GetArrayLength(values);
- auto *outData = scopedArray.get();
if (data == nullptr) {
- memset(outData, 0, size * sizeof(uint64_t));
- } else {
- memcpy(outData, data, size * sizeof(uint64_t));
+ return false;
}
+ auto size = env->GetArrayLength(values);
+ bool allZeros = true;
+ for (int i = 0; i < size; i++) {
+ if (data[i]) {
+ allZeros = false;
+ break;
+ }
+ }
+ if (allZeros) {
+ return false;
+ }
+ ScopedLongArrayRW scopedArray(env, values);
+ memcpy(scopedArray.get(), data, size * sizeof(uint64_t));
+ return true;
}
static jobject native_toString(JNIEnv *env, jclass, jlong nativePtr) {
@@ -249,7 +264,7 @@
// @CriticalNative
{"native_reset", "(J)V", (void *)native_reset},
// @FastNative
- {"native_getCounts", "(J[JI)V", (void *)native_getCounts},
+ {"native_getCounts", "(J[JI)Z", (void *)native_getCounts},
// @FastNative
{"native_toString", "(J)Ljava/lang/String;", (void *)native_toString},
// @FastNative
diff --git a/core/jni/jni_wrappers.h b/core/jni/jni_wrappers.h
index e3e17ee..1f44994 100644
--- a/core/jni/jni_wrappers.h
+++ b/core/jni/jni_wrappers.h
@@ -22,6 +22,8 @@
#include <log/log.h>
#include <nativehelper/JNIHelp.h>
+#include <string>
+
namespace android {
static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
diff --git a/core/jni/platform/host/HostRuntime.cpp b/core/jni/platform/host/HostRuntime.cpp
index 1a03283..746740b 100644
--- a/core/jni/platform/host/HostRuntime.cpp
+++ b/core/jni/platform/host/HostRuntime.cpp
@@ -48,6 +48,8 @@
* (see AndroidRuntime.cpp).
*/
+extern int register_android_media_ImageReader(JNIEnv* env);
+extern int register_android_media_PublicFormatUtils(JNIEnv* env);
extern int register_android_os_Binder(JNIEnv* env);
extern int register_libcore_util_NativeAllocationRegistry(JNIEnv* env);
@@ -126,6 +128,10 @@
{"android.database.sqlite.SQLiteDebug", REG_JNI(register_android_database_SQLiteDebug)},
{"android.database.sqlite.SQLiteRawStatement",
REG_JNI(register_android_database_SQLiteRawStatement)},
+#endif
+ {"android.media.ImageReader", REG_JNI(register_android_media_ImageReader)},
+ {"android.media.PublicFormatUtils", REG_JNI(register_android_media_PublicFormatUtils)},
+#ifdef __linux__
{"android.os.Binder", REG_JNI(register_android_os_Binder)},
{"android.os.FileObserver", REG_JNI(register_android_os_FileObserver)},
{"android.os.MessageQueue", REG_JNI(register_android_os_MessageQueue)},
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index b51f72d..aa8f841 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -5,7 +5,6 @@
singhtejinder@google.com
yanmin@google.com
yaochen@google.com
-yro@google.com
zhouwenjie@google.com
# Frameworks
diff --git a/core/proto/android/providers/settings/common.proto b/core/proto/android/providers/settings/common.proto
index 64ffefb6..931192e 100644
--- a/core/proto/android/providers/settings/common.proto
+++ b/core/proto/android/providers/settings/common.proto
@@ -37,6 +37,9 @@
// Whether the default is set by the system
optional bool default_from_system = 6;
+
+ // Whether the value is ignored when restoring from backup
+ optional bool preserved_in_restore = 7;
}
message SettingsOperationProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 78526ad..ee6899c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7759,7 +7759,17 @@
@FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")
@hide -->
<permission android:name="android.permission.READ_BLOCKED_NUMBERS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature"
+ android:featureFlag="!android.permission.flags.grant_read_blocked_numbers_to_system_ui_intelligence" />
+
+ <!-- Allows the holder to read blocked numbers. See
+ {@link android.provider.BlockedNumberContract}.
+ @SystemApi
+ @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")
+ @hide -->
+ <permission android:name="android.permission.READ_BLOCKED_NUMBERS"
+ android:protectionLevel="signature|role"
+ android:featureFlag="android.permission.flags.grant_read_blocked_numbers_to_system_ui_intelligence" />
<!-- Allows the holder to write blocked numbers. See
{@link android.provider.BlockedNumberContract}.
diff --git a/core/res/res/drawable-w192dp/loader_horizontal_watch.xml b/core/res/res/drawable-w192dp/loader_horizontal_watch.xml
deleted file mode 100644
index 18cea6e..0000000
--- a/core/res/res/drawable-w192dp/loader_horizontal_watch.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector android:height="15dp" android:width="67dp" android:viewportHeight="15" android:viewportWidth="67">
- <group android:name="_R_G">
- <group android:name="_R_G_L_1_G" android:translateX="33.5" android:translateY="7.5">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M33.5 -7.5 C33.5,-7.5 33.5,7.5 33.5,7.5 C33.5,7.5 -33.5,7.5 -33.5,7.5 C-33.5,7.5 -33.5,-7.5 -33.5,-7.5 C-33.5,-7.5 33.5,-7.5 33.5,-7.5c "/>
- </group>
- <group android:name="_R_G_L_0_G" android:translateX="-296.5" android:translateY="-62.5" android:pivotX="330" android:pivotY="70" android:scaleX="0.1" android:scaleY="0.1">
- <group android:name="_R_G_L_0_G_L_6_G" android:translateX="-224.84700000000004" android:translateY="-321.948" android:pivotX="555.09" android:pivotY="-329" android:rotation="28.9" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_6_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M194.88 359 C190,359 185.05,357.81 180.48,355.3 C59.86,289.14 -41.55,191.9 -112.79,74.11 C-186.14,-47.16 -224.91,-186.55 -224.91,-329 C-224.91,-345.57 -211.48,-359 -194.91,-359 C-178.34,-359 -164.91,-345.57 -164.91,-329 C-164.91,-197.5 -129.13,-68.84 -61.45,43.06 C4.33,151.82 97.97,241.6 209.33,302.69 C223.86,310.66 229.18,328.9 221.21,343.42 C215.75,353.37 205.48,359 194.88,359c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_5_G" android:translateX="744.323" android:translateY="-277.96299999999997" android:pivotX="-414.08" android:pivotY="-372.985" android:rotation="28.9">
- <path android:name="_R_G_L_0_G_L_5_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-335.95 402.99 C-351.13,402.99 -364.16,391.5 -365.76,376.07 C-367.46,359.59 -355.49,344.85 -339.01,343.14 C-162.93,324.91 -0.15,242.33 119.34,110.62 C239.66,-22.01 305.92,-193.76 305.92,-372.98 C305.92,-389.55 319.35,-402.98 335.92,-402.98 C352.49,-402.98 365.92,-389.55 365.92,-372.98 C365.92,-178.82 294.13,7.24 163.78,150.93 C34.34,293.61 -142.03,383.07 -332.83,402.82 C-333.88,402.93 -334.92,402.99 -335.95,402.99c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_2_G" android:translateX="185.385" android:translateY="70.09100000000001" android:pivotX="144.858" android:pivotY="-721.039" android:rotation="28.9" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M144.62 58.96 C144.61,58.96 144.61,58.96 144.6,58.96 C40.39,58.93 -60.82,38.66 -156.19,-1.28 C-171.48,-7.68 -178.68,-25.26 -172.28,-40.54 C-165.88,-55.82 -148.3,-63.02 -133.02,-56.62 C-45.02,-19.77 48.4,-1.07 144.63,-1.04 C161.19,-1.03 174.62,12.4 174.62,28.97 C174.61,45.53 161.18,58.96 144.62,58.96c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_0_G" android:translateX="330" android:translateY="70">
- <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-660 -313 C-660,-313 -660,313 -660,313 C-660,313 660,313 660,313 C660,313 660,-313 660,-313 C660,-313 -660,-313 -660,-313c M300.74 -1.16 C205.46,38.62 103.22,59.09 -0.03,59.05 C-103.28,59.01 -205.51,38.48 -300.76,-1.37 C-316.05,-7.76 -323.26,-25.34 -316.86,-40.62 C-310.47,-55.91 -292.9,-63.12 -277.61,-56.72 C-189.68,-19.94 -95.32,-0.98 -0.01,-0.95 C95.3,-0.92 189.67,-19.81 277.63,-56.53 C292.92,-62.91 310.49,-55.69 316.87,-40.4 C323.25,-25.11 316.03,-7.54 300.74,-1.16c "/>
- </group>
- </group>
- </group>
- <group android:name="time_group"/>
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.9" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.135 0.202,0.848 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.9" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.135 0.202,0.848 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.9" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.135 0.202,0.848 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="translateX" android:duration="1000" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
-
diff --git a/core/res/res/drawable-w204dp/loader_horizontal_watch.xml b/core/res/res/drawable-w204dp/loader_horizontal_watch.xml
deleted file mode 100644
index fbc6eab..0000000
--- a/core/res/res/drawable-w204dp/loader_horizontal_watch.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector android:height="15dp" android:width="70dp" android:viewportHeight="15" android:viewportWidth="70">
- <group android:name="_R_G">
- <group android:name="_R_G_L_1_G" android:translateX="35" android:translateY="7.5">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M35 -7.5 C35,-7.5 35,7.5 35,7.5 C35,7.5 -35,7.5 -35,7.5 C-35,7.5 -35,-7.5 -35,-7.5 C-35,-7.5 35,-7.5 35,-7.5c "/>
- </group>
- <group android:name="_R_G_L_0_G" android:translateX="-310" android:translateY="-64" android:pivotX="345" android:pivotY="71.5" android:scaleX="0.1" android:scaleY="0.1">
- <group android:name="_R_G_L_0_G_L_6_G" android:translateX="-239.44799999999998" android:translateY="-341.45" android:pivotX="584.448" android:pivotY="-346.55" android:rotation="28.8" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_6_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M205.28 376.55 C200.4,376.55 195.46,375.36 190.88,372.85 C64.08,303.29 -42.54,201.07 -117.44,77.24 C-194.55,-50.25 -235.31,-196.79 -235.31,-346.55 C-235.31,-363.12 -221.88,-376.55 -205.31,-376.55 C-188.74,-376.55 -175.31,-363.12 -175.31,-346.55 C-175.31,-207.74 -137.54,-71.93 -66.1,46.19 C3.34,160.99 102.18,255.76 219.73,320.24 C234.26,328.21 239.58,346.45 231.61,360.97 C226.15,370.92 215.88,376.55 205.28,376.55c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_5_G" android:translateX="781.413" android:translateY="-295.124" android:pivotX="-436.413" android:pivotY="-392.876" android:rotation="28.8">
- <path android:name="_R_G_L_0_G_L_5_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-353.86 422.88 C-369.04,422.88 -382.07,411.4 -383.67,395.97 C-385.37,379.49 -373.4,364.74 -356.92,363.03 C-171.06,343.79 0.76,256.62 126.89,117.59 C253.89,-22.41 323.83,-203.7 323.83,-392.88 C323.83,-409.44 337.26,-422.88 353.83,-422.88 C370.4,-422.88 383.83,-409.44 383.83,-392.88 C383.83,-188.76 308.36,6.84 171.32,157.9 C35.25,307.89 -150.15,401.94 -350.74,422.72 C-351.79,422.82 -352.83,422.88 -353.86,422.88c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_2_G" android:translateX="192.671" android:translateY="71.49599999999998" android:pivotX="152.329" android:pivotY="-759.496" android:rotation="28.8" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M152.33 60.5 C152.33,60.5 152.32,60.5 152.32,60.5 C42.76,60.47 -63.64,39.16 -163.91,-2.82 C-179.19,-9.22 -186.39,-26.8 -179.99,-42.08 C-173.59,-57.36 -156.02,-64.57 -140.73,-58.16 C-47.84,-19.27 50.77,0.47 152.34,0.5 C168.91,0.51 182.33,13.94 182.33,30.51 C182.32,47.08 168.89,60.5 152.33,60.5c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_0_G" android:translateX="345" android:translateY="71.5">
- <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-579 -259.5 C-579,-259.5 -579,259.5 -579,259.5 C-579,259.5 579,259.5 579,259.5 C579,259.5 579,-259.5 579,-259.5 C579,-259.5 -579,-259.5 -579,-259.5c M316.17 -2.8 C216,39.02 108.52,60.54 -0.03,60.5 C-108.58,60.46 -216.04,38.87 -316.18,-3.02 C-331.47,-9.41 -338.68,-26.99 -332.28,-42.27 C-325.89,-57.56 -308.32,-64.76 -293.03,-58.37 C-200.22,-19.55 -100.61,0.46 -0.01,0.5 C100.6,0.54 200.22,-19.41 293.06,-58.17 C308.35,-64.55 325.92,-57.33 332.3,-42.04 C338.68,-26.75 331.46,-9.18 316.17,-2.8c "/>
- </group>
- </group>
- </group>
- <group android:name="time_group"/>
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.8" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.8" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.8" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="translateX" android:duration="1000" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
-
diff --git a/core/res/res/drawable-w216dp/loader_horizontal_watch.xml b/core/res/res/drawable-w216dp/loader_horizontal_watch.xml
deleted file mode 100644
index ed4b7ea..0000000
--- a/core/res/res/drawable-w216dp/loader_horizontal_watch.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector android:height="16dp" android:width="74dp" android:viewportHeight="16" android:viewportWidth="74">
- <group android:name="_R_G">
- <group android:name="_R_G_L_1_G" android:translateX="37" android:translateY="8">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M37 -8 C37,-8 37,8 37,8 C37,8 -37,8 -37,8 C-37,8 -37,-8 -37,-8 C-37,-8 37,-8 37,-8c "/>
- </group>
- <group android:name="_R_G_L_0_G" android:translateX="-328" android:translateY="-65.5" android:pivotX="365" android:pivotY="73.5" android:scaleX="0.1" android:scaleY="0.1">
- <group android:name="_R_G_L_0_G_L_6_G" android:translateX="-256.447" android:translateY="-365.014" android:pivotX="621.447" android:pivotY="-368.486" android:rotation="28.8" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_6_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M218.28 398.49 C213.4,398.49 208.46,397.3 203.88,394.78 C69.34,320.99 -43.78,212.53 -123.25,81.15 C-205.06,-54.11 -248.31,-209.59 -248.31,-368.49 C-248.31,-385.05 -234.88,-398.49 -218.31,-398.49 C-201.74,-398.49 -188.31,-385.05 -188.31,-368.49 C-188.31,-220.54 -148.06,-75.8 -71.91,50.09 C2.1,172.45 107.45,273.45 232.73,342.18 C247.26,350.15 252.58,368.38 244.61,382.91 C239.15,392.86 228.88,398.49 218.28,398.49c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_5_G" android:translateX="829.0260000000001" android:translateY="-315.759" android:pivotX="-464.026" android:pivotY="-417.741" android:rotation="28.8">
- <path android:name="_R_G_L_0_G_L_5_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-376.25 447.74 C-391.43,447.74 -404.46,436.26 -406.05,420.83 C-407.76,404.35 -395.78,389.61 -379.3,387.9 C-181.22,367.38 1.9,274.48 136.32,126.3 C271.67,-22.9 346.22,-216.12 346.22,-417.74 C346.22,-434.31 359.65,-447.74 376.22,-447.74 C392.79,-447.74 406.22,-434.31 406.22,-417.74 C406.22,-201.18 326.15,6.35 180.76,166.61 C36.39,325.75 -160.31,425.54 -373.12,447.58 C-374.17,447.69 -375.22,447.74 -376.25,447.74c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_2_G" android:translateX="203.029" android:translateY="74.06899999999996" android:pivotX="161.971" android:pivotY="-807.569" android:rotation="28.8" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M161.97 62.43 C161.97,62.43 161.96,62.43 161.96,62.43 C45.71,62.4 -67.17,39.79 -173.55,-4.75 C-188.83,-11.15 -196.03,-28.72 -189.63,-44.01 C-183.24,-59.29 -165.66,-66.49 -150.38,-60.09 C-51.37,-18.64 53.72,2.4 161.98,2.43 C178.55,2.44 191.98,15.87 191.97,32.44 C191.97,49 178.54,62.43 161.97,62.43c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_0_G" android:translateX="365" android:translateY="73.5">
- <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-609 -244.5 C-609,-244.5 -609,244.5 -609,244.5 C-609,244.5 609,244.5 609,244.5 C609,244.5 609,-244.5 609,-244.5 C609,-244.5 -609,-244.5 -609,-244.5c M335.44 -4.16 C229.17,40.21 115.13,63.04 -0.04,63 C-115.21,62.96 -229.22,40.05 -335.47,-4.39 C-350.76,-10.79 -357.95,-28.36 -351.56,-43.65 C-345.17,-58.93 -327.59,-66.14 -312.31,-59.74 C-213.39,-18.36 -107.24,2.96 -0.02,3 C107.21,3.04 213.38,-18.22 312.33,-59.53 C327.62,-65.91 345.19,-58.69 351.57,-43.4 C357.95,-28.11 350.73,-10.54 335.44,-4.16c "/>
- </group>
- </group>
- </group>
- <group android:name="time_group"/>
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.8" android:valueTo="-51.3" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.8" android:valueTo="-51.3" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.8" android:valueTo="-51.3" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="translateX" android:duration="1000" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
-
-
diff --git a/core/res/res/drawable-w228dp/loader_horizontal_watch.xml b/core/res/res/drawable-w228dp/loader_horizontal_watch.xml
deleted file mode 100644
index 6b86c63..0000000
--- a/core/res/res/drawable-w228dp/loader_horizontal_watch.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector android:height="14dp" android:width="76dp" android:viewportHeight="14" android:viewportWidth="76">
- <group android:name="_R_G">
- <group android:name="_R_G_L_1_G" android:translateX="39" android:translateY="8">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M39 -8 C39,-8 39,8 39,8 C39,8 -39,8 -39,8 C-39,8 -39,-8 -39,-8 C-39,-8 39,-8 39,-8c "/>
- </group>
- <group android:name="_R_G_L_0_G" android:translateX="-345" android:translateY="-67" android:pivotX="384" android:pivotY="75" android:scaleX="0.1" android:scaleY="0.1">
- <group android:name="_R_G_L_0_G_L_6_G" android:translateX="-274.19" android:translateY="-390.077" android:pivotX="658.448" android:pivotY="-390.423" android:rotation="28.7" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_6_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M231.28 420.42 C226.4,420.42 221.45,419.23 216.88,416.72 C74.61,338.68 -45.02,224 -129.06,85.06 C-171.54,14.82 -204.38,-60.73 -226.66,-139.5 C-249.65,-220.76 -261.31,-305.18 -261.31,-390.42 C-261.31,-406.99 -247.88,-420.42 -231.31,-420.42 C-214.74,-420.42 -201.31,-406.99 -201.31,-390.42 C-201.31,-310.71 -190.42,-231.78 -168.93,-155.83 C-148.11,-82.23 -117.42,-11.63 -77.72,54 C0.86,183.92 112.71,291.15 245.73,364.12 C260.26,372.08 265.58,390.32 257.61,404.85 C252.15,414.79 241.88,420.42 231.28,420.42c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_5_G" android:translateX="875.8979999999999" android:translateY="-337.894" android:pivotX="-491.64" android:pivotY="-442.606" android:rotation="28.7">
- <path android:name="_R_G_L_0_G_L_5_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-398.64 472.61 C-413.82,472.61 -426.84,461.13 -428.44,445.7 C-430.15,429.22 -418.17,414.47 -401.69,412.77 C-191.38,390.98 3.04,292.33 145.75,135.01 C289.46,-23.4 368.6,-228.54 368.6,-442.61 C368.6,-459.17 382.04,-472.61 398.6,-472.61 C415.17,-472.61 428.6,-459.17 428.6,-442.61 C428.6,-213.6 343.93,5.85 190.19,175.33 C37.53,343.61 -170.48,449.13 -395.51,472.44 C-396.56,472.55 -397.6,472.61 -398.64,472.61c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_2_G" android:translateX="212.64499999999998" android:translateY="75.14200000000005" android:pivotX="171.613" android:pivotY="-855.642" android:rotation="28.7" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M171.61 64.36 C171.61,64.36 171.61,64.36 171.61,64.36 C48.68,64.32 -70.7,40.42 -183.19,-6.68 C-198.47,-13.07 -205.68,-30.65 -199.28,-45.93 C-192.88,-61.22 -175.3,-68.42 -160.02,-62.02 C-54.9,-18.01 56.68,4.33 171.62,4.36 C188.19,4.36 201.62,17.8 201.61,34.36 C201.61,50.93 188.18,64.36 171.61,64.36c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_0_G" android:translateX="384" android:translateY="75">
- <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-611 -259 C-611,-259 -611,259 -611,259 C-611,259 611,259 611,259 C611,259 611,-259 611,-259 C611,-259 -611,-259 -611,-259c M354.66 -6.52 C242.36,40.4 121.76,64.54 -0.04,64.5 C-121.84,64.46 -242.44,40.23 -354.74,-6.76 C-370.04,-13.16 -377.24,-30.73 -370.84,-46.02 C-364.44,-61.3 -346.94,-68.51 -331.64,-62.12 C-226.54,-18.18 -113.84,4.46 -0.04,4.5 C113.76,4.54 226.56,-18.02 331.56,-61.89 C346.86,-68.27 364.46,-61.05 370.86,-45.76 C377.26,-30.47 369.96,-12.9 354.66,-6.52c "/>
- </group>
- </group>
- </group>
- <group android:name="time_group"/>
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="translateX" android:duration="1000" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
diff --git a/core/res/res/drawable-w240dp/loader_horizontal_watch.xml b/core/res/res/drawable-w240dp/loader_horizontal_watch.xml
deleted file mode 100644
index ad60bbd..0000000
--- a/core/res/res/drawable-w240dp/loader_horizontal_watch.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector android:height="17dp" android:width="82dp" android:viewportHeight="17" android:viewportWidth="82">
- <group android:name="_R_G">
- <group android:name="_R_G_L_1_G" android:translateX="41" android:translateY="8.5">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M41 -8.5 C41,-8.5 41,8.5 41,8.5 C41,8.5 -41,8.5 -41,8.5 C-41,8.5 -41,-8.5 -41,-8.5 C-41,-8.5 41,-8.5 41,-8.5c "/>
- </group>
- <group android:name="_R_G_L_0_G" android:translateX="-362.5" android:translateY="-69" android:pivotX="403.5" android:pivotY="77.5" android:scaleX="0.1" android:scaleY="0.1">
- <group android:name="_R_G_L_0_G_L_6_G" android:translateX="-291.64799999999997" android:translateY="-414.141" android:pivotX="695.448" android:pivotY="-412.359" android:rotation="28.7" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_6_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M244.28 442.36 C239.4,442.36 234.45,441.17 229.88,438.66 C79.87,356.38 -46.26,235.46 -134.87,88.96 C-179.66,14.91 -214.28,-64.74 -237.78,-147.79 C-262.02,-233.47 -274.31,-322.49 -274.31,-412.36 C-274.31,-428.93 -260.88,-442.36 -244.31,-442.36 C-227.74,-442.36 -214.31,-428.93 -214.31,-412.36 C-214.31,-328.01 -202.78,-244.49 -180.05,-164.12 C-158.01,-86.24 -125.54,-11.54 -83.53,57.91 C-0.38,195.38 117.97,308.85 258.73,386.05 C273.26,394.02 278.58,412.26 270.61,426.78 C265.15,436.73 254.88,442.36 244.28,442.36c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_5_G" android:translateX="923.0530000000001" android:translateY="-359.029" android:pivotX="-519.253" android:pivotY="-467.471" android:rotation="28.7">
- <path android:name="_R_G_L_0_G_L_5_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-421.02 497.47 C-436.2,497.47 -449.23,485.99 -450.83,470.56 C-452.53,454.08 -440.56,439.34 -424.08,437.63 C-201.54,414.57 4.18,310.19 155.19,143.73 C229.54,61.77 287.7,-31.75 328.04,-134.22 C369.81,-240.3 390.99,-352.42 390.99,-467.47 C390.99,-484.04 404.42,-497.47 420.99,-497.47 C437.56,-497.47 450.99,-484.04 450.99,-467.47 C450.99,-226.02 361.72,5.35 199.63,184.04 C38.67,361.47 -180.63,472.73 -417.89,497.31 C-418.94,497.42 -419.99,497.47 -421.02,497.47c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_2_G" android:translateX="222.54600000000002" android:translateY="77.21400000000006" android:pivotX="181.254" android:pivotY="-903.714" android:rotation="28.7" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M181.26 66.28 C181.25,66.28 181.25,66.28 181.25,66.28 C51.64,66.25 -74.22,41.06 -192.83,-8.6 C-208.12,-15 -215.32,-32.58 -208.92,-47.86 C-202.52,-63.15 -184.94,-70.35 -169.66,-63.95 C-58.42,-17.38 59.64,6.25 181.26,6.28 C197.83,6.29 211.26,19.72 211.26,36.29 C211.25,52.86 197.82,66.28 181.26,66.28c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_0_G" android:translateX="403.5" android:translateY="77.5">
- <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-630.5 -255.5 C-630.5,-255.5 -630.5,255.5 -630.5,255.5 C-630.5,255.5 630.5,255.5 630.5,255.5 C630.5,255.5 630.5,-255.5 630.5,-255.5 C630.5,-255.5 -630.5,-255.5 -630.5,-255.5c M374 -8.88 C255.5,40.59 128.4,66.04 0,66 C-128.4,65.95 -255.6,40.42 -374,-9.14 C-389.3,-15.53 -396.5,-33.11 -390.1,-48.39 C-383.7,-63.68 -366.2,-70.88 -350.9,-64.49 C-239.7,-18 -120.5,5.96 0,6 C120.4,6.04 239.7,-17.84 350.9,-64.25 C366.2,-70.63 383.7,-63.41 390.1,-48.12 C396.5,-32.83 389.3,-15.26 374,-8.88c "/>
- </group>
- </group>
- </group>
- <group android:name="time_group"/>
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="translateX" android:duration="1000" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
-
diff --git a/core/res/res/drawable/accessibility_autoclick_resume.xml b/core/res/res/drawable/accessibility_autoclick_resume.xml
new file mode 100644
index 0000000..ae83e98
--- /dev/null
+++ b/core/res/res/drawable/accessibility_autoclick_resume.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright 2025 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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:viewportWidth="24"
+ android:viewportHeight="24"
+ android:width="24dp"
+ android:height="24dp">
+ <group>
+ <clip-path android:pathData="M0 0H24V24H0V0Z" />
+ <path
+ android:pathData="M8 19V5L19 12L8 19Z"
+ android:fillColor="@color/materialColorPrimary" />
+ </group>
+</vector>
diff --git a/core/res/res/drawable/loader_horizontal_watch.xml b/core/res/res/drawable/loader_horizontal_watch.xml
deleted file mode 100644
index 6b86c63..0000000
--- a/core/res/res/drawable/loader_horizontal_watch.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
- <aapt:attr name="android:drawable">
- <vector android:height="14dp" android:width="76dp" android:viewportHeight="14" android:viewportWidth="76">
- <group android:name="_R_G">
- <group android:name="_R_G_L_1_G" android:translateX="39" android:translateY="8">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M39 -8 C39,-8 39,8 39,8 C39,8 -39,8 -39,8 C-39,8 -39,-8 -39,-8 C-39,-8 39,-8 39,-8c "/>
- </group>
- <group android:name="_R_G_L_0_G" android:translateX="-345" android:translateY="-67" android:pivotX="384" android:pivotY="75" android:scaleX="0.1" android:scaleY="0.1">
- <group android:name="_R_G_L_0_G_L_6_G" android:translateX="-274.19" android:translateY="-390.077" android:pivotX="658.448" android:pivotY="-390.423" android:rotation="28.7" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_6_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M231.28 420.42 C226.4,420.42 221.45,419.23 216.88,416.72 C74.61,338.68 -45.02,224 -129.06,85.06 C-171.54,14.82 -204.38,-60.73 -226.66,-139.5 C-249.65,-220.76 -261.31,-305.18 -261.31,-390.42 C-261.31,-406.99 -247.88,-420.42 -231.31,-420.42 C-214.74,-420.42 -201.31,-406.99 -201.31,-390.42 C-201.31,-310.71 -190.42,-231.78 -168.93,-155.83 C-148.11,-82.23 -117.42,-11.63 -77.72,54 C0.86,183.92 112.71,291.15 245.73,364.12 C260.26,372.08 265.58,390.32 257.61,404.85 C252.15,414.79 241.88,420.42 231.28,420.42c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_5_G" android:translateX="875.8979999999999" android:translateY="-337.894" android:pivotX="-491.64" android:pivotY="-442.606" android:rotation="28.7">
- <path android:name="_R_G_L_0_G_L_5_G_D_0_P_0" android:fillColor="#303030" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-398.64 472.61 C-413.82,472.61 -426.84,461.13 -428.44,445.7 C-430.15,429.22 -418.17,414.47 -401.69,412.77 C-191.38,390.98 3.04,292.33 145.75,135.01 C289.46,-23.4 368.6,-228.54 368.6,-442.61 C368.6,-459.17 382.04,-472.61 398.6,-472.61 C415.17,-472.61 428.6,-459.17 428.6,-442.61 C428.6,-213.6 343.93,5.85 190.19,175.33 C37.53,343.61 -170.48,449.13 -395.51,472.44 C-396.56,472.55 -397.6,472.61 -398.64,472.61c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_2_G" android:translateX="212.64499999999998" android:translateY="75.14200000000005" android:pivotX="171.613" android:pivotY="-855.642" android:rotation="28.7" android:scaleY="0">
- <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M171.61 64.36 C171.61,64.36 171.61,64.36 171.61,64.36 C48.68,64.32 -70.7,40.42 -183.19,-6.68 C-198.47,-13.07 -205.68,-30.65 -199.28,-45.93 C-192.88,-61.22 -175.3,-68.42 -160.02,-62.02 C-54.9,-18.01 56.68,4.33 171.62,4.36 C188.19,4.36 201.62,17.8 201.61,34.36 C201.61,50.93 188.18,64.36 171.61,64.36c "/>
- </group>
- <group android:name="_R_G_L_0_G_L_0_G" android:translateX="384" android:translateY="75">
- <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-611 -259 C-611,-259 -611,259 -611,259 C-611,259 611,259 611,259 C611,259 611,-259 611,-259 C611,-259 -611,-259 -611,-259c M354.66 -6.52 C242.36,40.4 121.76,64.54 -0.04,64.5 C-121.84,64.46 -242.44,40.23 -354.74,-6.76 C-370.04,-13.16 -377.24,-30.73 -370.84,-46.02 C-364.44,-61.3 -346.94,-68.51 -331.64,-62.12 C-226.54,-18.18 -113.84,4.46 -0.04,4.5 C113.76,4.54 226.56,-18.02 331.56,-61.89 C346.86,-68.27 364.46,-61.05 370.86,-45.76 C377.26,-30.47 369.96,-12.9 354.66,-6.52c "/>
- </group>
- </group>
- </group>
- <group android:name="time_group"/>
- </vector>
- </aapt:attr>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_6_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_5_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="rotation" android:duration="983" android:startOffset="0" android:valueFrom="28.7" android:valueTo="-51.4" android:valueType="floatType">
- <aapt:attr name="android:interpolator">
- <pathInterpolator android:pathData="M 0.0,0.0 c0.402,0.136 0.202,0.847 1.0,1.0"/>
- </aapt:attr>
- </objectAnimator>
- </set>
- </aapt:attr>
- </target>
- <target android:name="_R_G_L_0_G_L_2_G">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="scaleY" android:duration="0" android:startOffset="133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator android:repeatCount="infinite" android:propertyName="translateX" android:duration="1000" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
- </set>
- </aapt:attr>
- </target>
-</animated-vector>
diff --git a/core/res/res/drawable/progress_ring_watch.xml b/core/res/res/drawable/progress_ring_watch.xml
index 8250ee6..2e65ff1 100644
--- a/core/res/res/drawable/progress_ring_watch.xml
+++ b/core/res/res/drawable/progress_ring_watch.xml
@@ -16,27 +16,27 @@
-->
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
- android:fromDegrees = "270"
- android:toDegrees="270"
- android:pivotX="50%"
- android:pivotY="50%" >
+ android:fromDegrees="270"
+ android:toDegrees="270">
<layer-list>
<item>
<shape
- android:shape="ring"
- android:innerRadiusRatio="@dimen/progressbar_inner_radius_ratio"
+ android:shape="arc"
+ android:useLevel="false"
android:thickness="@dimen/progressbar_thickness"
- android:useLevel="false">
- <solid android:color="@color/materialColorSurfaceContainer"/>
+ android:innerRadiusRatio="@dimen/progressbar_inner_radius_ratio"
+ android:strokeCap="round">
+ <solid android:color="@*android:color/materialColorSurfaceContainer"/>
</shape>
</item>
<item>
<shape
- android:shape="ring"
- android:innerRadiusRatio="@dimen/progressbar_inner_radius_ratio"
+ android:shape="arc"
+ android:useLevel="true"
android:thickness="@dimen/progressbar_thickness"
- android:useLevel="true">
- <solid android:color="@color/materialColorPrimary"/>
+ android:innerRadiusRatio="@dimen/progressbar_inner_radius_ratio"
+ android:strokeCap="round">
+ <solid android:color="@*android:color/materialColorPrimary"/>
</shape>
</item>
</layer-list>
diff --git a/core/res/res/layout/media_route_controller_dialog.xml b/core/res/res/layout/media_route_controller_dialog.xml
index 24a2535..a5cd83b 100644
--- a/core/res/res/layout/media_route_controller_dialog.xml
+++ b/core/res/res/layout/media_route_controller_dialog.xml
@@ -41,11 +41,5 @@
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp" />
</LinearLayout>
-
- <!-- Optional content view section. -->
- <FrameLayout android:id="@+id/media_route_control_frame"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone" />
</LinearLayout>
</ScrollView>
diff --git a/core/res/res/layout/notification_2025_conversation_header.xml b/core/res/res/layout/notification_2025_conversation_header.xml
index 1bde173..68096f8 100644
--- a/core/res/res/layout/notification_2025_conversation_header.xml
+++ b/core/res/res/layout/notification_2025_conversation_header.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2024 The Android Open Source Project
+ ~ Copyright (C) 2025 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -15,157 +15,74 @@
~ limitations under the License
-->
-<com.android.internal.widget.ConversationHeaderLinearLayout
+<!-- extends RelativeLayout -->
+<NotificationHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/conversation_header"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:id="@+id/notification_header"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_2025_header_height"
+ android:clipChildren="false"
+ android:gravity="center_vertical"
android:orientation="horizontal"
- android:paddingTop="@dimen/notification_2025_margin"
+ android:theme="@style/Theme.DeviceDefault.Notification"
+ android:importantForAccessibility="no"
>
- <TextView
- android:id="@+id/conversation_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
- android:textSize="16sp"
- android:singleLine="true"
- android:layout_weight="1"
- />
-
- <TextView
- android:id="@+id/app_name_divider"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:text="@string/notification_header_divider_symbol"
- android:singleLine="true"
- android:visibility="gone"
- />
-
- <!-- App Name -->
- <com.android.internal.widget.ObservableTextView
- android:id="@+id/app_name_text"
- android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:singleLine="true"
- android:visibility="gone"
- />
-
- <TextView
- android:id="@+id/time_divider"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:text="@string/notification_header_divider_symbol"
- android:singleLine="true"
- android:visibility="gone"
- />
-
- <DateTimeView
- android:id="@+id/time"
- android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:showRelative="true"
- android:singleLine="true"
- android:visibility="gone"
- />
-
- <ViewStub
- android:id="@+id/chronometer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:layout="@layout/notification_template_part_chronometer"
- android:visibility="gone"
- />
-
- <TextView
- android:id="@+id/verification_divider"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:text="@string/notification_header_divider_symbol"
- android:singleLine="true"
- android:visibility="gone"
- />
-
<ImageView
- android:id="@+id/verification_icon"
- android:layout_width="@dimen/notification_verification_icon_size"
- android:layout_height="@dimen/notification_verification_icon_size"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:baseline="10dp"
- android:scaleType="fitCenter"
- android:src="@drawable/ic_notifications_alerted"
+ android:id="@+id/left_icon"
+ android:layout_width="@dimen/notification_2025_left_icon_size"
+ android:layout_height="@dimen/notification_2025_left_icon_size"
+ android:layout_alignParentStart="true"
+ android:layout_margin="@dimen/notification_2025_margin"
+ android:background="@drawable/notification_large_icon_outline"
+ android:clipToOutline="true"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
android:visibility="gone"
/>
- <TextView
- android:id="@+id/verification_text"
- android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ <include layout="@layout/notification_2025_conversation_icon_container" />
+
+ <!-- extends ViewGroup -->
+ <NotificationTopLineView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/notification_top_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:layout_weight="100"
- android:showRelative="true"
- android:singleLine="true"
- android:visibility="gone"
+ android:layout_alignParentStart="true"
+ android:layout_toStartOf="@id/expand_button"
+ android:layout_alignWithParentIfMissing="true"
+ android:layout_marginVertical="@dimen/notification_2025_margin"
+ android:clipChildren="false"
+ android:gravity="center_vertical"
+ android:paddingStart="@dimen/notification_2025_content_margin_start"
+ android:theme="@style/Theme.DeviceDefault.Notification"
+ >
+
+ <include layout="@layout/notification_2025_top_line_views" />
+
+ </NotificationTopLineView>
+
+ <FrameLayout
+ android:id="@+id/alternate_expand_target"
+ android:layout_width="@dimen/notification_2025_content_margin_start"
+ android:layout_height="match_parent"
+ android:layout_alignParentStart="true"
+ android:importantForAccessibility="no"
+ android:focusable="false"
/>
- <ImageButton
- android:id="@+id/feedback"
- android:layout_width="@dimen/notification_feedback_size"
- android:layout_height="@dimen/notification_feedback_size"
- android:layout_marginStart="@dimen/notification_header_separating_margin"
- android:background="?android:selectableItemBackgroundBorderless"
- android:contentDescription="@string/notification_feedback_indicator"
- android:baseline="13dp"
- android:scaleType="fitCenter"
- android:src="@drawable/ic_feedback_indicator"
- android:visibility="gone"
- />
+ <include layout="@layout/notification_2025_expand_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ android:layout_alignParentEnd="true" />
- <ImageView
- android:id="@+id/phishing_alert"
- android:layout_width="@dimen/notification_2025_badge_size"
- android:layout_height="@dimen/notification_2025_badge_size"
- android:layout_marginStart="@dimen/notification_2025_badge_margin"
- android:baseline="@dimen/notification_2025_badge_baseline"
- android:scaleType="fitCenter"
- android:src="@drawable/ic_dialog_alert_material"
- android:visibility="gone"
- android:contentDescription="@string/notification_phishing_alert_content_description"
- />
+ <include layout="@layout/notification_close_button"
+ android:id="@+id/close_button"
+ android:layout_width="@dimen/notification_close_button_size"
+ android:layout_height="@dimen/notification_close_button_size"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentEnd="true" />
- <ImageView
- android:id="@+id/profile_badge"
- android:layout_width="@dimen/notification_2025_badge_size"
- android:layout_height="@dimen/notification_2025_badge_size"
- android:layout_marginStart="@dimen/notification_2025_badge_margin"
- android:baseline="@dimen/notification_2025_badge_baseline"
- android:scaleType="fitCenter"
- android:visibility="gone"
- android:contentDescription="@string/notification_work_profile_content_description"
- />
-
- <ImageView
- android:id="@+id/alerted_icon"
- android:layout_width="@dimen/notification_2025_badge_size"
- android:layout_height="@dimen/notification_2025_badge_size"
- android:layout_marginStart="@dimen/notification_2025_badge_margin"
- android:baseline="@dimen/notification_2025_badge_baseline"
- android:contentDescription="@string/notification_alerted_content_description"
- android:scaleType="fitCenter"
- android:src="@drawable/ic_notifications_alerted"
- android:visibility="gone"
- />
-</com.android.internal.widget.ConversationHeaderLinearLayout>
+</NotificationHeaderView>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_call.xml b/core/res/res/layout/notification_2025_template_collapsed_call.xml
index 6f3c15a..ee691e4 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_call.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_call.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2024 The Android Open Source Project
+ ~ Copyright (C) 2025 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -25,55 +25,177 @@
android:theme="@style/Theme.DeviceDefault.Notification"
>
- <!-- CallLayout shares visual appearance with ConversationLayout, so shares layouts -->
- <include layout="@layout/notification_2025_conversation_icon_container" />
-
<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="@dimen/notification_2025_min_height"
- android:orientation="horizontal"
+ android:clipChildren="false"
+ android:orientation="vertical"
>
- <LinearLayout
- android:id="@+id/notification_main_column"
+ <com.android.internal.widget.NotificationMaxHeightFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginStart="@dimen/notification_2025_content_margin_start"
- android:orientation="vertical"
- android:paddingBottom="@dimen/notification_2025_margin"
+ android:minHeight="@dimen/notification_2025_min_height"
+ android:clipChildren="false"
>
- <include
- layout="@layout/notification_2025_conversation_header"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ <ImageView
+ android:id="@+id/left_icon"
+ android:layout_width="@dimen/notification_2025_left_icon_size"
+ android:layout_height="@dimen/notification_2025_left_icon_size"
+ android:layout_alignParentStart="true"
+ android:layout_margin="@dimen/notification_2025_margin"
+ android:background="@drawable/notification_large_icon_outline"
+ android:clipToOutline="true"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
+ android:visibility="gone"
/>
- <include layout="@layout/notification_template_text"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/notification_text_height"
+ <!-- CallLayout shares visual appearance with ConversationLayout, so shares layouts -->
+ <include layout="@layout/notification_2025_conversation_icon_container" />
+
+ <FrameLayout
+ android:id="@+id/alternate_expand_target"
+ android:layout_width="@dimen/notification_2025_content_margin_start"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:importantForAccessibility="no"
+ android:focusable="false"
/>
+ <LinearLayout
+ android:id="@+id/notification_headerless_view_row"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/notification_2025_content_margin_start"
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ >
+
+ <LinearLayout
+ android:id="@+id/notification_headerless_view_column"
+ android:layout_width="0px"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:layout_marginBottom="@dimen/notification_2025_margin"
+ android:layout_marginTop="@dimen/notification_2025_margin"
+ android:clipChildren="false"
+ android:orientation="vertical"
+ >
+
+ <NotificationTopLineView
+ android:id="@+id/notification_top_line"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/notification_headerless_line_height"
+ android:clipChildren="false"
+ android:theme="@style/Theme.DeviceDefault.Notification"
+ >
+
+ <!--
+ NOTE: The notification_2025_top_line_views layout contains the app_name_text.
+ In order to include the title view at the beginning, the Notification.Builder
+ has logic to hide that view whenever this title view is to be visible.
+ -->
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:ellipsize="end"
+ android:fadingEdge="horizontal"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
+ />
+
+ <include layout="@layout/notification_2025_top_line_views" />
+
+ </NotificationTopLineView>
+
+ <LinearLayout
+ android:id="@+id/notification_main_column"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:clipChildren="false"
+ >
+ <com.android.internal.widget.NotificationVanishingFrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/notification_headerless_line_height"
+ >
+ <!-- This is the simplest way to keep this text vertically centered without
+ gravity="center_vertical" which causes jumpiness in expansion animations. -->
+ <include
+ layout="@layout/notification_2025_text"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_text_height"
+ android:layout_gravity="center_vertical"
+ android:layout_marginTop="0dp"
+ />
+ </com.android.internal.widget.NotificationVanishingFrameLayout>
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/right_icon"
+ android:layout_width="@dimen/notification_right_icon_size"
+ android:layout_height="@dimen/notification_right_icon_size"
+ android:layout_gravity="center_vertical|end"
+ android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
+ android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
+ android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:background="@drawable/notification_large_icon_outline"
+ android:clipToOutline="true"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
+ />
+
+ <FrameLayout
+ android:id="@+id/expand_button_touch_container"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:minWidth="@dimen/notification_content_margin_end"
+ >
+
+ <include layout="@layout/notification_2025_expand_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ />
+
+ </FrameLayout>
+
+ </LinearLayout>
+
+ <include layout="@layout/notification_close_button"
+ android:id="@+id/close_button"
+ android:layout_width="@dimen/notification_close_button_size"
+ android:layout_height="@dimen/notification_close_button_size"
+ android:layout_gravity="top|end" />
+
+ </com.android.internal.widget.NotificationMaxHeightFrameLayout>
+
+ <LinearLayout
+ android:id="@+id/notification_action_list_margin_target"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-20dp"
+ android:clipChildren="false"
+ android:orientation="vertical">
+ <include layout="@layout/notification_template_smart_reply_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_content_margin"
+ android:layout_marginStart="@dimen/notification_2025_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end" />
+ <include layout="@layout/notification_material_action_list" />
</LinearLayout>
-
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:minWidth="@dimen/notification_content_margin_end"
- >
-
- <include
- layout="@layout/notification_2025_expand_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="top|end"
- />
-
- </FrameLayout>
-
</LinearLayout>
</com.android.internal.widget.CallLayout>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_conversation.xml b/core/res/res/layout/notification_2025_template_collapsed_conversation.xml
new file mode 100644
index 0000000..f804111
--- /dev/null
+++ b/core/res/res/layout/notification_2025_template_collapsed_conversation.xml
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2025 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<!-- extends FrameLayout -->
+<com.android.internal.widget.ConversationLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/status_bar_latest_event_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:tag="conversation"
+ >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:orientation="vertical"
+ >
+
+
+ <com.android.internal.widget.NotificationMaxHeightFrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/notification_2025_min_height"
+ android:clipChildren="false"
+ >
+
+ <ImageView
+ android:id="@+id/left_icon"
+ android:layout_width="@dimen/notification_2025_left_icon_size"
+ android:layout_height="@dimen/notification_2025_left_icon_size"
+ android:layout_alignParentStart="true"
+ android:layout_margin="@dimen/notification_2025_margin"
+ android:background="@drawable/notification_large_icon_outline"
+ android:clipToOutline="true"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
+ android:visibility="gone"
+ />
+
+ <include layout="@layout/notification_2025_conversation_icon_container" />
+
+ <FrameLayout
+ android:id="@+id/alternate_expand_target"
+ android:layout_width="@dimen/notification_2025_content_margin_start"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:importantForAccessibility="no"
+ android:focusable="false"
+ />
+
+ <!--
+ NOTE: to make the expansion animation of id/notification_messaging happen vertically,
+ its X positioning must be the left edge of the notification, so instead of putting the
+ layout_marginStart on the id/notification_headerless_view_row, we put it on
+ id/notification_top_line, making the layout here just a bit different from the base.
+ -->
+ <LinearLayout
+ android:id="@+id/notification_headerless_view_row"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ >
+
+ <!--
+ NOTE: because messaging will always have 2 lines, this LinearLayout should NOT
+ have the id/notification_headerless_view_column, as that is used for modifying
+ vertical margins to accommodate the single-line state that base supports
+ -->
+ <LinearLayout
+ android:layout_width="0px"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:layout_marginBottom="@dimen/notification_2025_margin"
+ android:layout_marginTop="@dimen/notification_2025_margin"
+ android:layout_marginStart="@dimen/notification_2025_content_margin_start"
+ android:clipChildren="false"
+ android:orientation="vertical"
+ >
+
+ <NotificationTopLineView
+ android:id="@+id/notification_top_line"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/notification_headerless_line_height"
+ android:clipChildren="false"
+ android:theme="@style/Theme.DeviceDefault.Notification"
+ >
+
+ <!--
+ NOTE: The notification_2025_top_line_views layout contains the app_name_text.
+ In order to include the title view at the beginning, the Notification.Builder
+ has logic to hide that view whenever this title view is to be visible.
+ -->
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:ellipsize="end"
+ android:fadingEdge="horizontal"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
+ />
+
+ <include layout="@layout/notification_2025_top_line_views" />
+
+ </NotificationTopLineView>
+
+ <LinearLayout
+ android:id="@+id/notification_main_column"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:clipChildren="false"
+ >
+ <com.android.internal.widget.MessagingLinearLayout
+ android:id="@+id/notification_messaging"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:spacing="@dimen/notification_messaging_spacing" />
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <!-- Images -->
+ <com.android.internal.widget.MessagingLinearLayout
+ android:id="@+id/conversation_image_message_container"
+ android:layout_width="@dimen/notification_right_icon_size"
+ android:layout_height="@dimen/notification_right_icon_size"
+ android:layout_gravity="center_vertical|end"
+ android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
+ android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
+ android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:forceHasOverlappingRendering="false"
+ android:spacing="0dp"
+ android:clipChildren="false"
+ android:visibility="gone"
+ />
+
+ <ImageView
+ android:id="@+id/right_icon"
+ android:layout_width="@dimen/notification_right_icon_size"
+ android:layout_height="@dimen/notification_right_icon_size"
+ android:layout_gravity="center_vertical|end"
+ android:layout_marginTop="@dimen/notification_right_icon_headerless_margin"
+ android:layout_marginBottom="@dimen/notification_right_icon_headerless_margin"
+ android:layout_marginStart="@dimen/notification_right_icon_content_margin"
+ android:background="@drawable/notification_large_icon_outline"
+ android:clipToOutline="true"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
+ />
+
+ <FrameLayout
+ android:id="@+id/expand_button_touch_container"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:minWidth="@dimen/notification_content_margin_end"
+ >
+
+ <include layout="@layout/notification_2025_expand_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ />
+
+ </FrameLayout>
+
+ </LinearLayout>
+
+ <include layout="@layout/notification_close_button"
+ android:id="@+id/close_button"
+ android:layout_width="@dimen/notification_close_button_size"
+ android:layout_height="@dimen/notification_close_button_size"
+ android:layout_gravity="top|end" />
+
+ </com.android.internal.widget.NotificationMaxHeightFrameLayout>
+
+ <LinearLayout
+ android:id="@+id/notification_action_list_margin_target"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-20dp"
+ android:clipChildren="false"
+ android:orientation="vertical">
+ <include layout="@layout/notification_template_smart_reply_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_content_margin"
+ android:layout_marginStart="@dimen/notification_2025_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end" />
+ <include layout="@layout/notification_material_action_list" />
+ </LinearLayout>
+</LinearLayout>
+</com.android.internal.widget.ConversationLayout>
diff --git a/core/res/res/layout/notification_2025_template_conversation.xml b/core/res/res/layout/notification_2025_template_conversation.xml
deleted file mode 100644
index 24b6ad0..0000000
--- a/core/res/res/layout/notification_2025_template_conversation.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?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
- -->
-
-<!-- extends FrameLayout -->
-<com.android.internal.widget.ConversationLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/status_bar_latest_event_content"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:tag="conversation"
- android:theme="@style/Theme.DeviceDefault.Notification"
- >
-
- <include layout="@layout/notification_2025_conversation_icon_container" />
-
- <!-- Wraps entire "expandable" notification -->
- <com.android.internal.widget.RemeasuringLinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="top"
- android:clipToPadding="false"
- android:clipChildren="false"
- android:orientation="vertical"
- >
- <!-- LinearLayout for Expand Button-->
- <com.android.internal.widget.RemeasuringLinearLayout
- android:id="@+id/expand_button_and_content_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:gravity="start|top"
- android:orientation="horizontal"
- android:clipChildren="false"
- android:clipToPadding="false">
- <!--TODO: move this into a separate layout and share logic with the header to bring back app opps etc-->
- <com.android.internal.widget.RemeasuringLinearLayout
- android:id="@+id/notification_action_list_margin_target"
- android:layout_width="0dp"
- android:orientation="vertical"
- android:layout_height="wrap_content"
- android:layout_weight="1">
-
- <!-- Header -->
-
- <!-- Use layout_marginStart instead of paddingStart to work around strange
- measurement behavior on lower display densities. -->
- <include
- layout="@layout/notification_2025_conversation_header"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="2dp"
- android:layout_marginStart="@dimen/notification_2025_content_margin_start"
- />
-
- <!-- Messages -->
- <com.android.internal.widget.MessagingLinearLayout
- android:id="@+id/notification_messaging"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/notification_text_size"
- android:spacing="@dimen/notification_messaging_spacing"
- android:clipToPadding="false"
- android:clipChildren="false"
- />
- </com.android.internal.widget.RemeasuringLinearLayout>
-
- <!-- This is where the expand button container will be placed when collapsed-->
- </com.android.internal.widget.RemeasuringLinearLayout>
-
- <include layout="@layout/notification_template_smart_reply_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/notification_content_margin"
- android:layout_marginStart="@dimen/notification_2025_content_margin_start"
- android:layout_marginEnd="@dimen/notification_content_margin_end" />
- <include layout="@layout/notification_material_action_list" />
- </com.android.internal.widget.RemeasuringLinearLayout>
-
- <!--expand_button_a11y_container ensures talkback focus order is correct when view is expanded.
- The -1px of marginTop and 1px of paddingTop make sure expand_button_a11y_container is prior to
- its sibling view in accessibility focus order.
- {see android.view.ViewGroup.addChildrenForAccessibility()}
- expand_button_container will be moved under expand_button_and_content_container when collapsed,
- this dynamic movement ensures message can flow under expand button when expanded-->
- <FrameLayout
- android:id="@+id/expand_button_a11y_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="end|top"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_marginTop="-1px"
- android:paddingTop="1px"
- >
- <!--expand_button_container is dynamically placed between here and at the end of the
- layout. It starts here since only FrameLayout layout params have gravity-->
- <LinearLayout
- android:id="@+id/expand_button_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="end|top"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="vertical">
- <include layout="@layout/notification_close_button"
- android:layout_width="@dimen/notification_close_button_size"
- android:layout_height="@dimen/notification_close_button_size"
- android:layout_gravity="end"
- android:layout_marginEnd="20dp"
- />
- <!--expand_button_touch_container makes sure that we can nicely center the expand
- content in the collapsed layout while the parent makes sure that we're never laid out
- bigger than the messaging content.-->
- <LinearLayout
- android:id="@+id/expand_button_touch_container"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/conversation_expand_button_height"
- android:orientation="horizontal"
- android:layout_gravity="end|top"
- android:paddingEnd="0dp"
- android:clipToPadding="false"
- android:clipChildren="false"
- >
- <!-- Images -->
- <com.android.internal.widget.MessagingLinearLayout
- android:id="@+id/conversation_image_message_container"
- android:forceHasOverlappingRendering="false"
- android:layout_width="40dp"
- android:layout_height="40dp"
- android:layout_marginStart="@dimen/conversation_image_start_margin"
- android:spacing="0dp"
- android:layout_gravity="center"
- android:clipToPadding="false"
- android:clipChildren="false"
- />
- <include layout="@layout/notification_2025_expand_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="top|end"
- />
- </LinearLayout>
- </LinearLayout>
- </FrameLayout>
-</com.android.internal.widget.ConversationLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_call.xml b/core/res/res/layout/notification_2025_template_expanded_call.xml
index 0be6125..bbc2966 100644
--- a/core/res/res/layout/notification_2025_template_expanded_call.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_call.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2024 The Android Open Source Project
+ ~ Copyright (C) 2025 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -27,83 +27,47 @@
>
<!-- CallLayout shares visual appearance with ConversationLayout, so shares layouts -->
- <include layout="@layout/notification_2025_conversation_icon_container" />
+ <include layout="@layout/notification_2025_conversation_header"/>
- <LinearLayout
+ <com.android.internal.widget.RemeasuringLinearLayout
android:id="@+id/notification_action_list_margin_target"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/notification_content_margin"
- android:orientation="vertical"
- >
+ android:layout_gravity="top"
+ android:clipChildren="false"
+ android:orientation="vertical">
- <LinearLayout
+ <!-- Note: the top margin is being set in code based on the estimated space needed for
+ the header text. -->
+ <com.android.internal.widget.RemeasuringLinearLayout
+ android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_gravity="top"
android:layout_weight="1"
- android:orientation="horizontal"
- >
-
- <LinearLayout
- android:id="@+id/notification_main_column"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/notification_2025_content_margin_start"
- android:layout_weight="1"
- android:orientation="vertical"
- android:minHeight="68dp"
- >
-
- <include
- layout="@layout/notification_2025_conversation_header"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <include layout="@layout/notification_template_text_multiline" />
-
- <include
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_progress_bar_height"
- android:layout_marginTop="@dimen/notification_progress_margin_top"
- layout="@layout/notification_template_progress"
- />
- </LinearLayout>
-
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:minWidth="@dimen/notification_content_margin_end"
- >
-
- <include
- layout="@layout/notification_expand_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- </FrameLayout>
-
- </LinearLayout>
-
- <ViewStub
- android:layout="@layout/notification_material_reply_text"
- android:id="@+id/notification_material_reply_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
-
- <include
- layout="@layout/notification_template_smart_reply_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:layout_marginStart="@dimen/notification_2025_content_margin_start"
android:layout_marginEnd="@dimen/notification_content_margin_end"
+ android:orientation="vertical"
+ android:clipChildren="false"
+ >
+
+ <include layout="@layout/notification_template_part_line1"/>
+
+ <include layout="@layout/notification_template_text_multiline" />
+
+ </com.android.internal.widget.RemeasuringLinearLayout>
+
+ <include layout="@layout/notification_template_smart_reply_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_content_margin"
- />
+ android:layout_marginStart="@dimen/notification_2025_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end" />
<include layout="@layout/notification_material_action_list" />
- </LinearLayout>
+ </com.android.internal.widget.RemeasuringLinearLayout>
+
+ <include layout="@layout/notification_template_right_icon" />
</com.android.internal.widget.CallLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_conversation.xml b/core/res/res/layout/notification_2025_template_expanded_conversation.xml
new file mode 100644
index 0000000..d7e8bb3
--- /dev/null
+++ b/core/res/res/layout/notification_2025_template_expanded_conversation.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2025 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<!-- extends FrameLayout -->
+<com.android.internal.widget.ConversationLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/status_bar_latest_event_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipToPadding="false"
+ android:clipChildren="false"
+ android:tag="conversation"
+ >
+
+ <include layout="@layout/notification_2025_conversation_header"/>
+
+ <com.android.internal.widget.RemeasuringLinearLayout
+ android:id="@+id/notification_action_list_margin_target"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:clipChildren="false"
+ android:orientation="vertical">
+
+ <!-- Note: the top margin is being set in code based on the estimated space needed for
+ the header text. -->
+ <com.android.internal.widget.RemeasuringLinearLayout
+ android:id="@+id/notification_main_column"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:layout_weight="1"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
+ android:orientation="vertical"
+ android:clipChildren="false"
+ >
+
+ <include layout="@layout/notification_template_part_line1"/>
+
+ <com.android.internal.widget.MessagingLinearLayout
+ android:id="@+id/notification_messaging"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:spacing="@dimen/notification_messaging_spacing" />
+ </com.android.internal.widget.RemeasuringLinearLayout>
+
+ <include layout="@layout/notification_template_smart_reply_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_content_margin"
+ android:layout_marginStart="@dimen/notification_2025_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end" />
+
+ <include layout="@layout/notification_material_action_list" />
+
+ </com.android.internal.widget.RemeasuringLinearLayout>
+
+ <include layout="@layout/notification_template_right_icon" />
+
+</com.android.internal.widget.ConversationLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_messaging.xml b/core/res/res/layout/notification_2025_template_expanded_messaging.xml
index 177706c..20abfee 100644
--- a/core/res/res/layout/notification_2025_template_expanded_messaging.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_messaging.xml
@@ -36,17 +36,21 @@
android:clipChildren="false"
android:orientation="vertical">
+ <!-- Note: the top margin is being set in code based on the estimated space needed for
+ the header text. -->
<com.android.internal.widget.RemeasuringLinearLayout
android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_weight="1"
- android:layout_marginTop="@dimen/notification_2025_header_height"
android:layout_marginEnd="@dimen/notification_content_margin_end"
android:orientation="vertical"
android:clipChildren="false"
>
+
+ <include layout="@layout/notification_template_part_line1"/>
+
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/notification_messaging"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_2025_top_line_views.xml b/core/res/res/layout/notification_2025_top_line_views.xml
index 7487346..7431c42 100644
--- a/core/res/res/layout/notification_2025_top_line_views.xml
+++ b/core/res/res/layout/notification_2025_top_line_views.xml
@@ -20,7 +20,7 @@
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
- <TextView
+ <com.android.internal.widget.ObservableTextView
android:id="@+id/app_name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -108,6 +108,42 @@
android:visibility="gone"
/>
+ <TextView
+ android:id="@+id/verification_divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:text="@string/notification_header_divider_symbol"
+ android:singleLine="true"
+ android:visibility="gone"
+ />
+
+ <ImageView
+ android:id="@+id/verification_icon"
+ android:layout_width="@dimen/notification_2025_badge_size"
+ android:layout_height="@dimen/notification_2025_badge_size"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:baseline="@dimen/notification_2025_badge_baseline"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ />
+
+ <TextView
+ android:id="@+id/verification_text"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:layout_weight="100"
+ android:showRelative="true"
+ android:singleLine="true"
+ android:visibility="gone"
+ />
+
<ImageButton
android:id="@+id/feedback"
android:layout_width="@dimen/notification_feedback_size"
diff --git a/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml b/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml
index 149a5a9..2df1725 100644
--- a/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml
+++ b/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml
@@ -45,6 +45,7 @@
android:maxDrawableWidth="@dimen/notification_icon_circle_size"
android:maxDrawableHeight="@dimen/notification_icon_circle_size"
android:scaleType="centerCrop"
+ android:visibility="gone"
android:importantForAccessibility="no"
/>
<ViewStub
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5da0924..788d5f7 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"toegang te verkry tot sensordata oor jou lewenstekens"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Kennisgewings"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"wys kennisgewings"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Venster-inhoud ophaal"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Die inhoud ondersoek van \'n venster waarmee jy interaksie het."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Verken-met-raak aanskakel"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Laat die app toe om jou fotoversameling te wysig."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"lees liggings in jou mediaversameling"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Laat die app toe om liggings in jou mediaversameling te lees."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Gebruik biometrie"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gebruik biometrie of skermslot"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifieer dat dit jy is"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"D-paneel middel"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Outoklik-tipe instellingspaneel"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Linksklik"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Regsklik"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dubbelklik"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Sleep"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Rollees"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Onderbreek"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Posisie"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> is in die BEPERK-groep geplaas"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index c55f1c6..ca145e5 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ስለአስፈላጊ ምልክቶችዎ ያሉ የዳሳሽ ውሂብ ይድረሱ"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"ማሳወቂያዎች"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"ማሳወቂያዎች አሳይ"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"የመስኮት ይዘት ሰርስረው ያውጡ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"መስተጋበር የሚፈጥሩት የመስኮት ይዘት ይመርምሩ።"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"በመንካት ያስሱን ያብሩ"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"መተግበሪያው የፎቶ ስብስብዎን እንዲቀይረው ያስችለዋል።"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"አካባቢዎችን ከሚዲያ ስብስብዎ ማንበብ"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"መተግበሪያው አካባቢዎችን ከሚዲያ ስብስብዎ እንዲያነብብ ያስችለዋል።"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ባዮሜትሪኮችን ይጠቀሙ"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ባዮሜትሪክስ ወይም ማያ ገፅ መቆለፊያን ይጠቀሙ"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"እርስዎን መሆንዎን ያረጋግጡ"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"የDpad ማዕከል"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"የራስ-ሰር ጠቅ ማድረግ ትየባ ቅንብሮች ፓነል"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"የግራ ጠቅታ"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"የቀኝ ጠቅታ"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"ድርብ ጠቅ አድርግ"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"ጎትት"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"ሸብልል"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"ባለበት አቁም"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"አቀማመጥ"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ወደ የRESTRICTED ባልዲ ተከትቷል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index f542d439b..24d628a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -357,6 +357,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"الوصول إلى بيانات المستشعر حول علاماتك الحيوية"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"الإشعارات"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"عرض الإشعارات"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"استرداد محتوى النافذة:"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"فحص محتوى نافذة يتم التفاعل معها."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"تفعيل الاستكشاف باللمس:"</string>
@@ -652,6 +660,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"للسماح للتطبيق بتعديل مجموعة صورك."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"قراءة المواقع من مجموعة الوسائط التابعة لك"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"للسماح للتطبيق بقراءة المواقع من مجموعة الوسائط التابعة لك."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"استخدام المقاييس الحيوية"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"استخدام المقاييس الحيوية أو قفل الشاشة"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"تأكيد هويتك"</string>
@@ -1157,7 +1197,7 @@
<string name="year" msgid="5182610307741238982">"سنة"</string>
<string name="years" msgid="5797714729103773425">"أعوام"</string>
<string name="now_string_shortest" msgid="3684914126941650330">"الآن"</string>
- <string name="duration_minutes_shortest" msgid="5744379079540806690">"<xliff:g id="COUNT">%d</xliff:g> دقيقة"</string>
+ <string name="duration_minutes_shortest" msgid="5744379079540806690">"<xliff:g id="COUNT">%d</xliff:g> د"</string>
<string name="duration_hours_shortest" msgid="1477752094141971675">"<xliff:g id="COUNT">%d</xliff:g> ساعة"</string>
<string name="duration_days_shortest" msgid="4083124701676227233">"<xliff:g id="COUNT">%d</xliff:g> يوم"</string>
<string name="duration_years_shortest" msgid="483982719231145618">"<xliff:g id="COUNT">%d</xliff:g> سنة"</string>
@@ -1973,7 +2013,7 @@
<string name="zen_mode_rule_name_combination" msgid="7174598364351313725">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
<string name="toolbar_collapse_description" msgid="8009920446193610996">"تصغير"</string>
<string name="zen_mode_feature_name" msgid="3785547207263754500">"عدم الإزعاج"</string>
- <string name="zen_mode_downtime_feature_name" msgid="5886005761431427128">"التعطل"</string>
+ <string name="zen_mode_downtime_feature_name" msgid="5886005761431427128">"فترة التوقّف"</string>
<string name="zen_mode_default_weeknights_name" msgid="7902108149994062847">"ليلة يوم من أيام الأسبوع"</string>
<string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"نهاية الأسبوع"</string>
<string name="zen_mode_default_events_name" msgid="2280682960128512257">"حدث"</string>
@@ -2251,14 +2291,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"الزرّ المركزي"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"لوحة إعدادات نوع النقر التلقائي"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"النقر بالزر الأيسر"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"النقر بزر الماوس الأيمن"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"النقر مرّتين"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"سحب"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"الانتقال للأسفل أو للأعلى"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"إيقاف مؤقت"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"تعديل الموضع"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"تم وضع <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> في الحزمة \"محظورة\"."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index b8afd2e..397afe2 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ অৱস্থাৰ বিষয়ে ছেন্সৰৰ ডেটা লাভ কৰিব পাৰে"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"জাননী"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"জাননী দেখুৱাওক"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ৱিণ্ড’ সমল বিচাৰি উলিওৱাৰ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"আপুনি চাই থকা ৱিণ্ড’খনৰ সমল পৰীক্ষা কৰাৰ।"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"স্পৰ্শৰ দ্বাৰা অন্বেষণ কৰাৰ সুবিধা অন কৰাৰ"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"এপক আপোনাৰ ফট’ সংগ্ৰহ সালসলনি কৰিবলৈ দিয়ে।"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"এপক আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ দিয়ে।"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"বায়\'মেট্ৰিক ব্যৱহাৰ কৰক"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"বায়\'মেট্ৰিক অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"এইয়া আপুনিয়েই বুলি সত্যাপন কৰক"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"ডিপেডৰ মাজৰ বুটাম"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"প্ৰকাৰৰ ছেটিঙৰ পেনেলত স্বয়ংক্ৰিয়ভাৱে ক্লিক কৰক"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"বাওঁফালৰ ক্লিক"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"সোঁফালৰ ক্লিক"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"দুবাৰ ক্লিক"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"টানি আনি এৰক"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"স্ক্ৰ’ল কৰক"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"পজ কৰক"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"স্থান"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>ক সীমাবদ্ধ বাকেটটোত ৰখা হৈছে"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index affa569..96c77e4 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"Həyati əlamətlər haqqında sensor dataya daxil olun"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Bildirişlər"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"bildirişləri göstərmək"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Pəncərənin məzmununu əldə edin"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Əlaqədə olduğunuz pəncərənin məzmununu nəzərdən keçirin."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Toxunuşla öyrənmə funksiyasını aktiv edin"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Tətbiqin foto kolleksiyanıza düzəliş etməsinə icazə verir."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"media kolleksiyanızdan məkanları oxuyun"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Tətbiqin media kolleksiyanızdan məkanları oxumasına icazə verin."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biometrik məlumatlardan istifadə edin"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrik məlumatlardan və ya ekran kilidindən istifadə edin"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Kimliyinizi doğrulayın"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad Mərkəzə"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Avtomatik klikləmə növü üzrə ayarlar paneli"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Sola klik"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Sağ düymə ilə toxunun"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"İki dəfə toxunun"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Çəkin"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Sürüşdürün"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Durdurun"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Mövqe"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> MƏHDUDLAŞDIRILMIŞ səbətinə yerləşdirilib"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 3acc8df..6a68f8d 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"pristupa podacima senzora o vitalnim funkcijama"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Obaveštenja"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"prikazivanje obaveštenja"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"da preuzima sadržaj prozora"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Proverava sadržaj prozora sa kojim ostvarujete interakciju."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"da uključi Istraživanja dodirom"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Dozvoljava aplikaciji da menja kolekciju slika."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"čitanje lokacija iz medijske kolekcije"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Dozvoljava aplikaciji da čita lokacije iz medijske kolekcije."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Koristite biometriju"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Koristite biometriju ili otključavanje ekrana"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrdite identitet"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 7c827bb..69271ba 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"атрымліваць з датчыка даныя асноўных фізіялагічных паказчыкаў"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Апавяшчэнні"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"паказваць апавяшчэнні"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Атрымліваць змесціва вакна"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Аналізаваць змесціва актыўнага вакна."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Уключаць Азнаямленне дотыкам"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Праграма зможа змяняць фотакалекцыю."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"паказваць месцазнаходжанне ў калекцыі мультымедыя"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Праграма зможа паказваць месцазнаходжанне ў калекцыі мультымедыя."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Выкарыстоўваць біяметрыю"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Выкарыстоўваць біяметрыю ці блакіроўку экрана"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Спраўдзіце, што гэта вы"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index c3a2712..1581ab8 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"достъп до сензорните данни за жизнените ви показатели"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Известия"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"показване на известията"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Извлича съдържанието от прозореца"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Инспектира съдържанието на прозорец, с който взаимодействате."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Включи изследването чрез докосване"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Разрешава на приложението да променя колекцията ви от снимки."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"да чете местоположенията от мултимедийната ви колекция"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Разрешава на приложението да чете местоположенията от мултимедийната ви колекция."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Използване на биометр. данни"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Използване на биометрични данни или опцията за заключване на екрана"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Потвърдете, че сте вие"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Поставена е нова SIM карта"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Докоснете, за да я настроите"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Часовата ви зона се промени"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Вече сте в зоната <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Вече сте във: <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Задаване на часа"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Задаване на дата"</string>
<string name="date_time_set" msgid="4603445265164486816">"Задаване"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Контролен пад – център"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Панел с настройки за типа на автоматичното кликване"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Кликване с ляв бутон"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Кликване с десния бутон"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Кликване два пъти"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Преместване с плъзгане"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Превъртане"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Пауза"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Позиция"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Пакетът <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> е поставен в ОГРАНИЧЕНИЯ контейнер"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index f6492c5..c05ea6d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"আপনার অত্যাবশ্যক লক্ষণগুলির সম্পর্কে সেন্সর ডেটা অ্যাক্সেস করে"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"বিজ্ঞপ্তি"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"বিজ্ঞপ্তি দেখুন"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"উইন্ডোর কন্টেন্ট ফিরিয়ে আনুন"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ব্যবহার করছেন এমন একটি উইন্ডোর কন্টেন্ট পরীক্ষা করে৷"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"স্পর্শের মাধ্যমে অন্বেষণ করা চালু করুন"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"অ্যাপকে আপনার ফটো সংগ্রহ পরিবর্তন করার অনুমতি দিন।"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ডিয়া সংগ্রহ থেকে লোকেশন দেখতে দিন"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"আপনার মিডিয়া সংগ্রহ থেকে লোকেশন দেখতে অ্যাপকে অনুমতি দিন।"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"বায়োমেট্রিক্স ব্যবহার করুন"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"বায়োমেট্রিক্স অথবা স্ক্রিন লক ব্যবহার করুন"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"আপনার পরিচয় যাচাই করুন"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"ডিপ্যাড (Dpad)-এর মাঝখানে"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"অটোক্লিক টাইপ সেটিংস প্যানেল"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"বাঁদিকের বোতামে ক্লিক করুন"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"মাউসের ডানদিকের বোতামে ক্লিক করুন"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"ডবল ক্লিক করুন"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"টেনে আনুন"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"স্ক্রল করুন"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"পজ করুন"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"পজিশন"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> সীমাবদ্ধ গ্রুপে অন্তর্ভুক্ত করা হয়েছে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 3ff85ac..ebef234 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"pristupa podacima senzora o vašim vitalnim funkcijama"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Obavještenja"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"prikaz obavještenja"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"preuzimati sadržaj prozora"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Pregleda sadržaj prozora koji trenutno koristite."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"uključiti Istraživanje dodirom"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Omogućava aplikaciji da mijenja vašu kolekciju fotografija."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"čitanje lokacija iz kolekcije medija"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Omogućava aplikaciji da čita lokacije iz vaše kolekcije medija."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Koristi biometriju"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Koristi biometriju ili zaključavanje ekrana"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrdite identitet"</string>
@@ -2250,8 +2290,8 @@
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Lijevi klik"</string>
<string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Desni klik"</string>
<string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dvostruki klik"</string>
- <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Povuci"</string>
- <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Pomakni se"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Prevlačenje"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Klizanje"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pauziraj"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Položaj"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Paket <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> je stavljen u odjeljak OGRANIČENO"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 9b61887..6ddfeaf 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"accedir a les dades del sensor sobre les constants vitals"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificacions"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"mostra notificacions"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Recuperar el contingut de la finestra"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspeccionar el contingut d\'una finestra amb què estàs interaccionant."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Activar Exploració tàctil"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permet que l\'aplicació modifiqui la teva col·lecció de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"llegir les ubicacions de les teves col·leccions multimèdia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permet que l\'aplicació llegeixi les ubicacions de les teves col·leccions multimèdia."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Utilitza la biometria"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Fes servir la biometria o el bloqueig de pantalla"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica la teva identitat"</string>
@@ -2248,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Creu direccional: centre"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Tauler de configuració del tipus de clic automàtic"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Clic esquerre"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Fes clic amb el botó dret"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Fes doble clic"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Arrossega"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Desplaça"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Posa en pausa"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Posició"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> s\'ha transferit al segment RESTRINGIT"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 9c8cc9a..5e596fc 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"přístup k datům ze senzorů vašich životních funkcí"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Oznámení"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"zobrazovat oznámení"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Načítat obsah oken"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Může prozkoumávat obsah oken, se kterými pracujete."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Zapnout funkci Prozkoumání dotykem"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Umožňuje aplikaci upravit vaši sbírku fotek."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"čtení míst ze sbírky médií"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Umožňuje aplikaci číst místa z vaší sbírky médií."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Použít biometrii"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Použít biometrii nebo zámek obrazovky"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrďte, že jste to vy"</string>
@@ -2090,12 +2130,9 @@
<string name="unpin_target" msgid="3963318576590204447">"Odepnout"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Odepnout: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"O aplikaci"</string>
- <!-- no translation found for shortcut_group_a11y_title (2992150163811583865) -->
- <skip />
- <!-- no translation found for suggested_apps_group_a11y_title (2804876567839501831) -->
- <skip />
- <!-- no translation found for all_apps_group_a11y_title (7020352520224108745) -->
- <skip />
+ <string name="shortcut_group_a11y_title" msgid="2992150163811583865">"Přímé sdílení cílů"</string>
+ <string name="suggested_apps_group_a11y_title" msgid="2804876567839501831">"Návrhy aplikací"</string>
+ <string name="all_apps_group_a11y_title" msgid="7020352520224108745">"Seznam aplikací"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Spouštění ukázky…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"Resetování zařízení…"</string>
@@ -2252,14 +2289,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad střed"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel nastavení typu automatického kliknutí"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Kliknutí levým"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Kliknutí pravým tlačítkem"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dvojité kliknutí"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Přetažení"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Posunutí"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pozastavit"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Pozice"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Balíček <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> byl vložen do sekce OMEZENO"</string>
@@ -2536,12 +2569,8 @@
<string name="keyboard_shortcut_group_applications_maps" msgid="7950000659522589471">"Mapy"</string>
<string name="keyboard_shortcut_group_applications" msgid="3010389163951364798">"Aplikace"</string>
<string name="fingerprint_loe_notification_msg" msgid="3927447270148854546">"Vaše otisky prstů se nedaří rozpoznat. Nastavte odemknutí otiskem prstu znovu."</string>
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_title (468577168569874967) -->
- <skip />
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_text (6695268246267993166) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_title (3461195995882871461) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_text (6537085605929303187) -->
- <skip />
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_title" msgid="468577168569874967">"Zařízení USB bylo připojeno, když bylo zařízení zamknuté"</string>
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_text" msgid="6695268246267993166">"Zařízení USB bylo připojeno, když byl Android zamknutý. Pokud zařízení chcete používat, nejdříve Android odemkněte a pak zařízení USB připojte znovu."</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_title" msgid="3461195995882871461">"Podezřelá aktivita USB"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_text" msgid="6537085605929303187">"Datový signál USB byl deaktivován."</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 1b96dbb..8cc1cfe 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"få adgang til sensordata om dine vitale værdier"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifikationer"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"vise notifikationer"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Hente indholdet i vinduet"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Undersøge indholdet i et vindue, du interagerer med."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Aktivere Udforsk ved berøring"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Tillader, at appen kan ændre din billedsamling."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"læse lokationer fra din mediesamling"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Tillader, at appen kan læse lokationer fra din mediesamling."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Brug biometri"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Brug biometri eller skærmlås"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verificer, at det er dig"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"D-pad, midten"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel med indstillinger for type af automatisk klik"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Venstreklik"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Højreklik"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dobbeltklik"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Træk"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Rul"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Sæt på pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Placering"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> er blevet placeret i samlingen BEGRÆNSET"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 73e7b9a..7d5672b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"auf Sensordaten zu deinen Vitaldaten zugreifen"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Benachrichtigungen"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"Benachrichtigungen anzeigen"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Fensterinhalte abrufen"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Die Inhalte eines Fensters, mit dem du interagierst, werden abgerufen."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"\"Tippen & Entdecken\" aktivieren"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Ermöglicht der App, deine Fotosammlung zu ändern."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"Standorte aus meiner Mediensammlung abrufen"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Ermöglicht der App, Standorte aus deiner Mediensammlung abzurufen."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biometrisches Verfahren nutzen"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrisches Verfahren oder Displaysperre verwenden"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Deine Identität bestätigen"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Neue SIM-Karte eingelegt"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Zum Einrichten tippen"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Die Zeitzone hat sich geändert"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Du bist jetzt in <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Du bist jetzt in: <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Uhrzeit festlegen"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Datum festlegen"</string>
<string name="date_time_set" msgid="4603445265164486816">"Speichern"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Steuerkreuz Mitte"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Bereich mit Einstellungen für automatische Klicks"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Linksklick"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Rechtsklicken"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Doppelklicken"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Ziehen"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Scrollen"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pausieren"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Position"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> wurde in den BESCHRÄNKT-Bucket gelegt"</string>
@@ -2430,8 +2466,8 @@
<string name="default_card_name" msgid="9198284935962911468">"KARTE <xliff:g id="CARDNUMBER">%d</xliff:g>"</string>
<string name="permlab_companionProfileWatch" msgid="2457738382085872542">"Berechtigung für Companion-Smartwatch-Profil zum Verwalten von Smartwatches"</string>
<string name="permdesc_companionProfileWatch" msgid="5655698581110449397">"Ermöglicht einer Companion-App, Smartwatches zu verwalten."</string>
- <string name="permlab_observeCompanionDevicePresence" msgid="9008994909653990465">"Präsenz von Companion-Geräten beobachten"</string>
- <string name="permdesc_observeCompanionDevicePresence" msgid="3011699826788697852">"Ermöglicht einer Companion-App, die Präsenz von Companion-Geräten zu beobachten, wenn sie in der Nähe oder weit entfernt sind."</string>
+ <string name="permlab_observeCompanionDevicePresence" msgid="9008994909653990465">"Präsenz von Begleitgeräten beobachten"</string>
+ <string name="permdesc_observeCompanionDevicePresence" msgid="3011699826788697852">"Ermöglicht einer Companion-App, die Präsenz von Begleitgeräten zu beobachten, wenn sie in der Nähe oder weit entfernt sind."</string>
<string name="permlab_deliverCompanionMessages" msgid="3931552294842980887">"Companion-Nachrichten senden"</string>
<string name="permdesc_deliverCompanionMessages" msgid="2170847384281412850">"Ermöglicht einer Companion-App, Companion-Nachrichten an andere Geräte zu senden."</string>
<string name="permlab_startForegroundServicesFromBackground" msgid="6363004936218638382">"Dienste im Vordergrund aus dem Hintergrund starten"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 25a787c..84ca5b7 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Ειδοποιήσεις"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"εμφάνιση ειδοποιήσεων"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Ανάκτηση του περιεχομένου του παραθύρου"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Έλεγχος του περιεχομένου ενός παραθύρου με το οποίο αλληλεπιδράτε."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Ενεργοποίηση της \"Εξερεύνησης με άγγιγμα\""</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη συλλογή φωτογραφιών σας."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ανάγνωση τοποθεσιών από τη συλλογή πολυμέσων σας"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Επιτρέπει στην εφαρμογή να διαβάσει τοποθεσίες από τη συλλογή πολυμέσων σας."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Χρήση βιομετρικών"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Χρήση βιομετρικών ή κλειδώματος οθόνης"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Επαλήθευση ταυτότητας"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad κέντρο"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Πλαίσιο ρυθμίσεων τύπου αυτόματου κλικ"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Αριστερό κλικ"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Δεξί κλικ"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Διπλό κλικ"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Μεταφορά"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Κύλιση"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Παύση"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Θέση"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Το πακέτο <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> τοποθετήθηκε στον κάδο ΠΕΡΙΟΡΙΣΜΕΝΗΣ ΠΡΟΣΒΑΣΗΣ."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 886beff..ef7238c 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"access sensor data about your vital signs"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifications"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"show notifications"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Retrieve window content"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspect the content of a window you\'re interacting with."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Turn on Explore by Touch"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Allows the app to modify your photo collection."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"read locations from your media collection"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Allows the app to read locations from your media collection."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Use biometrics"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify that it’s you"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad centre"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Autoclick type settings panel"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Left-click"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Right-click"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Double-click"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Drag"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Scroll"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Position"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> has been put into the RESTRICTED bucket"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 33bbc6f..7e83739 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"access sensor data about your vital signs"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifications"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"show notifications"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Retrieve window content"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspect the content of a window you\'re interacting with."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Turn on Explore by Touch"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Allows the app to modify your photo collection."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"read locations from your media collection"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Allows the app to read locations from your media collection."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Use biometrics"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify it’s you"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index f0a9c2a..5b99b57 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"access sensor data about your vital signs"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifications"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"show notifications"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Retrieve window content"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspect the content of a window that you\'re interacting with."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Turn on Explore by Touch"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Allows the app to modify your photo collection."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"read locations from your media collection"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Allows the app to read locations from your media collection."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Use biometrics"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify that it’s you"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad centre"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Autoclick type settings panel"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Left-click"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Right-click"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Double-click"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Drag"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Scroll"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Position"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> has been put into the RESTRICTED bucket"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8fcb412..5ba765b 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"access sensor data about your vital signs"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifications"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"show notifications"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Retrieve window content"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspect the content of a window you\'re interacting with."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Turn on Explore by Touch"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Allows the app to modify your photo collection."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"read locations from your media collection"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Allows the app to read locations from your media collection."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Use biometrics"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Use biometrics or screen lock"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verify that it’s you"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad centre"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Autoclick type settings panel"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Left-click"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Right-click"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Double-click"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Drag"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Scroll"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Position"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> has been put into the RESTRICTED bucket"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index f46a4d4..d3258dd 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"acceder a los datos de sensores acerca de tus signos vitales"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificaciones"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"mostrar notificaciones"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Recuperar el contenido de las ventanas"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspeccionará el contenido de la ventana con la que estés interactuando."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Activar la Exploración táctil"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que la app modifique tu colección de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"leer ubicaciones de tu colección de contenido multimedia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que la app lea las ubicaciones de tu colección de contenido multimedia."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Usar datos biométricos"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar datos biométricos o bloqueo de pantalla"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Comprueba que eres tú"</string>
@@ -2248,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Pad direccional: centro"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel de configuración del tipo de clic automático"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Clic izquierdo"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Clic con botón derecho"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Hacer doble clic"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Arrastrar"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Desplazamiento"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pausar"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Posición"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Se colocó <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> en el bucket RESTRICTED"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d594897..c021a8a 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"acceder a datos de sensores de tus constantes vitales"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificaciones"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"mostrar notificaciones"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Comprobar el contenido de la ventana"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspecciona el contenido de una ventana con la que estés interactuando."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Activar la exploración táctil"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que la aplicación modifique tu colección de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"leer las ubicaciones de tu colección de contenido multimedia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que la aplicación lea las ubicaciones de tu colección de contenido multimedia."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Usar biometría"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar biometría o bloqueo de pantalla"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica que eres tú"</string>
@@ -1410,7 +1450,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Nueva SIM insertada"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Toca para configurar"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Tu zona horaria ha cambiado"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Ahora estás en <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Ahora estás en la <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Establecer hora"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Establecer fecha"</string>
<string name="date_time_set" msgid="4603445265164486816">"Establecer"</string>
@@ -2248,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Cruceta: centro"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel de ajustes del tipo de clic automático"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Clic izquierdo"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Hacer clic con el botón derecho"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Hacer doble clic"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Arrastrar"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Desplazarse"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pausar"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Posición"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> se ha incluido en el grupo de restringidos"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 5e961f4..ae21583 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"juurdepääs anduri andmetele teie eluliste näitajate kohta"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Märguanded"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"märguannete kuvamine"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Akna sisu toomine"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Kasutatava akna sisu kontrollimine."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Puudutusega sirvimise sisselülitamine"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Võimaldab rakendusel muuta teie fotokogu."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"Lugeda teie meediakogus olevaid asukohti"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Võimaldab rakendusel lugeda teie meediakogus olevaid asukohti."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biomeetria kasutamine"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biomeetria või ekraaniluku kasutamine"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Kinnitage oma isik"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 0e450d1..a78754f 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"atzitu bizi-konstanteei buruzko sentsorearen datuak"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Jakinarazpenak"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"jakinarazpenak erakutsi"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Leihoko edukia eskuratu."</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Arakatu irekita daukazun leihoko edukia."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"\"Arakatu ukituta\" aktibatu."</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Argazki bilduma aldatzeko baimena ematen dio aplikazioari."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"multimedia-edukien bildumako kokapena irakurri"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Multimedia-edukien bildumako kokapena irakurtzeko baimena ematen dio aplikazioari."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Erabili sistema biometrikoak"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Erabili sistema biometrikoak edo pantailaren blokeoa"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Egiaztatu zeu zarela"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Norabide-kontrolagailuko erdiko botoia"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Automatikoki klik egiteko eginbide motaren ezarpenen panela"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Egin klik ezkerreko botoiarekin"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Egin klik eskuineko botoiarekin"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Egin klik bikoitza"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Arrastatu"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Egin gora eta behera"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pausatu"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Ezarri posizioan"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Murriztuen edukiontzian ezarri da <xliff:g id="PACKAGE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4334713..ddde0b2 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"دسترسی به دادههای حسگر در رابطه با علائم حیاتی شما"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"اعلانها"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"نمایش اعلان"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"محتوای پنجره را بازیابی کند"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"محتوای پنجرهای را که درحال تعامل با آن هستید بررسی میکند."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"فعالسازی کاوش لمسی"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"به برنامه اجازه میدهد مجموعه عکستان را تغییر دهد."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"خواندن مکانها از مجموعه رسانه شما"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"به برنامه اجازه میدهد مکانها را از مجموعه رسانهتان بخواند."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"استفاده از دادههای زیستسنجشی"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"استفاده از دادههای زیستسنجشی یا قفل صفحه"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"تأیید کنید این شمایید"</string>
@@ -2514,7 +2554,7 @@
<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>
- <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"تغییر کاربر"</string>
+ <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"تعویض کاربر"</string>
<string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"بیصدا کردن"</string>
<string name="bg_user_sound_notification_message" msgid="8613881975316976673">"برای بیصدا کردن، تکضرب بزنید"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="6535007304687100909">"مرورگر"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 5e3913e..b17ab23 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"pääsy anturidataan elintoiminnoistasi"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Ilmoitukset"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"näyttää ilmoituksia"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Noutaa ikkunan sisältöä"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Tarkistaa käyttämäsi ikkunan sisältö."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Ottaa kosketuksella tutkimisen käyttöön"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Antaa sovelluksen muokata kuvakokoelmaasi."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"lukea mediakokoelmasi sijainteja"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Antaa sovelluksen lukea mediakokoelmasi sijainteja."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Käytä biometriikkaa"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Käytä biometriikkaa tai näytön lukitusta"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Vahvista henkilöllisyytesi"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Suuntanäppäimistö: keskipainike"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Automaattisen klikkaustyypin asetuspaneeli"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Ykköspainike"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Klikkaa kakkospainikkeella"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Kaksoisklikkaa"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Vedä"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Vieritä"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Keskeytä"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Sijainti"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> on nyt rajoitettujen ryhmässä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 6ef3e21..7145e57 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -74,7 +74,7 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint"</string>
<string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Cette appli n\'est pas compatible avec les pages de 16 ko. La vérification de l\'alignement de fichiers APK a échoué. Cette appli sera exécutée en mode compatible avec la taille de la page. Pour une meilleure compatibilité, veuillez recompiler l\'application avec la prise en charge de pages de 16 ko. Pour en savoir plus, consultez la page <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string>
<string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Cette appli n\'est pas compatible avec les pages de 16 ko. La vérification de l\'alignement de fichiers ELF a échoué. Cette appli sera exécutée en mode compatible avec la taille de la page. Pour une meilleure compatibilité, veuillez recompiler l\'application avec la prise en charge de pages de 16 ko. Pour en savoir plus, consultez la page <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string>
- <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Cette appli n\'est pas compatible avec les pages de 16 ko. Les vérifications d\'alignement de fichiers APK et ELF ont échoué. Cette appli sera exécutée en mode compatible avec la taille de la page. Pour une meilleure compatibilité, veuillez recompiler l\'application avec la prise en charge de pages de 16 ko. Pour en savoir plus, consultez la page <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string>
+ <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Cette appli n\'est pas compatible avec les pages de 16 ko. Les vérifications de l\'alignement de fichiers APK et ELF ont échoué. Cette appli sera exécutée dans un mode compatible avec la taille de la page. Pour une compatibilité optimale, veuillez recompiler l\'application afin de prendre en charge les pages de 16 ko. Pour en savoir plus, consultez la page <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string>
<string name="serviceNotProvisioned" msgid="8289333510236766193">"Ce service n\'est pas pris en charge."</string>
<string name="CLIRPermanent" msgid="166443681876381118">"Impossible de modifier le paramètre relatif au numéro de l\'appelant."</string>
<string name="auto_data_switch_title" msgid="3286350716870518297">"Données changées à <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string>
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"accéder aux données des capteurs sur vos signes vitaux"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifications"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"afficher les notifications"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Récupérer le contenu d\'une fenêtre"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspecter le contenu d\'une fenêtre avec laquelle vous interagissez."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Activer la fonctionnalité Explorer au toucher"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Autorise l\'appli à modifier votre collection de photos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"lire les positions issues de votre collection multimédia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Autorise l\'appli à lire les positions indiquées dans votre collection multimédia."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Utiliser les données biométriques"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utiliser les données biométriques ou le verrouillage de l\'écran"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirmez que c\'est vous"</string>
@@ -2248,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Pavé directionnel – centre"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panneau de configuration des paramètres de type clic automatique"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Clic gauche"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Clic droit"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Double-cliquer"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Glisser"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Faire défiler"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Position"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> a été placé dans le compartiment RESTREINT"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4fd8601..a71348a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"accéder aux données des capteurs relatives à vos signes vitaux"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifications"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"afficher des notifications"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Récupérer le contenu d\'une fenêtre"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspecte le contenu d\'une fenêtre avec laquelle vous interagissez."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Activer la fonctionnalité Explorer au toucher"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Autorise l\'application à modifier votre bibliothèque photo."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"consulter des positions issues de votre bibliothèque multimédia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Autorise l\'application à consulter des positions issues de votre bibliothèque multimédia."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Utiliser la biométrie"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utiliser la biométrie ou le verrouillage de l\'écran"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirmez votre identité"</string>
@@ -2248,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Pavé directionnel - Centre"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panneau des paramètres du type de clic automatique"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Clic gauche"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Clic droit"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Double-cliquer"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Faire glisser"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Faire défiler"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Position"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> a été placé dans le bucket RESTRICTED"</string>
@@ -2486,7 +2522,7 @@
<string name="satellite_manual_selection_state_popup_cancel" msgid="973605633339469252">"Retour"</string>
<string name="unarchival_session_app_label" msgid="6811856981546348205">"En attente…"</string>
<string name="satellite_sos_available_notification_title" msgid="5396708154268096124">"SOS par satellite est maintenant disponible"</string>
- <string name="satellite_sos_available_notification_summary" msgid="1727088812951848330">"Vous pouvez envoyer des messages aux services d\'urgence s\'il n\'y a pas de réseau mobile ou Wi-Fi. Google Messages doit être votre application de chat par défaut."</string>
+ <string name="satellite_sos_available_notification_summary" msgid="1727088812951848330">"Vous pouvez envoyer des messages aux services d\'urgence s\'il n\'y a pas de réseau mobile ou Wi-Fi. Google Messages doit être votre application de messagerie par défaut."</string>
<string name="satellite_sos_not_supported_notification_title" msgid="2659100983227637285">"SOS par satellite n\'est pas disponible"</string>
<string name="satellite_sos_not_supported_notification_summary" msgid="1071762454665310549">"SOS par satellite n\'est pas disponible sur cet appareil"</string>
<string name="satellite_sos_not_provisioned_notification_title" msgid="8564738683795406715">"SOS par satellite n\'est pas configuré"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 4ce3fc3..e8090b8 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"acceder aos datos dos sensores sobre as túas constantes vitais"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificacións"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"mostrar notificacións"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Recuperar contido da ventá"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspecciona o contido dunha ventá coa que estás interactuando."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Activar a exploración táctil"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que a aplicación modifique a túa colección de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ler localizacións da túa colección multimedia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que a aplicación lea as localizacións da túa colección multimedia."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Utilizar desbloqueo biométrico"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utilizar desbloqueo biométrico ou credencial do dispositivo"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica a túa identidade"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Cruceta: centro"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel de configuración do tipo de clic automático"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Clic co botón esquerdo do rato"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Facer clic co botón dereito"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Facer dobre clic"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Arrastrar"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Desprazar"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pausa"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Posición"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> incluíuse no grupo RESTRINXIDO"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index fcba3fe..3ddc9da 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"તમારા મહત્વપૂર્ણ ચિહ્નો વિશે સેન્સર ડેટા ઍક્સેસ કરો"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"નોટિફિકેશન"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"નોટિફિકેશન બતાવો"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"વિંડો કન્ટેન્ટ પુનઃપ્રાપ્ત કરો"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"તમે જેની સાથે ક્રિયા-પ્રતિક્રિયા કરી રહ્યાં છો તે વિંડોનું કન્ટેન્ટ તપાસો."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"સ્પર્શ કરીને શોધખોળ કરવું ચાલુ કરો"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"એપને તમારો ફોટો સંગ્રહ સંશોધિત કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"આપના મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવા"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"એપને તમારા મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવાની મંજૂરી આપે છે."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"બાયોમેટ્રિક્સનો ઉપયોગ કરો"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"બાયોમેટ્રિક્સ અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"આ તમે જ છો તેની ચકાસણી કરો"</string>
@@ -1408,7 +1448,7 @@
<string name="install_carrier_app_notification_button" msgid="6257740533102594290">"ઍપ ડાઉનલોડ કરો"</string>
<string name="carrier_app_notification_title" msgid="5815477368072060250">"નવું સિમ દાખલ કર્યું"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"તેને સેટ કરવા માટે ટૅપ કરો"</string>
- <string name="time_zone_change_notification_title" msgid="5232503069219193218">"તમારો સમય ઝોન બદલાયો છે"</string>
+ <string name="time_zone_change_notification_title" msgid="5232503069219193218">"તમારો ટાઇમ ઝોન બદલાયો છે"</string>
<string name="time_zone_change_notification_body" msgid="6135793674904665585">"તમે <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)માં છો"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"સમય સેટ કરો"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"તારીખ સેટ કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 66f0ced..a587509 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"अपने महत्वपूर्ण संकेतों के बारे में सेंसर डेटा को ऐक्सेस करें"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"सूचनाएं"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"सूचनाएं दिखाएं"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"विंडो का कॉन्टेंट वापस पाएं"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"विंडो पर नज़र आ रहे कॉन्टेंट की जांच करें."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"छूकर, किसी चीज़ से जुड़ी जानकारी सुनने की सुविधा चालू करें"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"इससे ऐप्लिकेशन को आपके फ़ोटो संग्रह में बदलाव करने की मंज़ूरी दी जाती है."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"अपने मीडिया संग्रह से जगह की जानकारी ऐक्सेस करने की अनुमति दें"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"इससे ऐप्लिकेशन को आपके मीडिया संग्रह से जगह की जानकारी ऐक्सेस करने की अनुमति दी जाती है."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"बायोमेट्रिक्स इस्तेमाल करें"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"बायोमेट्रिक्स या स्क्रीन लॉक का क्रेडेंशियल इस्तेमाल करें"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"अपनी पहचान की पुष्टि करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index aadf118..cfea6ab 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"pristupiti podacima senzora o vašim vitalnim znakovima"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Obavijesti"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"prikazati obavijesti"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Dohvaćati sadržaj prozora"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Pregledat će sadržaj prozora koji upotrebljavate."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Uključiti značajku Istraži dodirom"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Omogućuje aplikaciji izmjenu vaše zbirke fotografija."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"čitanje lokacija iz vaše medijske zbirke"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Omogućuje aplikaciji čitanje lokacija iz vaše medijske zbirke."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Upotreba biometrije"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Upotreba biometrijske autentifikacije ili zaključavanja zaslona"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrdite da ste to vi"</string>
@@ -1410,7 +1450,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Umetnuta je nova SIM kartica"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Dodirnite da biste je postavili"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Vaša je vremenska zona promijenjena"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Sada ste u vremenskoj zoni <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Trenutačna vremenska zona: <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Postavite vrijeme"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Postavi datum"</string>
<string name="date_time_set" msgid="4603445265164486816">"Postavi"</string>
@@ -2246,7 +2286,7 @@
<string name="accessibility_system_action_dpad_left_label" msgid="6557647179116479152">"Lijevo na plohi za smjerove"</string>
<string name="accessibility_system_action_dpad_right_label" msgid="9180196950365804081">"Desno na plohi za smjerove"</string>
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"U središtu plohe za smjerove"</string>
- <string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Ploča postavki vrste automatskog klika"</string>
+ <string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Ploča postavki automatskih klikova"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Lijevi klik"</string>
<string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Desni klik"</string>
<string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dvostruki klik"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 39a4cfc..24389d6 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"az érzékelők által mért, életjelekkel kapcsolatos adatok elérése"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Értesítések"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"értesítések megjelenítése"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Ablaktartalom lekérdezése"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"A használt ablak tartalmának vizsgálata."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Felfedezés érintéssel bekapcsolása"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Engedélyezi az alkalmazásnak a fényképgyűjtemény módosítását."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"helyek olvasása a médiagyűjteményből"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Engedélyezi az alkalmazásnak a helyek médiagyűjteményből való olvasását."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biometriai feloldás használata"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"A folytatás biometriai feloldással vagy képernyőzárral lehetséges"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Igazolja, hogy Ön az"</string>
@@ -1765,7 +1805,7 @@
<string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Képernyő megtekintése és kezelése"</string>
<string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Elolvashatja a képernyő tartalmát, és tartalmakat jeleníthet meg más alkalmazások felett."</string>
<string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Műveletek megtekintése és elvégzése"</string>
- <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Követheti az alkalmazásokkal és hardveres érzékelőkkel való interakcióit, és műveleteket végezhet az alkalmazásokkal az Ön nevében."</string>
+ <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Követheti az appokkal és hardveres érzékelőkkel való interakcióit, és műveleteket végezhet az appokkal az Ön nevében."</string>
<string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Engedélyezés"</string>
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Tiltás"</string>
<string name="accessibility_dialog_button_uninstall" msgid="2952465517671708108">"Eltávolítás"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"D-pad – középre"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Automatikus kattintás típusának beállításai panel"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Kattintás bal egérgombbal"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Kattintás jobb egérgombbal"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Duplakattintás"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Húzás"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Görgetés"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Szüneteltetés"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Pozíció"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"A következő csomag a KORLÁTOZOTT csoportba került: <xliff:g id="PACKAGE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index f4b83f2..1125dc9 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"օգտագործել սենսորների տվյալները ձեր օրգանիզմի վիճակի մասին"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Ծանուցումներ"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"ցուցադրել ծանուցումներ"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Առբերել պատուհանի բովանդակությունը"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Վերլուծել գործող պատուհանի բովանդակությունը"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Միացնել Հպման միջոցով հետազոտումը"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Թույլ է տալիս հավելվածին փոփոխել ձեր լուսանկարների հավաքածուն:"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ճանաչել տեղադրության մասին տվյալները մեդիա բովանդակության հավաքածուից"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Թույլ է տալիս հավելվածին ճանաչել տեղադրության մասին տվյալները ձեր մեդիա բովանդակության հավաքածուից:"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Կենսաչափական համակարգեր"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Օգտագործել կենսաչափական համակարգեր կամ էկրանի կողպում"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Հաստատեք ձեր ինքնությունը"</string>
@@ -2088,12 +2128,9 @@
<string name="unpin_target" msgid="3963318576590204447">"Ապամրացնել"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Ապամրացնել <xliff:g id="LABEL">%1$s</xliff:g> հավելվածը"</string>
<string name="app_info" msgid="6113278084877079851">"Հավելվածի մասին"</string>
- <!-- no translation found for shortcut_group_a11y_title (2992150163811583865) -->
- <skip />
- <!-- no translation found for suggested_apps_group_a11y_title (2804876567839501831) -->
- <skip />
- <!-- no translation found for all_apps_group_a11y_title (7020352520224108745) -->
- <skip />
+ <string name="shortcut_group_a11y_title" msgid="2992150163811583865">"Direct Share-ի ստացողներ"</string>
+ <string name="suggested_apps_group_a11y_title" msgid="2804876567839501831">"Առաջարկվող հավելվածներ"</string>
+ <string name="all_apps_group_a11y_title" msgid="7020352520224108745">"Հավելվածների ցուցակ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Ցուցադրական օգտատերը գործարկվում է…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"Սարքը վերակայվում է…"</string>
@@ -2250,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad-ի «Կենտրոն» կոճակ"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Ավտոմատ սեղմման տեսակի կարգավորումների վահանակ"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Ձախ սեղմում"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Սեղմել մկնիկի աջ կոճակը"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Երկու անգամ սեղմել"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Քաշել"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Ոլորել"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Դադարեցնել"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Դիրքը"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> փաթեթը գցվեց ՍԱՀՄԱՆԱՓԱԿՎԱԾ զամբյուղի մեջ"</string>
@@ -2534,12 +2567,8 @@
<string name="keyboard_shortcut_group_applications_maps" msgid="7950000659522589471">"Քարտեզներ"</string>
<string name="keyboard_shortcut_group_applications" msgid="3010389163951364798">"Հավելվածներ"</string>
<string name="fingerprint_loe_notification_msg" msgid="3927447270148854546">"Ձեր մատնահետքերն այլևս չեն կարող ճանաչվել։ Նորից կարգավորեք մատնահետքով ապակողպումը։"</string>
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_title (468577168569874967) -->
- <skip />
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_text (6695268246267993166) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_title (3461195995882871461) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_text (6537085605929303187) -->
- <skip />
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_title" msgid="468577168569874967">"Ապակողպեք Android սարքը"</string>
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_text" msgid="6695268246267993166">"Android սարքը կողպված է։ USB կրիչն օգտագործելու համար նախ ապակողպեք Android սարքը, այնուհետև նորից տեղադրեք կրիչը։"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_title" msgid="3461195995882871461">"Հայտնաբերվել է կասկածելի USB կրիչ"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_text" msgid="6537085605929303187">"USB-ով տվյալների փոխանցումն անջատված է։"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index ce9a7f6..2cd5472 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"mengakses data sensor tentang tanda-tanda vital"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifikasi"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"tampilkan notifikasi"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Membaca konten di jendela"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Memeriksa konten di jendela yang sedang Anda buka."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Mengaktifkan Jelajahi dengan Sentuhan"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Mengizinkan aplikasi untuk memodifikasi koleksi foto Anda."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"membaca lokasi dari koleksi media Anda"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Mengizinkan aplikasi untuk membaca lokasi dari koleksi media Anda."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Gunakan biometrik"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gunakan biometrik atau kunci layar"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifikasi diri Anda"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad Tengah"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel setelan jenis klik otomatis"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Klik kiri"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Klik kanan"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Klik dua kali"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Tarik"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Scroll"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Jeda"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Posisi"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> telah dimasukkan ke dalam bucket DIBATASI"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b80efc7..a89a50f 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"aðgangur að skynjaragögnum um lífsmörk þín"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Tilkynningar"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"sýna tilkynningar"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Sækja innihald glugga"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Kanna innihald glugga sem þú ert að nota."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Kveikja á snertikönnun"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Leyfir forritinu að breyta myndasafninu þínu."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"lesa staðsetningar úr efnissafninu þínu"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Leyfir forritinu að lesa staðsetningar úr efnissafninu þínu."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Nota lífkenni"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Nota lífkenni eða skjálás"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Staðfestu hver þú ert"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Nýtt SIM-kort sett í"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Ýttu til að setja það upp"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Tímabeltinu þínu var breytt"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Þú ert nú á <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Tímabeltið þitt er nú <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Veldu tíma"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Veldu dagsetningu"</string>
<string name="date_time_set" msgid="4603445265164486816">"Velja"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Miðjuhnappur stýriflatar"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Stillingasvæði fyrir tegund sjálfvirks smells"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Vinstrismellur"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Hægrismella"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Tvísmella"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Draga"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Fletta"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Hlé"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Staðsetning"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> var sett í flokkinn TAKMARKAÐ"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3ca9f7f..47ef283 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"Possono accedere ai dati dei sensori relativi ai tuoi parametri vitali"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notifiche"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"Visualizzazione di notifiche"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Recuperare contenuti della finestra"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Esamina i contenuti di una finestra con cui interagisci."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Attivare Esplora al tocco"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Consente all\'app di modificare la tua raccolta di foto."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"lettura delle posizioni dalla tua raccolta multimediale"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Consente all\'app di leggere le posizioni dalla tua raccolta multimediale."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Usa la biometria"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usa la biometria o il blocco schermo"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifica la tua identità"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index cfa0987..d58084d 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"גישה אל נתוני חיישנים של הסימנים החיוניים שלך"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"התראות"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"הצגת התראות"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"אחזור תוכן של חלון"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"בדיקת התוכן של חלון שאיתו מתבצעת אינטראקציה."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"הפעלה של \'גילוי באמצעות מגע\'"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"מאפשרת לאפליקציה לשנות את אוסף התמונות שלך."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"לקרוא מיקומים מאוסף המדיה שלך"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"מאפשרת לאפליקציה לקרוא מיקומים מאוסף המדיה שלך."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"שימוש במידע ביומטרי"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"שימוש במידע ביומטרי בנעילת מסך"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"אימות הזהות שלך"</string>
@@ -1433,7 +1473,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"המכשיר זיהה התקן אודיו אנלוגי"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"ההתקן שחיברת לא תואם לטלפון הזה. יש ללחוץ לקבלת מידע נוסף."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"ניפוי באגים ב-USB מחובר"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"צריך ללחוץ כדי להשבית את ניפוי הבאגים ב-USB"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"לוחצים להשבתת ניפוי הבאגים ב-USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"יש ללחוץ על ההתראה כדי להשבית ניפוי באגים ב-USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"ניפוי הבאגים האלחוטי מחובר"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"יש ללחוץ כדי להשבית ניפוי באגים אלחוטי"</string>
@@ -2089,12 +2129,9 @@
<string name="unpin_target" msgid="3963318576590204447">"ביטול הצמדה"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"ביטול ההצמדה של <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"פרטי האפליקציה"</string>
- <!-- no translation found for shortcut_group_a11y_title (2992150163811583865) -->
- <skip />
- <!-- no translation found for suggested_apps_group_a11y_title (2804876567839501831) -->
- <skip />
- <!-- no translation found for all_apps_group_a11y_title (7020352520224108745) -->
- <skip />
+ <string name="shortcut_group_a11y_title" msgid="2992150163811583865">"יעדים לשיתוף ישיר"</string>
+ <string name="suggested_apps_group_a11y_title" msgid="2804876567839501831">"הצעות לאפליקציות"</string>
+ <string name="all_apps_group_a11y_title" msgid="7020352520224108745">"רשימת האפליקציות"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"תהליך ההדגמה מתחיל…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"מתבצע איפוס של המכשיר…"</string>
@@ -2251,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"לחצן אמצעי ב-Dpad"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"חלונית ההגדרות של סוג הקליק האוטומטי"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"לחיצה שמאלית"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"לחיצה ימנית"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"לחיצה כפולה"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"גרירה"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"גלילה"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"השהיה"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"מיקום"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> התווספה לקטגוריה \'מוגבל\'"</string>
@@ -2535,12 +2568,8 @@
<string name="keyboard_shortcut_group_applications_maps" msgid="7950000659522589471">"מפות"</string>
<string name="keyboard_shortcut_group_applications" msgid="3010389163951364798">"אפליקציות"</string>
<string name="fingerprint_loe_notification_msg" msgid="3927447270148854546">"טביעות האצבע שלך נשחקו ואי אפשר לזהות אותן. צריך להגדיר \'פתיחה בטביעת אצבע\' מחדש."</string>
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_title (468577168569874967) -->
- <skip />
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_text (6695268246267993166) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_title (3461195995882871461) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_text (6537085605929303187) -->
- <skip />
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_title" msgid="468577168569874967">"התקן ה-USB מחובר כשהמכשיר נעול"</string>
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_text" msgid="6695268246267993166">"התקן ה-USB מחובר כשמערכת Android נעולה. כדי להשתמש בהתקן ה-USB, קודם צריך לבטל את הנעילה של Android ואז לחבר את ההתקן מחדש."</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_title" msgid="3461195995882871461">"זוהתה פעילות חשודה בהתקן USB"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_text" msgid="6537085605929303187">"האות עם הנתונים מהתקן ה-USB הושבת."</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index ad770aa..7e37dff 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"バイタルサインに関するセンサーデータへのアクセス"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"通知"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"通知を表示"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ウィンドウコンテンツの取得"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ユーザーがアクセスしているウィンドウのコンテンツを検査します。"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"タッチガイドの有効化"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"写真コレクションの変更をアプリに許可します。"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"メディア コレクションの位置情報の読み取り"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"メディア コレクションの位置情報の読み取りをアプリに許可します。"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"生体認証の使用"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"生体認証または画面ロックの使用"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"本人確認"</string>
@@ -1432,7 +1472,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"アナログのオーディオ アクセサリーを検出"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"接続したデバイスはこのスマートフォンと互換性がありません。タップすると、詳細を確認できます。"</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"USB デバッグが接続されました"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"無効にするにはここをタップしてください"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"無効にするにはタップしてください"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB デバッグを無効にする場合に選択します。"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"ワイヤレス デバッグが接続されました"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"無効にするにはここをタップしてください"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 481c422..5ecf5b7 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"თქვენი სასიცოცხლო ფუნქციების შესახებ სენსორის მონაცემებზე წვდომა"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"შეტყობინებები"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"შეტყობინებების ჩვენება"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ფანჯრის კონტენტის მოძიება"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"იმ ფანჯრის კონტენტის შემოწმება, რომელშიც მუშაობთ."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"„შეხებით აღმოჩენის“ ჩართვა"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"აპი შეძლებს თქვენი ფოტოკოლექციის შეცვლას."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"მდებარეობების გაცნობა თქვენი მედიაკოლექციიდან"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"აპი შეძლებს მდებარეობების გაცნობას თქვენი მედიაკოლექციიდან."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"გამოიყენეთ ბიომეტრიული სისტემა"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"გამოიყენეთ ბიომეტრიული სისტემა ან ეკრანის დაბლოკვა"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"დაადასტურეთ ვინაობა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 70412be..98addd0 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ағза күйінің көрсеткіштері туралы сенсор деректеріне қатынасу"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Хабарландырулар"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"хабарландыруларды көрсету"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Терезе контентін оқып отыру"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Ашық тұрған терезе контентін тексеру."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Түртілген элементтерді дыбыстау функциясын қосу"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Қолданбаға суреттер жинағын өзгертуге мүмкіндік береді."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"медиамазмұн жинағынан геодеректерді оқу"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Қолданбаға медиамазмұн жинағынан геодеректерді оқуға мүмкіндік береді."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Биометриканы пайдалану"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Биометриканы немесе экран құлпын пайдалану"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Cіз екеніңізді растаңыз"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Жаңа SIM салынды"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Оны орнату үшін түртіңіз"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Уақыт белдеуі өзгертілді"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Қазір <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>) уақыт белдеуіндесіз."</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Қазір <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>) белдеуіндесіз."</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Уақытты реттеу"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Мезгілін реттеу"</string>
<string name="date_time_set" msgid="4603445265164486816">"Орнату"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Ортаңғы Dpad түймесі"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Автоматты басу түрі параметрлері панелі"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Сол жағын басу"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Тінтуірдің оң жақ түймесін басу"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Екі рет басу"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Сүйреу"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Айналдыру"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Кідірту"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Орналастыру"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ШЕКТЕЛГЕН себетке салынды."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index fdd522b..7d0f7785 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ចូលដំណើរការទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នក"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"ការជូនដំណឹង"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"បង្ហាញការជូនដំណឹង"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ទាញយកខ្លឹមសារវិនដូ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ពិនិត្យខ្លឹមសារវិនដូដែលអ្នកកំពុងធ្វើអន្តរកម្មជាមួយ។"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"បើកការរកមើលដោយប៉ះ"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"អនុញ្ញាតឱ្យកម្មវិធីកែប្រែបណ្ដុំរូបថតរបស់អ្នក។"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"អានទីតាំងពីបណ្ដុំមេឌៀរបស់អ្នក"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"អនុញ្ញាតឱ្យកម្មវិធីអានទីតាំងពីបណ្ដុំមេឌៀរបស់អ្នក។"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ប្រើជីវមាត្រ"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ប្រើជីវមាត្រ ឬការចាក់សោអេក្រង់"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ផ្ទៀងផ្ទាត់ថាជាអ្នក"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 887938c..e3caae5 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸಾರ್ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸಿ"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ವಿಂಡೋ ವಿಷಯವನ್ನು ಹಿಂಪಡೆಯುತ್ತದೆ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ನೀವು ಸಂವಹನ ನಡೆಸುತ್ತಿರುವ ವಿಂಡೋದ ಕಂಟೆಂಟ್ ಅನ್ನು ಪರೀಕ್ಷಿಸಿ."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"ಸ್ಪರ್ಶ-ಎಕ್ಸ್ಪ್ಲೋರ್ ಆನ್ ಮಾಡುತ್ತದೆ"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"ನಿಮ್ಮ ಫೋಟೋ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಿ"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬಳಸಿ"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ಇದು ನೀವೇ ಎಂದು ಪರಿಶೀಲಿಸಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index fc39271..ffbe631 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"생체 신호에 관한 센서 데이터에 액세스"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"알림"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"알림 표시"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"창 콘텐츠 가져오기"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"상호작용 중인 창의 콘텐츠를 검사합니다."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"터치하여 탐색 사용"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"앱에서 사진 컬렉션을 수정하도록 허용합니다."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"미디어 컬렉션에서 위치 읽기"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"앱에서 미디어 컬렉션의 위치를 읽도록 허용합니다."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"생체 인식 사용"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"생체 인식 또는 화면 잠금을 사용"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"본인 확인"</string>
@@ -1027,7 +1067,7 @@
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"중지"</string>
<string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"되감기"</string>
<string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"빨리 감기"</string>
- <string name="emergency_calls_only" msgid="3057351206678279851">"긴급 통화만 허용"</string>
+ <string name="emergency_calls_only" msgid="3057351206678279851">"긴급 전화만 허용"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"네트워크 잠김"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="2867953953604224166">"SIM이 PUK 잠김 상태입니다."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"사용자 가이드를 참조하거나 고객지원팀에 문의하세요."</string>
@@ -1572,7 +1612,7 @@
<string name="vpn_lockdown_config" msgid="8331697329868252169">"네트워크 또는 VPN 설정 변경"</string>
<string name="upload_file" msgid="8651942222301634271">"파일 선택"</string>
<string name="no_file_chosen" msgid="4146295695162318057">"파일을 선택하지 않았습니다."</string>
- <string name="reset" msgid="3865826612628171429">"초기화"</string>
+ <string name="reset" msgid="3865826612628171429">"재설정"</string>
<string name="submit" msgid="862795280643405865">"제출"</string>
<string name="car_mode_disable_notification_title" msgid="8450693275833142896">"운전 앱 실행 중"</string>
<string name="car_mode_disable_notification_message" msgid="8954550232288567515">"운전 앱을 종료하려면 탭하세요."</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"방향 패드 가운데"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"자동 클릭 유형 설정 패널"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"왼쪽 클릭"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"오른쪽 클릭"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"더블클릭"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"드래그"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"스크롤"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"일시중지"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"위치"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> 항목이 RESTRICTED 버킷으로 이동함"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index f8c0022..5f19cf7 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"организмдин абалына көз салган сенсордун дайындарына мүмкүнчүлүк алуу"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Билдирмелер"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"билдирмелерди көрсөтүү"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Терезедеги нерселерди алып туруу"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Учурда ачылып турган терезедеги маалыматты талдайт."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"\"Сыйпалап изилдөө\" мүмкүнчүлүгүн иштетет"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Колдонмого сүрөт жыйнагыңызды өзгөртүүгө мүмкүнчүлүк берет."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"медиа жыйнагыңыз сакталган жерлерди окуу"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Колдонмого медиа жыйнагыңыз сакталган жерлерди окууга мүмкүнчүлүк берет."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Биометрикалык параметрлерди колдонуу"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Биометрикалык жөндөөнү же экрандын кулпусун колдонуу"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Өзүңүздү ырастаңыз"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad\'дын ортоңку баскычы"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Авточыкылдатуу түрүнүн параметрлеринин панели"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Сол баскычын чыкылдатуу"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Оң баскычын чыкылдатуу"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Эки жолу чыкылдатуу"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Сүйрөө"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Сыдыруу"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Тындыруу"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Орду"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ЧЕКТЕЛГЕН чакага коюлган"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 429f3f7..fa1ff2b 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ເຂົ້າຫາຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານ"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"ການແຈ້ງເຕືອນ"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"ສະແດງການແຈ້ງເຕືອນ"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ດຶງຂໍ້ມູນເນື້ອຫາໃນໜ້າຈໍ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ກວດກາເນື້ອຫາຂອງໜ້າຈໍທີ່ທ່ານກຳລັງມີປະຕິສຳພັນນຳ."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"ເປີດໃຊ້ \"ການສຳຫຼວດໂດຍສຳຜັດ\""</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຄໍເລັກຊັນຮູບຂອງທ່ານ."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"ອະນຸຍາດໃຫ້ແອັບອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ໃຊ້ລະບົບຊີວະມິຕິ"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ໃຊ້ລະບົບຊີວະມິຕິ ຫຼື ການລັອກໜ້າຈໍ"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ຢັ້ງຢືນວ່າແມ່ນທ່ານ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 3ca681b..b9303fa 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"pasiekti jutiklių duomenis apie gyvybinius ženklus"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Pranešimai"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"rodyti pranešimus"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Gauti lango turinį"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Tikrinti lango, su kuriuo sąveikaujate, turinį."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Įjungti „Naršyti paliečiant“"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Programai leidžiama keisti nuotraukų kolekciją."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"skaityti vietoves iš medijos kolekcijos"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Programai leidžiama skaityti vietoves iš medijos kolekcijos."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Naudoti biometrinius duomenis"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Naudoti biometrinius duomenis arba ekrano užraktą"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Patvirtinkite, kad tai jūs"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1e7ffd1..3a1df4b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"piekļūt sensoru datiem par jūsu veselības rādījumiem"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Paziņojumi"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"rādīt paziņojumus"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Izgūt loga saturu."</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Skatīt tā loga saturu, ar kuru mijiedarbojaties."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Aktivizēt funkciju “Pārlūkot pieskaroties”."</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Ļauj lietotnei pārveidot jūsu fotoattēlu kolekciju."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"Lasīt atrašanās vietas no jūsu multivides kolekcijas"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Ļauj lietotnei lasīt atrašanās vietas no jūsu multivides kolekcijas."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biometrijas izmantošana"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrijas vai ekrāna bloķēšanas izmantošana"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Apstipriniet, ka tas esat jūs"</string>
@@ -2248,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Virzienu slēdzis — centrs"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Automātiskās klikšķināšanas veida iestatījumu panelis"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Noklikšķināt ar peles kreiso pogu"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Noklikšķināt ar peles labo pogu"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Veikt dubultklikšķi"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Vilkt"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Ritināt"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pārtraukt"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Pozīcija"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Pakotne “<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>” ir ievietota ierobežotā kopā."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index c1a7c1d..c6d51c7 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"пристапува до податоците од сензорите за виталните функции"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Известувања"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"да прикажува известувања"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"да ги вчитува содржините од прозорците"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"да ги проверува содржините од прозорецот што го користите"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"да вклучи „Истражувај со допир“"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Дозволува апликацијата да ја менува вашата збирка на фотографии."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"да чита локации од вашата збирка на аудиовизуелни содржини"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Дозволува апликацијата да чита локации од вашата збирка на аудиовизуелни содржини."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Користи биометрика"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Користи биометрика или заклучен екран"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Потврдете дека сте вие"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Навигациско копче за средина"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Табла со поставки за вид автоматско кликнување"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Кликни со лево копче"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Кликнување со десно копче"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Кликнување двапати"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Повлекување"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Лизгање"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Паузирај"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Позиционирај"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> е ставен во корпата ОГРАНИЧЕНИ"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 5c31433..17fa98b 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"നിങ്ങളുടെ ജീവാധാര ലക്ഷണങ്ങളെ കുറിച്ചുള്ള സെൻസർ വിവരങ്ങൾ ആക്സസ് ചെയ്യുക"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"അറിയിപ്പുകൾ"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"അറിയിപ്പുകൾ കാണിക്കുക"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"വിൻഡോ ഉള്ളടക്കം വീണ്ടെടുക്കുക"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"നിങ്ങൾ സംവദിക്കുന്ന ഒരു വിൻഡോയുടെ ഉള്ളടക്കം പരിശോധിക്കുക."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"സ്പർശനം വഴി പര്യവേക്ഷണം ചെയ്യുക, ഓണാക്കുക"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"നിങ്ങളുടെ ഫോട്ടോ ശേഖരം പരിഷ്ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുക"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ബയോമെട്രിക്സ് ഉപയോഗിക്കുക"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ബയോമെട്രിക്സ് അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ഇത് നിങ്ങളാണെന്ന് പരിശോധിച്ചുറപ്പിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 24637fa..48b2aa8 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"таны биеийн байдлын талаарх мэдрэгч бүхий өгөгдөлд нэвтрэх"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Мэдэгдэл"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"мэдэгдэл харуулах"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Цонхны агуулгыг авах"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Таны харилцан үйлчлэх цонхны контентоос шалгах."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Хүрэлтээр сонсохыг асаах"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Таны зургийн цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"медиа цуглуулгаасаа байршлыг унших"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Таны медиа цуглуулгаас байршлыг унших зөвшөөрлийг аппад олгодог."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Биометр ашиглах"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Биометр эсвэл дэлгэцийн түгжээ ашиглах"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Өөрийгөө мөн гэдгийг баталгаажуулаарай"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad гол"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Автомат товшилтын төрлийн тохиргооны түр зуурын самбар"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Зүүн талыг товших"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Баруун талыг товших"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"2 товших"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Чирэх"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Гүйлгэх"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Түр зогсоох"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Байрлал"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>-г ХЯЗГААРЛАСАН сагс руу орууллаа"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 0717eb9..03400f2 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"आपल्या महत्त्वाच्या मापनांविषयी सेन्सर डेटा अॅक्सेस करा"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"सूचना"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"सूचना दाखवा"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"विंडोमधील आशय पुन्हा मिळवा"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"तुम्ही वापरत असलेल्या विंडोमधील आशय तपासा."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"स्पर्श करून अन्वेषण सुरू करा"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"ॲपला तुमच्या फोटो संग्रहामध्ये सुधारणा करण्याची अनुमती देते."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"तुमच्या मीडिया संग्रहातून स्थाने वाचा"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"ॲपला तुमच्या मीडिया संग्रहामध्येील स्थाने वाचण्यासाठी अनुमती देते."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"बायोमेट्रिक वापरा"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"बायोमेट्रिक किंवा स्क्रीन लॉक वापरा"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"हे तुम्हीच आहात याची पडताळणी करा"</string>
@@ -1344,13 +1384,13 @@
<string name="volume_call" msgid="7625321655265747433">"कॉल-मधील व्हॉल्यूम"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"ब्लूटूथ कॉल-मधील व्हॉल्यूम"</string>
<string name="volume_alarm" msgid="4486241060751798448">"अलार्म व्हॉल्यूम"</string>
- <string name="volume_notification" msgid="6864412249031660057">"सूचना व्हॉल्यूम"</string>
+ <string name="volume_notification" msgid="6864412249031660057">"नोटिफिकेशन व्हॉल्यूम"</string>
<string name="volume_unknown" msgid="4041914008166576293">"व्हॉल्यूम"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"ब्लूटूथ व्हॉल्यूम"</string>
<string name="volume_icon_description_ringer" msgid="2187800636867423459">"रिंगटोन व्हॉल्यूम"</string>
<string name="volume_icon_description_incall" msgid="4491255105381227919">"कॉल व्हॉल्यूम"</string>
<string name="volume_icon_description_media" msgid="4997633254078171233">"मीडिया व्हॉल्यूम"</string>
- <string name="volume_icon_description_notification" msgid="579091344110747279">"सूचना व्हॉल्यूम"</string>
+ <string name="volume_icon_description_notification" msgid="579091344110747279">"नोटिफिकेशन व्हॉल्यूम"</string>
<string name="ringtone_default" msgid="9118299121288174597">"डीफॉल्ट रिंगटोन"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"डीफॉल्ट (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="397111123930141876">"काहीही नाही"</string>
@@ -2228,7 +2268,7 @@
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"होम"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"मागे जा"</string>
<string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"अलीकडील ॲप्स"</string>
- <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"सूचना"</string>
+ <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"नोटिफिकेशन"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"क्विक सेटिंग्ज"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"पॉवर डायलॉग"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"स्क्रीन लॉक करा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5cac65d..889324c 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"akses data penderia tentang tanda vital anda"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Pemberitahuan"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"tunjukkan pemberitahuan"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Dapatkan kembali kandungan tetingkap"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Periksa kandungan tetingkap yang berinteraksi dengan anda."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Hidupkan Teroka melalui Sentuhan"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Membenarkan apl mengubah suai koleksi foto anda."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"baca lokasi daripada koleksi media anda"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Membenarkan apl membaca lokasi daripada koleksi media anda."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Gunakan biometrik"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gunakan biometrik atau kunci skrin"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Sahkan diri anda"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 10bcd1b..67f0841 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"သင်၏အရေးကြီးသော ကျန်းမာရေးလက္ခဏာဆိုင်ရာ အာရုံခံကိရိယာဒေတာကို ရယူရန်"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"အကြောင်းကြားချက်များ"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"အကြောင်းကြားချက်များ ပြနိုင်သည်"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ဝင်းဒိုးတွင် ပါရှိသည်များကို ပြန်လည်ရယူရန်"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"သင်အသုံးပြုနေသော ဝင်းဒိုးတွင် ပါရှိသည်များကို ကြည့်ရှုစစ်ဆေးသည်။"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"တို့ထိခြင်းဖြင့် ရှာဖွေမှုကို ဖွင့်ရန်"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"အက်ပ်အား သင့်ဓာတ်ပုံစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခြင်း"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"အက်ပ်အား သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခွင့်ပေးသည်။"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ဇီဝမက်ထရစ်အချက်အလက်များ သုံးခြင်း"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ဇီဝမက်ထရစ်အချက်အလက်များ (သို့) ဖန်သားပြင်လော့ခ်ချခြင်းကို သုံးခြင်း"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"သင်ဖြစ်ကြောင်း အတည်ပြုပါ"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad အလယ်"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"အော်တိုနှိပ်ခြင်း အမျိုးအစား ဆက်တင်အကန့်"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"ဘယ်ကလစ်"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"ညာဘက်ခလုတ်ကို နှိပ်ရန်"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"နှစ်ချက်နှိပ်ရန်"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"ဖိဆွဲရန်"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"လှိမ့်ရန်"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"ခဏရပ်ရန်"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"နေရာ"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ကို တားမြစ်ထားသော သိမ်းဆည်းမှုအတွင်းသို့ ထည့်ပြီးပါပြီ"</string>
@@ -2518,7 +2554,7 @@
<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>
- <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"အသုံးပြုသူ ပြောင်းရန်"</string>
+ <string name="bg_user_sound_notification_button_switch_user" msgid="3091969648572788946">"အသုံးပြုသူပြောင်းရန်"</string>
<string name="bg_user_sound_notification_button_mute" msgid="4942158515665615243">"အသံပိတ်ရန်"</string>
<string name="bg_user_sound_notification_message" msgid="8613881975316976673">"အသံပိတ်ရန် တို့ပါ"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="6535007304687100909">"ဘရောင်ဇာ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 800f118..44458ba 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"få tilgang til sensordata om de vitale tegnene dine"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Varsler"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"vise varsler"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"hente innhold i vinduer"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Appen analyserer innholdet i vinduer du samhandler med."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"slå på berøringsutforsking"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Lar appen gjøre endringer i bildesamlingen din."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"lese posisjoner fra mediesamlingen din"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Lar appen lese posisjoner fra mediesamlingen din."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Bruk biometri"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Bruk biometri eller skjermlås"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Bekreft at det er deg"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Midt på styrepilene"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Innstillingspanel for type autoklikk"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Venstreklikk"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Høyreklikk"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dobbeltklikk"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Dra"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Rull"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Sett på pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Plassér"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> er blitt plassert i TILGANGSBEGRENSET-toppmappen"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index ce0c67e..2591a15 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"तपाईंको महत्त्वपूर्ण संकेत बारे सेन्सर डेटा पहुँच गर्नुहोस्"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"नोटिफिकेसनहरू"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"सूचनाहरू देखाउनुहोस्"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"विन्डो सामग्रीको पुनःबहाली गर्नुहोस्।"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"तपाईँको अन्तरक्रिया भइरहेको विन्डोको सामग्रीको निरीक्षण गर्नुहोस्।"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"छोएर गरिने खोजलाई सुचारु गर्नुहोस्"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"यसले एपलाई तपाईंको तस्बिरको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"आफ्नो मिडियाको सङ्ग्रहका स्थानहरू पढ्नुहोस्"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"यसले एपलाई तपाईंको मिडिया सङ्ग्रहका स्थानहरू पढ्न दिन्छ।"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"बायोमेट्रिक्स प्रयोग गर्नुहोस्"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"बायोमेट्रिक्स वा स्क्रिन लक प्रयोग गर्नुहोस्"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"यो व्यक्ति तपाईं नै हो भन्ने प्रमाणित गर्नुहोस्"</string>
@@ -1344,13 +1384,13 @@
<string name="volume_call" msgid="7625321655265747433">"इन-कल भोल्युम"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"ब्लुटुथ भित्री-कल मात्रा"</string>
<string name="volume_alarm" msgid="4486241060751798448">"आलर्मको भोल्युम"</string>
- <string name="volume_notification" msgid="6864412249031660057">"सूचनाको भोल्युम"</string>
+ <string name="volume_notification" msgid="6864412249031660057">"नोटिफिकेसनको भोल्युम"</string>
<string name="volume_unknown" msgid="4041914008166576293">"मात्रा"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"ब्लुटुथ भोल्युम"</string>
<string name="volume_icon_description_ringer" msgid="2187800636867423459">"घन्टिको आवाज मात्रा"</string>
<string name="volume_icon_description_incall" msgid="4491255105381227919">"कला मात्रा"</string>
<string name="volume_icon_description_media" msgid="4997633254078171233">"मिडियाको भोल्युम"</string>
- <string name="volume_icon_description_notification" msgid="579091344110747279">"सूचनाको भोल्युम"</string>
+ <string name="volume_icon_description_notification" msgid="579091344110747279">"नोटिफिकेसनको भोल्युम"</string>
<string name="ringtone_default" msgid="9118299121288174597">"डिफल्ट रिङटोन"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"डिफल्ट (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="397111123930141876">"कुनै पनि होइन"</string>
@@ -2088,12 +2128,9 @@
<string name="unpin_target" msgid="3963318576590204447">"अनपिन गर्नुहोस्"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> लाई अनपिन गर्नुहोस्"</string>
<string name="app_info" msgid="6113278084877079851">"एपका बारे जानकारी"</string>
- <!-- no translation found for shortcut_group_a11y_title (2992150163811583865) -->
- <skip />
- <!-- no translation found for suggested_apps_group_a11y_title (2804876567839501831) -->
- <skip />
- <!-- no translation found for all_apps_group_a11y_title (7020352520224108745) -->
- <skip />
+ <string name="shortcut_group_a11y_title" msgid="2992150163811583865">"सामग्री सीधै सेयर गर्नका निम्ति चयन गरिएका व्यक्ति वा समूहहरू"</string>
+ <string name="suggested_apps_group_a11y_title" msgid="2804876567839501831">"सिफारिस गरिएका एपहरू"</string>
+ <string name="all_apps_group_a11y_title" msgid="7020352520224108745">"एपहरूको सूची"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"डेमो सुरु गर्दै…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"यन्त्रलाई रिसेट गर्दै…"</string>
@@ -2250,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad को बिचको बटन"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"अटोक्लिकको प्रकारसम्बन्धी सेटिङको प्यानल"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"बायाँ क्लिक गर्नुहोस्"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"राइट क्लिक गर्नुहोस्"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"डबल क्लिक गर्नुहोस्"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"ड्र्याग गर्नुहोस्"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"स्क्रोल गर्नुहोस्"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"पज गर्नुहोस्"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"स्थिति"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> लाई प्रतिबन्धित बाल्टीमा राखियो"</string>
@@ -2534,12 +2567,8 @@
<string name="keyboard_shortcut_group_applications_maps" msgid="7950000659522589471">"नक्सा"</string>
<string name="keyboard_shortcut_group_applications" msgid="3010389163951364798">"एपहरू"</string>
<string name="fingerprint_loe_notification_msg" msgid="3927447270148854546">"तपाईंको फिंगरप्रिन्ट अब पहिचान गर्न सकिँदैन। फिंगरप्रिन्ट अनलक फेरि सेटअप गर्नुहोस्।"</string>
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_title (468577168569874967) -->
- <skip />
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_text (6695268246267993166) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_title (3461195995882871461) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_text (6537085605929303187) -->
- <skip />
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_title" msgid="468577168569874967">"लक भएपछि USB डिभाइस घुसाइएको छ"</string>
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_text" msgid="6695268246267993166">"Android लक भएपछि USB डिभाइस घुसाइएको छ। USB डिभाइस प्रयोग गर्न कृपया सुरुमा Android अनलक गर्नुहोस् र त्यसपछि USB डिभाइस फेरि घुसाउनुहोस्।"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_title" msgid="3461195995882871461">"USB सम्बन्धी शङ्कास्पद गतिविधि"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_text" msgid="6537085605929303187">"USB डेटा सिग्नल अफ गरिएको छ।"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3466641..bbdc1bb 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"toegang krijgen tot sensorgegevens over je vitale functies"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Meldingen"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"meldingen tonen"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Content van vensters ophalen"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"De content inspecteren van een venster waarmee je interactie hebt."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Verkennen via aanraking aanzetten"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Hiermee sta je de app toe je fotocollectie aan te passen."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"locaties van je mediacollecties bekijken"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Hiermee sta je de app toe locaties van je mediacollectie te bekijken."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biometrische gegevens gebruiken"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrische gegevens of schermvergrendeling gebruiken"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Je identiteit bevestigen"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Nieuwe simkaart geplaatst"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Tik om dit in te stellen"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Je tijdzone is gewijzigd"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Je bent nu in <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Je tijdzone is <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Tijd instellen"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Datum instellen"</string>
<string name="date_time_set" msgid="4603445265164486816">"Instellen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 418231f..a1b24eb 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ଆପଣଙ୍କ ଗୁରୁତପୂର୍ଣ୍ଣ ସଂକେତଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର୍ ଡାଟା ଆକ୍ସେସ୍ କରେ"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଦେଖାନ୍ତୁ"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ୱିଣ୍ଡୋ କଣ୍ଟେଣ୍ଟ ହାସଲ କରନ୍ତୁ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ଆପଣ କାମ କରୁଥିବା ୱିଣ୍ଡୋର କଣ୍ଟେଣ୍ଟକୁ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"ସ୍ପର୍ଶ ଦ୍ୱାରା ଏକ୍ସପ୍ଲୋର୍ ଅନ୍ କରନ୍ତୁ"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"ଆପଣଙ୍କ ଫଟୋ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଲୋକେସନ୍ଗୁଡିକୁ ପଢନ୍ତୁ"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଅବସ୍ଥାନଗୁଡିକୁ ପଢିବାକୁ ଆପ୍ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ବାୟୋମେଟ୍ରିକ୍ସ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ବାୟୋମେଟ୍ରିକ୍ସ ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ଏହା ଆପଣ ବୋଲି ଯାଞ୍ଚ କରନ୍ତୁ"</string>
@@ -1572,7 +1612,7 @@
<string name="vpn_lockdown_config" msgid="8331697329868252169">"ନେଟ୍ୱର୍କ କିମ୍ବା VPN ସେଟିଙ୍ଗ ବଦଳାନ୍ତୁ"</string>
<string name="upload_file" msgid="8651942222301634271">"ଫାଇଲ୍ ଚୟନ କରନ୍ତୁ"</string>
<string name="no_file_chosen" msgid="4146295695162318057">"କୌଣସି ଫାଇଲ୍ ଚୟନ କରାଯାଇନାହିଁ"</string>
- <string name="reset" msgid="3865826612628171429">"ରିସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="reset" msgid="3865826612628171429">"ରିସେଟ କରନ୍ତୁ"</string>
<string name="submit" msgid="862795280643405865">"ଦାଖଲ କରନ୍ତୁ"</string>
<string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ଡ୍ରାଇଭିଙ୍ଗ ଆପ୍ ଚାଲୁଛି"</string>
<string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ଡ୍ରାଇଭିଙ୍ଗ ଆପ୍ରୁ ବାହାରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad କେନ୍ଦ୍ର"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"ଅଟୋକ୍ଲିକ ପ୍ରକାର ସେଟିଂସ ପେନେଲ"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"ବାମ ବଟନ କ୍ଲିକ କରନ୍ତୁ"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"ଡାହାଣ କ୍ଲିକ କରନ୍ତୁ"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"ଦୁଇ ଥର କ୍ଲିକ କରନ୍ତୁ"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"ଡ୍ରାଗ କରନ୍ତୁ"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"ସ୍କ୍ରୋଲ କରନ୍ତୁ"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"ବିରତ କରନ୍ତୁ"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"ସ୍ଥିତି"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>କୁ ପ୍ରତିବନ୍ଧିତ ବକେଟରେ ରଖାଯାଇଛି"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 26769a6..70dcd66 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ਆਪਣੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਚਿੰਨ੍ਹਾਂ ਬਾਰੇ ਸੰਵੇਦਕ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"ਸੂਚਨਾਵਾਂ"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"ਸੂਚਨਾਵਾਂ ਦਿਖਾਓ"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ਵਿੰਡੋ ਸਮੱਗਰੀ ਮੁੜ-ਪ੍ਰਾਪਤ ਕਰਨਾ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ਉਸ ਵਿੰਡੋ ਸਮੱਗਰੀ ਦੀ ਜਾਂਚ ਕਰੋ, ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਅੰਤਰਕਿਰਿਆ ਕਰ ਰਹੇ ਹੋ"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"\'ਸਪੱਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ ਕਰੋ\' ਚਾਲੂ ਕਰਨਾ"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਟੋ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨਾ"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ਬਾਇਓਮੈਟ੍ਰਿਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ਬਾਇਓਮੈਟ੍ਰਿਕ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ਆਪਣੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e091700..c92c2bb 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"dostęp do danych czujnika podstawowych funkcji życiowych"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Powiadomienia"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"pokazuj powiadomienia"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Pobieranie zawartości okna"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Sprawdzanie zawartości okna, z którego korzystasz."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Włączenie czytania dotykiem"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Zezwala aplikacji na modyfikowanie kolekcji zdjęć."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"odczytywanie lokalizacji z kolekcji multimediów"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Zezwala aplikacji na odczytywanie lokalizacji z kolekcji multimediów."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Używaj biometrii"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Używaj biometrii lub blokady ekranu"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Potwierdź, że to Ty"</string>
@@ -1411,7 +1451,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Włożono nową kartę SIM"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Kliknij, by skonfigurować"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Zmieniła się Twoja strefa czasowa"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Jesteś teraz w strefie <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Twoja aktualna strefa to <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Ustaw godzinę"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Ustaw datę"</string>
<string name="date_time_set" msgid="4603445265164486816">"Ustaw"</string>
@@ -2249,14 +2289,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad – środek"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel ustawień typu automatycznego kliknięcia"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Kliknięcie lewym przyciskiem"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Kliknięcie prawym przyciskiem"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dwukrotne kliknięcie"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Przeciąganie"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Przewijanie"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Wstrzymaj"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Pozycja"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Umieszczono pakiet <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> w zasobniku danych RESTRICTED"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 06b43cb..99c4375 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"acesse dados do sensor sobre seus sinais vitais"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificações"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"mostrar notificações"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Acessar conteúdo de uma janela"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspeciona o conteúdo de uma janela com a qual você está interagindo."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Ativar Explorar por toque"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que o app modifique sua coleção de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ler locais na sua coleção de mídias"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que o app leia os locais na sua coleção de mídias."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Usar biometria"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar biometria ou bloqueio de tela"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme que é você"</string>
@@ -1970,7 +2010,7 @@
<string name="zen_mode_rule_name_combination" msgid="7174598364351313725">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
<string name="toolbar_collapse_description" msgid="8009920446193610996">"Recolher"</string>
<string name="zen_mode_feature_name" msgid="3785547207263754500">"Não perturbe"</string>
- <string name="zen_mode_downtime_feature_name" msgid="5886005761431427128">"Tempo de inatividade"</string>
+ <string name="zen_mode_downtime_feature_name" msgid="5886005761431427128">"Intervalo"</string>
<string name="zen_mode_default_weeknights_name" msgid="7902108149994062847">"Durante a semana à noite"</string>
<string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fim de semana"</string>
<string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index f48c326..a453546 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"aceder a dados do sensor acerca dos seus sinais vitais"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificações"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"mostrar notificações"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Obter conteúdo da janela"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspecionar o conteúdo de uma janela com a qual está a interagir."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Ativar Explorar Através do Toque"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que a app modifique a sua coleção de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ler as localizações a partir da sua coleção de multimédia"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que a app leia as localizações a partir da sua coleção de multimédia."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Usar a biometria"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar a biometria ou o bloqueio de ecrã"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme a sua identidade"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 06b43cb..99c4375 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"acesse dados do sensor sobre seus sinais vitais"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificações"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"mostrar notificações"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Acessar conteúdo de uma janela"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspeciona o conteúdo de uma janela com a qual você está interagindo."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Ativar Explorar por toque"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que o app modifique sua coleção de fotos."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ler locais na sua coleção de mídias"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que o app leia os locais na sua coleção de mídias."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Usar biometria"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar biometria ou bloqueio de tela"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme que é você"</string>
@@ -1970,7 +2010,7 @@
<string name="zen_mode_rule_name_combination" msgid="7174598364351313725">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
<string name="toolbar_collapse_description" msgid="8009920446193610996">"Recolher"</string>
<string name="zen_mode_feature_name" msgid="3785547207263754500">"Não perturbe"</string>
- <string name="zen_mode_downtime_feature_name" msgid="5886005761431427128">"Tempo de inatividade"</string>
+ <string name="zen_mode_downtime_feature_name" msgid="5886005761431427128">"Intervalo"</string>
<string name="zen_mode_default_weeknights_name" msgid="7902108149994062847">"Durante a semana à noite"</string>
<string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fim de semana"</string>
<string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 73f532a..28728b5 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"să acceseze datele de la senzori despre semnele vitale"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Notificări"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"să afișeze notificări"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"să preia conținutul ferestrei"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspectează conținutul unei ferestre cu care interacționezi."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"să activeze funcția Explorează prin atingere"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite aplicației să-ți modifice colecția de fotografii."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"să citească locațiile din colecția media"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite aplicației să citească locațiile din colecția ta media."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Folosește sistemele biometrice"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Folosește sistemele biometrice sau blocarea ecranului"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirmă-ți identitatea"</string>
@@ -2248,14 +2288,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad centru"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panoul de setări pentru clicul automat"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Clic stânga"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Clic dreapta"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dublu clic"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Trage"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Derulează"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Întrerupe"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Poziție"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> a fost adăugat la grupul RESTRICȚIONATE"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index e0e0807..f587a73 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"доступ к данным датчиков о состоянии организма"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Уведомления"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"показ уведомлений"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Получать содержимое окна"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Анализировать содержимое активного окна."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Включать Изучение касанием"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Приложение сможет вносить изменения в вашу фотоколлекцию."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"Доступ к геоданным в медиаколлекции"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Приложение получит доступ к геоданным в вашей медиаколлекции."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Использовать биометрию"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Использовать биометрию или блокировку экрана"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Подтвердите, что это вы"</string>
@@ -1014,7 +1054,7 @@
<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="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"SIM-карта отсутствует"</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">"В устройстве Android TV отсутствует SIM-карта."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="6184187634180854181">"В телефоне отсутствует SIM-карта."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 45dd5df..f30a483 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ඔබේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්ත වෙත පිවිසෙන්න"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"දැනුම්දීම්"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"දැනුම්දීම් පෙන්වන්න"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"කවුළු අන්න්තර්ගතය ලබාගන්න"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ඔබ අන්තර්ක්රියාකාරී වන කවුළුවේ අන්තර්ගතය පරීක්ෂා කරන්න."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"ස්පර්ශයෙන් ගවේෂණය සක්රිය කරන්න"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"ඔබගේ ඡායාරූප එකතුව වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"ඔබගේ මාධ්ය එකතුවෙන් ස්ථාන කියවන්න"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"ඔබගේ මාධ්ය එකතුවෙන් ස්ථාන කියවීමට යෙදුමට ඉඩ දෙයි."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ජෛවමිතික භාවිත කරන්න"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ජෛවමිතික හෝ තිර අගුල භාවිත කරන්න"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"එය ඔබ බව තහවුරු කරන්න"</string>
@@ -2088,12 +2128,9 @@
<string name="unpin_target" msgid="3963318576590204447">"ගලවන්න"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ඇමුණුම ඉවත් කරන්න"</string>
<string name="app_info" msgid="6113278084877079851">"යෙදුම් තොරතුරු"</string>
- <!-- no translation found for shortcut_group_a11y_title (2992150163811583865) -->
- <skip />
- <!-- no translation found for suggested_apps_group_a11y_title (2804876567839501831) -->
- <skip />
- <!-- no translation found for all_apps_group_a11y_title (7020352520224108745) -->
- <skip />
+ <string name="shortcut_group_a11y_title" msgid="2992150163811583865">"සෘජු බෙදා ගැනීමේ ඉලක්ක"</string>
+ <string name="suggested_apps_group_a11y_title" msgid="2804876567839501831">"යෙදුම් යෝජනා"</string>
+ <string name="all_apps_group_a11y_title" msgid="7020352520224108745">"යෙදුම් ලැයිස්තුව"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ආදර්ශනය ආරම්භ කරමින්..."</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"උපාංගය යළි සකසමින්..."</string>
@@ -2250,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad මැද"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"ස්වයං ක්ලික් ආකාර සැකසීම් පැනලය"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"වම්පස ක්ලිකය"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"දකුණු ක්ලිකය"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"දෙවරක් ක්ලික් කරන්න"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"අදින්න"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"අනුචලනය කරන්න"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"විරාම කරන්න"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"ස්ථානය"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> අවහිර කළ බාල්දියට දමා ඇත"</string>
@@ -2534,12 +2567,8 @@
<string name="keyboard_shortcut_group_applications_maps" msgid="7950000659522589471">"සිතියම්"</string>
<string name="keyboard_shortcut_group_applications" msgid="3010389163951364798">"යෙදුම්"</string>
<string name="fingerprint_loe_notification_msg" msgid="3927447270148854546">"ඔබේ ඇඟිලි සලකුණු තවදුරටත් හඳුනාගත නොහැක. ඇඟිලි සලකුණු අගුළු හැරීම නැවත පිහිටුවන්න."</string>
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_title (468577168569874967) -->
- <skip />
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_text (6695268246267993166) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_title (3461195995882871461) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_text (6537085605929303187) -->
- <skip />
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_title" msgid="468577168569874967">"අගුළු දමා ඇති විට USB උපාංගය පේනුගත කර ඇත"</string>
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_text" msgid="6695268246267993166">"Android අගුළු දමා ඇති විට USB උපාංගය පේනුගත කර ඇත. උපාංගය භාවිතා කිරීමට, පළමුව Android අගුළු හැර, පසුව එය භාවිතා කිරීමට USB උපාංගය නැවත ඇතුළු කරන්න."</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_title" msgid="3461195995882871461">"සැක සහිත USB ක්රියාකාරකම"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_text" msgid="6537085605929303187">"USB දත්ත සංඥාව අබල කර ඇත."</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d675978..49600ce 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"prístup k dátam senzorov vašich životných funkcií"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Upozornenia"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"zobrazovať upozornenia"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Načítať obsah okna"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Môžete preskúmať obsah okna, s ktorým pracujete."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Zapnúť funkciu Preskúmanie dotykom"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Umožňuje aplikácii upravovať zbierku fotiek."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"čítať polohy zo zbierky médií"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Umožňuje aplikácii čítať polohy zo zbierky médií."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Použiť biometrické údaje"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Použiť biometrické údaje alebo zámku obrazovky"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Potvrďte, že ste to vy"</string>
@@ -1433,8 +1473,8 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"Pripojené zariadenie sa nabíja. Ďalšie možností získate klepnutím."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Bolo zistené analógové zvukové príslušenstvo"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Pripojené zariadenie nie je kompatibilné s týmto telefónom. Ďalšie informácie zobrazíte klepnutím."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"Ladenie cez USB je pripojené"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Klepnutím vypnite ladenie cez USB"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"Ladenie cez USB je zapnuté"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Klepnutím vypnete"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Vyberte, ak chcete zakázať ladenie cez USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Bezdrôtové ladenie je pripojené"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Klepnutím vypnete bezdrôtové ladenie"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0136f5f8..c8dc4ee 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"dostop do podatkov tipala o vaših vitalnih znakih"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Obvestila"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"prikaz obvestil"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Pridobiti vsebino okna"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Preverjanje vsebine okna, ki ga uporabljate."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Vklopiti raziskovanje z dotikom"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Aplikaciji omogoča spreminjanje zbirke fotografij."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"branje lokacij v predstavnostni zbirki"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Aplikaciji omogoča branje lokacij v predstavnostni zbirki."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Uporaba biometrike"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Uporaba biometrike ali odklepanja s poverilnico"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Potrdite, da ste res vi"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 37aa8bf..fa3eeae 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"qasu tek të dhënat e sensorëve rreth shenjave të tua jetësore"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Njoftimet"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"shfaq njoftimet"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Të nxjerrë përmbajtjen e dritares"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Inspekton përmbajtjen e dritares me të cilën po ndërvepron."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Të aktivizojë veçorinë \"Eksploro me prekje\""</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Lejon aplikacionin të modifikojë koleksionin tënd të fotografive."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"lexo vendndodhjet nga koleksioni yt i medias"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Lejon aplikacionin të lexojë vendndodhjet nga koleksioni yt i medias."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Përdor sistemet biometrike"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Përdor sistemet biometrike ose kyçjen e ekranit"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifiko që je ti"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Qendra e bllokut të drejtimit"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Paneli i cilësimeve për llojin e klikimit automatik"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Klikimi majtas"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Kliko djathtas"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Kliko dy herë"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Zvarrit"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Lëviz"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Vendos në pauzë"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Pozicioni"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> është vendosur në grupin E KUFIZUAR"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index a4f0e55..5481023 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -354,6 +354,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"приступа подацима сензора о виталним функцијама"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Обавештења"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"приказивање обавештења"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"да преузима садржај прозора"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Проверава садржај прозора са којим остварујете интеракцију."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"да укључи Истраживања додиром"</string>
@@ -649,6 +657,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Дозвољава апликацији да мења колекцију слика."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"читање локација из медијске колекције"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Дозвољава апликацији да чита локације из медијске колекције."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Користите биометрију"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Користите биометрију или откључавање екрана"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Потврдите идентитет"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e56097f..38634d5 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"få åtkomst till sensordata om dina vitalparametrar"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Aviseringar"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"visa aviseringar"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Hämta fönsterinnehåll"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Granska innehållet i ett fönster som du interagerar med."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Aktivera Explore by touch"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Tillåter att appen gör ändringar i din fotosamling."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"läsa av platser i din mediesamling"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Tillåter att appen läser av platser i din mediesamling."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Använd biometri"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Använd biometrisk data eller skärmlåset"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Verifiera din identitet"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Styrkors, mitten"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Inställningspanel för typ av automatiskt klick"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Vänsterklick"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Högerklicka"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Dubbelklicka"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Trycka och dra"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Scrolla"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pausa"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Position"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> har placerats i hinken RESTRICTED"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 03a581a..b6eab89 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"fikia data ya kitambuzi kuhusu alama zako muhimu"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Arifa"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"kuonyesha arifa"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Kufikia maudhui ya dirisha"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Kuchunguza maudhui ya dirisha unalotumia."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Kuwasha \'Chunguza kwa Kugusa\'"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Inaruhusu programu kubadilisha mkusanyiko wa picha zako."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"kusoma maeneo kwenye mkusanyiko wa vipengee vyako"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Inaruhusu programu kusoma maeneo kwenye mkusanyiko wa vipengee vyako."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Tumia bayometriki"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Tumia bayometriki au mbinu ya kufunga skrini"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Thibitisha kuwa ni wewe"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"SIM mpya imewekwa"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Gusa ili uiweke"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Saa za eneo lako zimebadilika"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Sasa unatumia saa za eneo za <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Sasa unatumia <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Weka saa"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Weka tarehe"</string>
<string name="date_time_set" msgid="4603445265164486816">"Weka"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Kitufe cha katikati cha Dpad"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Kidirisha cha mipangilio ya aina ya kubofya kiotomatiki"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Bofya kushoto"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Bofya kulia"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Bofya mara mbili"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Buruta"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Sogeza"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Sitisha"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Nafasi"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> kimewekwa katika kikundi KILICHODHIBITIWA"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 16c021e..d48f4a2 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"உங்கள் உடல் இயக்கம் பற்றி உணர்விகள் கூறும் தகவலைப் பார்க்கலாம்"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"அறிவிப்புகள்"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"அறிவிப்புகளைக் காட்டும்"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"சாளர உள்ளடக்கத்தைப் பெறும்"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"நீங்கள் பணியாற்றிக் கொண்டிருக்கும் சாளரத்தின் உள்ளடக்கத்தைப் பார்க்கலாம்."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"தொடுவதன் மூலம் அறிவதை இயக்கும்"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"உங்களின் படத் தொகுப்பை மாற்ற ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"மீடியா தொகுப்பிலிருந்து இடங்களை அறிதல்"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"உங்களின் மீடியா தொகுப்பிலிருந்து இடங்களை அறிந்துகொள்ள ஆப்ஸை அனுமதிக்கும்."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"பயோமெட்ரிக்ஸைப் பயன்படுத்து"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"பயோமெட்ரிக்ஸையோ திரைப் பூட்டையோ பயன்படுத்து"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"நீங்கள்தான் என உறுதிசெய்க"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"மையப் பகுதியைக் காட்டும் பட்டன்"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"ஆட்டோ கிளிக் வகை அமைப்புகள் பேனல்"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"இடது கிளிக்"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"வலது கிளிக் செய்யும்"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"இரு கிளிக் செய்யும்"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"இழுக்கும்"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"நகர்த்தும்"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"இடைநிறுத்து"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"நிலை"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> என்பதை வரம்பிடப்பட்ட பக்கெட்திற்குள் சேர்க்கப்பட்டது"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index c565618..84e56d2 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాను యాక్సెస్ చేస్తుంది"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"నోటిఫికేషన్లు"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"నోటిఫికేషన్లను చూపండి"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"విండో కంటెంట్ను తిరిగి పొందుతుంది"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"మీరు పరస్పర చర్య చేస్తున్న విండో కంటెంట్ను పరిశీలిస్తుంది."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"తాకడం ద్వారా విశ్లేషణను ఆన్ చేయండి"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"మీ ఫోటో సేకరణను ఎడిట్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"మీ మీడియా సేకరణ నుండి లొకేషన్లను చదవండి"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"మీ మీడియా సేకరణ నుండి లొకేషన్లను చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"బయోమెట్రిక్స్ను ఉపయోగించండి"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"బయోమెట్రిక్స్ను లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ఈ చర్య చేస్తోంది మీరేనని వెరిఫై చేయండి"</string>
@@ -887,7 +927,7 @@
<item msgid="6216981255272016212">"అనుకూలం"</item>
</string-array>
<string-array name="emailAddressTypes">
- <item msgid="7786349763648997741">"ఇల్లు"</item>
+ <item msgid="7786349763648997741">"హోమ్"</item>
<item msgid="435564470865989199">"కార్యాలయం"</item>
<item msgid="4199433197875490373">"ఇతరం"</item>
<item msgid="3233938986670468328">"అనుకూలం"</item>
@@ -1153,7 +1193,7 @@
<string name="year" msgid="5182610307741238982">"సంవత్సరం"</string>
<string name="years" msgid="5797714729103773425">"సంవత్సరాలు"</string>
<string name="now_string_shortest" msgid="3684914126941650330">"ఇప్పుడు"</string>
- <string name="duration_minutes_shortest" msgid="5744379079540806690">"<xliff:g id="COUNT">%d</xliff:g>నిమిషం"</string>
+ <string name="duration_minutes_shortest" msgid="5744379079540806690">"<xliff:g id="COUNT">%d</xliff:g>ని"</string>
<string name="duration_hours_shortest" msgid="1477752094141971675">"<xliff:g id="COUNT">%d</xliff:g>గంట"</string>
<string name="duration_days_shortest" msgid="4083124701676227233">"<xliff:g id="COUNT">%d</xliff:g>రోజు"</string>
<string name="duration_years_shortest" msgid="483982719231145618">"<xliff:g id="COUNT">%d</xliff:g>సం"</string>
@@ -2020,7 +2060,7 @@
<string name="call_notification_screening_text" msgid="8396931408268940208">"ఇన్కమింగ్ కాల్ను స్క్రీన్ చేయండి"</string>
<string name="default_notification_channel_label" msgid="3697928973567217330">"వర్గీకరించబడలేదు"</string>
<string name="promotional_notification_channel_label" msgid="7414844730492860233">"ప్రమోషన్లు"</string>
- <string name="social_notification_channel_label" msgid="106520267132019945">"సామాజికం"</string>
+ <string name="social_notification_channel_label" msgid="106520267132019945">"సోషల్ మీడియా"</string>
<string name="news_notification_channel_label" msgid="4299937455247883311">"వార్తలు"</string>
<string name="recs_notification_channel_label" msgid="4945985121418684297">"సిఫార్సులు"</string>
<string name="importance_from_user" msgid="2782756722448800447">"మీరు ఈ నోటిఫికేషన్ల ప్రాముఖ్యతను సెట్ చేశారు."</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"DPad మధ్యన"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"ఆటో-క్లిక్ టైప్ సెట్టింగ్ల ప్యానెల్"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"ఎడమ క్లిక్"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"రైట్-క్లిక్"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"డబుల్ క్లిక్"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"లాగండి"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"స్క్రోల్ చేయండి"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"పాజ్ చేయండి"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"స్థానం"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> పరిమితం చేయబడిన బకెట్లో ఉంచబడింది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index f4a3651..e16a28a 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"เข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพของคุณ"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"การแจ้งเตือน"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"แสดงการแจ้งเตือน"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"เรียกข้อมูลเนื้อหาของหน้าต่าง"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ตรวจสอบเนื้อหาของหน้าต่างที่คุณกำลังโต้ตอบอยู่"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"เปิด \"แตะเพื่อสำรวจ\""</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"อนุญาตให้แอปแก้ไขคอลเล็กชันรูปภาพของคุณ"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"อ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"อนุญาตให้แอปอ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"ใช้ข้อมูลไบโอเมตริก"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"ใช้ข้อมูลไบโอเมตริกหรือการล็อกหน้าจอ"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ยืนยันว่าเป็นตัวคุณ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 8782970..98de106 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"i-access ang data ng sensor tungkol sa iyong vital signs"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Mga Notification"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"magpakita ng mga notification"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Kunin ang content ng window"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Siyasatin ang nilalaman ng isang window kung saan ka nakikipag-ugnayan."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"I-on ang Explore by Touch"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Pinapayagan ang app na baguhin ang iyong koleksyon ng larawan."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"basahin ang mga lokasyon mula sa iyong koleksyon ng media"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Pinapayagan ang app na basahin ang mga lokasyon mula sa iyong koleksyon ng media."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Gumamit ng biometrics"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Gumamit ng biometrics o lock ng screen"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"I-verify na ikaw ito"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad Center"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Panel ng mga setting ng uri ng autoclick"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Mag-left click"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Mag-right click"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Mag-double click"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"I-drag"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Mag-scroll"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"I-pause"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Posisyon"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Inilagay ang <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> sa PINAGHIHIGPITANG bucket"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 7048a83..2ec15ca 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"hayati belirtilerinizle ilgili sensör verilerine erişme"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Bildirimler"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"bildirimleri göster"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Pencere içeriğini alma"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Etkileşim kurduğunuz pencerenin içeriğini inceler."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Dokunarak Keşfet\'i açma"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Uygulamanın fotoğraf koleksiyonunuzu değiştirmesine izin verir."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"medya koleksiyonunuzdaki konumları okuma"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Uygulamanın medya koleksiyonunuzdaki konumları okumasına izin verir."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biyometri kullan"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biyometri veya ekran kilidi kullan"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Kimliğinizi doğrulayın"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"Yeni SIM kart takıldı"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"Kurmak için dokunun"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"Saat diliminiz değişti"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"Artık <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>) saat dilimindesiniz"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"<xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>) saat dilimindesiniz"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Saati ayarlayın"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Tarihi ayarlayın"</string>
<string name="date_time_set" msgid="4603445265164486816">"Ayarla"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad Orta"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Otomatik tıklama türü ayarları paneli"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Sol tıklama"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Sağ tıklama"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Çift tıklama"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Sürükleme"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Kaydırma"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Duraklatma"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Konum"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> KISITLANMIŞ gruba yerleştirildi"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index a366990..9aeee9c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -355,6 +355,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"отримувати доступ до інформації датчиків про ваші життєві показники"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Сповіщення"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"показувати сповіщення"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Отримувати вміст вікна"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Перевіряти вміст вікна, з яким ви взаємодієте."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Увімкнути функцію дослідження дотиком"</string>
@@ -650,6 +658,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Додаток зможе змінювати вашу колекцію фотографій."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"розпізнавати геодані з колекції медіа-вмісту"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Додаток зможе розпізнавати геодані з вашої колекції медіа-вмісту."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Доступ через біометрію"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Використовувати біометрію або дані для розблокування екрана"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Підтвердьте, що це ви"</string>
@@ -2090,12 +2130,9 @@
<string name="unpin_target" msgid="3963318576590204447">"Відкріпити"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Відкріпити додаток <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Про додатки"</string>
- <!-- no translation found for shortcut_group_a11y_title (2992150163811583865) -->
- <skip />
- <!-- no translation found for suggested_apps_group_a11y_title (2804876567839501831) -->
- <skip />
- <!-- no translation found for all_apps_group_a11y_title (7020352520224108745) -->
- <skip />
+ <string name="shortcut_group_a11y_title" msgid="2992150163811583865">"Цілі прямого надання доступу"</string>
+ <string name="suggested_apps_group_a11y_title" msgid="2804876567839501831">"Рекомендовані додатки"</string>
+ <string name="all_apps_group_a11y_title" msgid="7020352520224108745">"Список додатків"</string>
<string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Запуск демонстрації…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"Скидання налаштувань пристрою…"</string>
@@ -2252,14 +2289,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Центральна кнопка панелі керування"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Панель налаштувань типу автоматичного натискання"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Натиснути лівою кнопкою миші"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Натиснути правою кнопкою миші"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Двічі натиснути"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Перетягнути"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Прокрутити"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Призупинити"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Змінити позицію"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Пакет \"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>\" додано в сегмент з обмеженнями"</string>
@@ -2536,12 +2569,8 @@
<string name="keyboard_shortcut_group_applications_maps" msgid="7950000659522589471">"Карти"</string>
<string name="keyboard_shortcut_group_applications" msgid="3010389163951364798">"Додатки"</string>
<string name="fingerprint_loe_notification_msg" msgid="3927447270148854546">"Ваші відбитки пальців більше не розпізнаються. Налаштуйте розблокування відбитком пальця повторно."</string>
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_title (468577168569874967) -->
- <skip />
- <!-- no translation found for usb_apm_usb_plugged_in_when_locked_notification_text (6695268246267993166) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_title (3461195995882871461) -->
- <skip />
- <!-- no translation found for usb_apm_usb_suspicious_activity_notification_text (6537085605929303187) -->
- <skip />
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_title" msgid="468577168569874967">"USB-пристрій підключено до заблокованого пристрою"</string>
+ <string name="usb_apm_usb_plugged_in_when_locked_notification_text" msgid="6695268246267993166">"USB-пристрій підключено, коли пристрій Android заблоковано. Щоб використовувати USB-пристрій, вийміть і знову вставте його після того, як розблокуєте пристрій Android."</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_title" msgid="3461195995882871461">"Підозрілі дії з USB-пристроєм"</string>
+ <string name="usb_apm_usb_suspicious_activity_notification_text" msgid="6537085605929303187">"Передавання даних через USB вимкнено."</string>
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index b725a12..f934b87 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"اپنی علامات حیات کے متعلق سنسر ڈیٹا تک رسائی حاصل کریں"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"اطلاعات"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"اطلاعات دکھائیں"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ونڈو مواد بازیافت کرنے کی"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"کسی ایسی ونڈو کے مواد کا معائنہ کریں جس کے ساتھ آپ تعامل کر رہے ہیں۔"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"ٹچ کے ذریعے دریافت کریں کو آن کرنے کی"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"ایپ کو آپ کی تصویر کے مجموعے میں ترمیم کی اجازت دیتا ہے۔"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"اپنی میڈيا کے مجموعے سے مقامات پڑھیں"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"ایپ کو آپ کی میڈيا کے مجموعے سے مقامات پڑھنے کی اجازت دیتا ہے۔"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"بایو میٹرکس استعمال کریں"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"بایو میٹرکس یا اسکرین لاک استعمال کریں"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"توثیق کریں کہ یہ آپ ہیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index a834669..942be79 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"organizm holati haqidagi sezgich ma’lumotlariga kirish"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Bildirishnomalar"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"bildirishnomalarni chiqarish"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Oynadagi kontentni o‘qiydi"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Joriy oynadagi kontent mazmunini aniqlaydi."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Teginib o‘rganish xizmatini yoqadi"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Ilovaga suratlar to‘plamingizni o‘zgartirishga ruxsat beradi."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"multimedia to‘plamidan joylashuv axborotini o‘qish"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Ilovaga multimedia to‘plamingizdan joylashuv axborotini o‘qishga ruxsat beradi."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Biometrik tasdiqlash"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Biometrika yoki ekran qulfi"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Oʻzingizni taniting"</string>
@@ -1431,11 +1471,11 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"Ulangan qurilma quvvatlanmoqda. Boshqa parametrlar uchun bosing."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Analogli audio uskuna aniqlandi"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Biriktirilgan qurilma mazkur telefon bilan mos emas. Batafsil axborot olish uchun bu yerga bosing."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"USB debagging ulandi"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"USB debaggingni uzish uchun bosing"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"USB debaging ulandi"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Uzish uchun bosing"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB orqali nosozliklarni tuzatishni o‘chirib qo‘yish uchun bosing."</string>
- <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Wi-Fi orqali debagging yoqildi"</string>
- <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Wi-Fi orqali debagging uzilishi uchun bosing"</string>
+ <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Wi-Fi orqali debaging yoqildi"</string>
+ <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Wi-Fi orqali debaging uzilishi uchun bosing"</string>
<string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Uni faolsizlantirish uchun bosing."</string>
<string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Xavfsizlik sinovi rejimi yoqildi"</string>
<string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Xavfsizlik sinovi rejimini faolsizlantirish uchun zavod sozlamalariga qaytaring."</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad – markazga"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Avtomatik klik turi sozlamalari paneli"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Chap klik"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Oʻng klik"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Ikki marta bosish"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Tortish"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Aylantirish"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Pauza"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Joylashuvi"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> cheklangan turkumga joylandi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c07ff1d..947a9b4 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"truy cập dữ liệu cảm biến về dấu hiệu sinh tồn của bạn"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Thông báo"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"hiển thị thông báo"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Truy xuất nội dung cửa sổ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Kiểm tra nội dung của cửa sổ bạn đang tương tác."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Bật tính năng Khám phá bằng cách chạm"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Cho phép ứng dụng này sửa đổi bộ sưu tập ảnh của bạn."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"đọc vị trí từ bộ sưu tập phương tiện"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Cho phép ứng dụng này đọc vị trí từ bộ sưu tập phương tiện của bạn."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Dùng dữ liệu sinh trắc học"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Dùng dữ liệu sinh trắc học hoặc phương thức khóa màn hình"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Xác minh danh tính của bạn"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Căn giữa bằng bàn phím di chuyển"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Bảng cài đặt loại tự động nhấp"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Nhấp chuột trái"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Nhấp chuột phải"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Nhấp đúp"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Kéo"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Cuộn"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Tạm dừng"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Vị trí"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"Đã đưa <xliff:g id="PACKAGE_NAME">%1$s</xliff:g> vào bộ chứa BỊ HẠN CHẾ"</string>
diff --git a/core/res/res/values-w192dp/dimens_watch.xml b/core/res/res/values-w192dp/dimens_watch.xml
deleted file mode 100644
index c6bf767..0000000
--- a/core/res/res/values-w192dp/dimens_watch.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<resources>
- <!-- 16.7% of display size -->
- <dimen name="base_error_dialog_top_padding">32dp</dimen>
- <!-- 5.2% of display size -->
- <dimen name="base_error_dialog_padding">10dp</dimen>
- <!-- 20.83% of display size -->
- <dimen name="base_error_dialog_bottom_padding">40dp</dimen>
-
- <!-- watch's indeterminate progress bar dimens based on the current screen size -->
- <dimen name="loader_horizontal_min_width_watch">67dp</dimen>
- <dimen name="loader_horizontal_min_height_watch">15dp</dimen>
-</resources>
diff --git a/core/res/res/values-w216dp/dimens_watch.xml b/core/res/res/values-w216dp/dimens_watch.xml
deleted file mode 100644
index e14ce5e..0000000
--- a/core/res/res/values-w216dp/dimens_watch.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources>
- <!-- watch's indeterminate progress bar dimens based on the current screen size -->
- <dimen name="loader_horizontal_min_width_watch">72dp</dimen>
- <dimen name="loader_horizontal_min_height_watch">16dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/core/res/res/values-w228dp/dimens_watch.xml b/core/res/res/values-w228dp/dimens_watch.xml
deleted file mode 100644
index 3c62656..0000000
--- a/core/res/res/values-w228dp/dimens_watch.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2025 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<resources>
- <!-- watch's indeterminate progress bar dimens based on the current screen size -->
- <dimen name="loader_horizontal_min_width">76dp</dimen>
- <dimen name="loader_horizontal_min_height">14dp</dimen>
-</resources>
diff --git a/core/res/res/values-w240dp/dimens_material.xml b/core/res/res/values-w240dp/dimens_material.xml
index e30aea4..bd26c8b 100644
--- a/core/res/res/values-w240dp/dimens_material.xml
+++ b/core/res/res/values-w240dp/dimens_material.xml
@@ -21,8 +21,4 @@
<dimen name="screen_percentage_12">28.8dp</dimen>
<dimen name="screen_percentage_15">36dp</dimen>
<dimen name="screen_percentage_3646">87.5dp</dimen>
-
- <!-- watch's indeterminate progress bar dimens based on the current screen size -->
- <dimen name="progress_indeterminate_horizontal_min_width_watch">80dp</dimen>
- <dimen name="progress_indeterminate_horizontal_min_height_watch">17dp</dimen>
</resources>
diff --git a/core/res/res/values-watch/styles_device_defaults.xml b/core/res/res/values-watch/styles_device_defaults.xml
index eeb66e7..fb7dbb0 100644
--- a/core/res/res/values-watch/styles_device_defaults.xml
+++ b/core/res/res/values-watch/styles_device_defaults.xml
@@ -42,8 +42,5 @@
<item name="indeterminateOnly">false</item>
<!-- Use Wear Material3 ring shape as default determinate drawable -->
<item name="progressDrawable">@drawable/progress_ring_watch</item>
- <item name="indeterminateDrawable">@drawable/loader_horizontal_watch</item>
- <item name="android:minWidth">@dimen/loader_horizontal_min_width_watch</item>
- <item name="android:minHeight">@dimen/loader_horizontal_min_height_watch</item>
</style>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c746d3c..46c53eb 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"访问与您的生命体征相关的传感器数据"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"通知"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"显示通知"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"检索窗口内容"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"检测您与之互动的窗口的内容。"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"启用触摸浏览"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"允许该应用修改您的照片收藏。"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"从您的媒体收藏中读取位置信息"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"允许该应用从您的媒体收藏中读取位置信息。"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"使用生物识别"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"使用生物识别或屏幕锁定凭据"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"验证是您本人在操作"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"方向键中心"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"自动点击类型设置面板"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"点击鼠标左键"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"右键点击"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"双击"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"拖动"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"滚动"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"暂停"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"位置"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> 已被放入受限存储分区"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index c6b952c..d013a47 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"存取與你生命體徵相關的感應器資料"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"通知"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"顯示通知"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"擷取視窗內容"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"檢查你使用中的視窗內容。"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"開啟「輕觸探索」功能"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"允許應用程式修改你的相片集。"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"讀取媒體集的位置"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"允許應用程式讀取媒體集的位置。"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"使用生物識別"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"使用生物識別或螢幕鎖定"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"驗證是你本人"</string>
@@ -1409,7 +1449,7 @@
<string name="carrier_app_notification_title" msgid="5815477368072060250">"已插入新的 SIM 卡"</string>
<string name="carrier_app_notification_text" msgid="6567057546341958637">"輕按即可設定"</string>
<string name="time_zone_change_notification_title" msgid="5232503069219193218">"你的時區已變更"</string>
- <string name="time_zone_change_notification_body" msgid="6135793674904665585">"你現在處於 <xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
+ <string name="time_zone_change_notification_body" msgid="6135793674904665585">"目前所在時區為<xliff:g id="TIME_ZONE_DISPLAY_NAME">%1$s</xliff:g> (<xliff:g id="TIME_ZONE_OFFSET">%2$s</xliff:g>)"</string>
<string name="time_picker_dialog_title" msgid="9053376764985220821">"設定時間"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"日期設定"</string>
<string name="date_time_set" msgid="4603445265164486816">"設定"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"十字鍵中心鍵"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"自動點擊類型設定面板"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"按一下左鍵"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"按一下右鍵"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"連按兩下"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"拖曳"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"捲動"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"暫停"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"位置"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> 已納入受限制的儲存區"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ca0402a..f1c9dcd 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"存取與你生命徵象相關的感應器資料"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"通知"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"顯示通知"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"擷取視窗內容"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"檢查你存取的視窗內容。"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"啟用輕觸探索功能"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"允許應用程式修改你的相片收藏。"</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"讀取你的媒體收藏的位置資訊"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"允許應用程式讀取你的媒體收藏的位置資訊。"</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"使用生物辨識功能"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"使用生物辨識或螢幕鎖定功能"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"驗證你的身分"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Dpad 置中"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"自動點選類型設定面板"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"按滑鼠左鍵"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"按一下滑鼠右鍵"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"按兩下"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"拖曳"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"捲動"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"暫停"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"位置"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"已將「<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>」移入受限制的值區"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 96d6b57..5732cec 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -353,6 +353,14 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"finyelela idatha yesizweli mayelana nezimpawu zakho ezibalulekile"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Izaziso"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"bonisa izaziso"</string>
+ <!-- no translation found for permgrouplab_xr_tracking (7418994009794287471) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking (6777198859446500821) -->
+ <skip />
+ <!-- no translation found for permgrouplab_xr_tracking_sensitive (1194833982988144536) -->
+ <skip />
+ <!-- no translation found for permgroupdesc_xr_tracking_sensitive (9178027369004805829) -->
+ <skip />
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Thola okuqukethwe kwewindi"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Hlola okuqukethwe kwewindi ohlanganyela nalo."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Vula ukuhlola ngokuthinta"</string>
@@ -648,6 +656,38 @@
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Ivumela uhlelo lwakho lokusebenza ukuthi lilungise iqoqo lakho lesithombe."</string>
<string name="permlab_mediaLocation" msgid="7368098373378598066">"funda izindawo kusukela kuqoqo lakho lemidiya"</string>
<string name="permdesc_mediaLocation" msgid="597912899423578138">"Ivumela uhlelo lokusebenza ukuthi lifunde izindawo kusukela kuqoqo lakho lemidiya."</string>
+ <!-- no translation found for permlab_eye_tracking_coarse (7989596289790269059) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_coarse (870510233930553355) -->
+ <skip />
+ <!-- no translation found for permlab_eye_tracking_fine (6914457357027049512) -->
+ <skip />
+ <!-- no translation found for permdesc_eye_tracking_fine (5788889152304524730) -->
+ <skip />
+ <!-- no translation found for permlab_face_tracking (2272048395128283324) -->
+ <skip />
+ <!-- no translation found for permdesc_face_tracking (2622783922311211866) -->
+ <skip />
+ <!-- no translation found for permlab_hand_tracking (6478233866595566940) -->
+ <skip />
+ <!-- no translation found for permdesc_hand_tracking (8639715900104966456) -->
+ <skip />
+ <!-- no translation found for permlab_head_tracking (1309731456372087270) -->
+ <skip />
+ <!-- no translation found for permdesc_head_tracking (231597390513699188) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_coarse (6518646430502858641) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_coarse (4508880777646198656) -->
+ <skip />
+ <!-- no translation found for permlab_scene_understanding_fine (409126403264393251) -->
+ <skip />
+ <!-- no translation found for permdesc_scene_understanding_fine (6223368011593524179) -->
+ <skip />
+ <!-- no translation found for permlab_xr_tracking_in_background (7117098718465619023) -->
+ <skip />
+ <!-- no translation found for permdesc_xr_tracking_in_background (939504041387836853) -->
+ <skip />
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Sebenzisa i-biometrics"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Sebenzisa i-biometrics noma ukukhiya isikrini"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Qinisekisa ukuthi nguwe"</string>
@@ -2247,14 +2287,10 @@
<string name="accessibility_system_action_dpad_center_label" msgid="8149791419358224893">"Isikhungo se-Dpad"</string>
<string name="accessibility_autoclick_type_settings_panel_title" msgid="7354373370578758696">"Iphaneli yamasethingi ohlobo lokuchofoza ngokuzenzekelayo"</string>
<string name="accessibility_autoclick_left_click" msgid="2301793352260551080">"Chofoza kwesokunxele"</string>
- <!-- no translation found for accessibility_autoclick_right_click (4353495816526181293) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_double_click (2103826849116176478) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_drag (1499559489796843224) -->
- <skip />
- <!-- no translation found for accessibility_autoclick_scroll (3499385943728726933) -->
- <skip />
+ <string name="accessibility_autoclick_right_click" msgid="4353495816526181293">"Chofoza ngakwesokudla"</string>
+ <string name="accessibility_autoclick_double_click" msgid="2103826849116176478">"Chofoza kabili"</string>
+ <string name="accessibility_autoclick_drag" msgid="1499559489796843224">"Hudula"</string>
+ <string name="accessibility_autoclick_scroll" msgid="3499385943728726933">"Skrola"</string>
<string name="accessibility_autoclick_pause" msgid="3272200156172573568">"Misa"</string>
<string name="accessibility_autoclick_position" msgid="2933660969907663545">"Indawo"</string>
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"I-<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ifakwe kubhakede LOKUKHAWULELWE"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6611178..d2c993ae 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6934,6 +6934,8 @@
<enum name="line" value="2" />
<!-- Ring shape. -->
<enum name="ring" value="3" />
+ <!-- ARC shape. -->
+ <enum name="arc" value="4"/>
</attr>
<!-- Inner radius of the ring expressed as a ratio of the ring's width. For instance,
if innerRadiusRatio=9, then the inner radius equals the ring's width divided by 9.
@@ -6966,6 +6968,12 @@
<attr name="opticalInsetRight" />
<!-- Bottom optical inset. -->
<attr name="opticalInsetBottom" />
+ <!-- Attributes that customize the stroke line cap. @hide -->
+ <attr name="strokeCap" format="enum">
+ <enum name="butt" value="0"/>
+ <enum name="round" value="1"/>
+ <enum name="square" value="2"/>
+ </attr>
</declare-styleable>
<!-- Used to specify the size of the shape for GradientDrawable. -->
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index f2ec56c..59ed25a 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -64,6 +64,13 @@
<integer name="auto_data_switch_performance_stability_time_threshold_millis">120000</integer>
<java-symbol type="integer" name="auto_data_switch_performance_stability_time_threshold_millis" />
+ <!-- Define the bar for switching data back to the default SIM when both SIMs are out of service
+ in milliseconds. A value of 0 means an immediate switch, otherwise for a negative value,
+ the threshold defined by auto_data_switch_availability_stability_time_threshold_millis
+ will be used instead. -->
+ <integer name="auto_data_switch_availability_switchback_stability_time_threshold_millis">150000</integer>
+ <java-symbol type="integer" name="auto_data_switch_availability_switchback_stability_time_threshold_millis" />
+
<!-- Define the maximum retry times when a validation for switching failed.-->
<integer name="auto_data_switch_validation_max_retry">7</integer>
<java-symbol type="integer" name="auto_data_switch_validation_max_retry" />
diff --git a/core/res/res/values/dimens_watch.xml b/core/res/res/values/dimens_watch.xml
index 1984591..7462b73 100644
--- a/core/res/res/values/dimens_watch.xml
+++ b/core/res/res/values/dimens_watch.xml
@@ -52,7 +52,7 @@
<dimen name="primary_content_alpha_device_default">0.38</dimen>
<!-- values for wear material3 progress bar(progress indicator) -->
- <item name="progressbar_inner_radius_ratio" format="float" type="dimen">2.12</item>
+ <item name="progressbar_inner_radius_ratio" format="float" type="dimen">2</item>
<dimen name="progressbar_thickness">8dp</dimen>
<dimen name="progressbar_elevation">0.1dp</dimen>
@@ -61,8 +61,4 @@
<dimen name="disabled_alpha_wear_material3">0.12</dimen>
<!-- Alpha transparency applied to elements which are considered primary (e.g. primary text) -->
<dimen name="primary_content_alpha_wear_material3">0.38</dimen>
-
- <!-- watch's indeterminate progress bar dimens -->
- <dimen name="loader_horizontal_min_width">68dp</dimen>
- <dimen name="loader_horizontal_min_height">13dp</dimen>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06861b11..b013ffd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1743,7 +1743,6 @@
<java-symbol type="id" name="media_route_list" />
<java-symbol type="id" name="media_route_volume_layout" />
<java-symbol type="id" name="media_route_volume_slider" />
- <java-symbol type="id" name="media_route_control_frame" />
<java-symbol type="id" name="media_route_extended_settings_button" />
<java-symbol type="id" name="media_route_progress_bar" />
<java-symbol type="string" name="media_route_chooser_title" />
@@ -3265,6 +3264,7 @@
<java-symbol type="dimen" name="notification_content_margin" />
<java-symbol type="dimen" name="notification_2025_margin" />
<java-symbol type="dimen" name="notification_2025_content_margin_top" />
+ <java-symbol type="dimen" name="notification_2025_content_margin_start" />
<java-symbol type="dimen" name="notification_2025_expand_button_horizontal_icon_padding" />
<java-symbol type="dimen" name="notification_2025_expand_button_reduced_end_padding" />
<java-symbol type="dimen" name="notification_progress_margin_horizontal" />
@@ -4706,7 +4706,8 @@
<java-symbol type="dimen" name="conversation_icon_container_top_padding" />
<java-symbol type="dimen" name="conversation_icon_container_top_padding_small_avatar" />
<java-symbol type="layout" name="notification_template_material_conversation" />
- <java-symbol type="layout" name="notification_2025_template_conversation" />
+ <java-symbol type="layout" name="notification_2025_template_collapsed_conversation" />
+ <java-symbol type="layout" name="notification_2025_template_expanded_conversation" />
<java-symbol type="dimen" name="button_padding_horizontal_material" />
<java-symbol type="dimen" name="button_inset_horizontal_material" />
<java-symbol type="layout" name="conversation_face_pile_layout" />
@@ -5649,6 +5650,8 @@
<java-symbol type="id" name="accessibility_autoclick_pause_button" />
<java-symbol type="id" name="accessibility_autoclick_position_layout" />
<java-symbol type="id" name="accessibility_autoclick_position_button" />
+ <java-symbol type="drawable" name="accessibility_autoclick_pause" />
+ <java-symbol type="drawable" name="accessibility_autoclick_resume" />
<!-- For HapticFeedbackConstants configurability defined at HapticFeedbackCustomization -->
<java-symbol type="string" name="config_hapticFeedbackCustomizationFile" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 4c49ff8..05fb5735 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -249,8 +249,14 @@
android_ravenwood_test {
name: "FrameworksCoreTestsRavenwood",
libs: [
- "android.test.base.stubs.system",
- "android.test.runner.stubs.system",
+ "android.test.base.stubs",
+ "android.test.mock.stubs",
+ "android.test.runner.stubs",
+ "android.view.flags-aconfig-java",
+ "ext",
+ "framework",
+ "framework-res",
+ "org.apache.http.legacy.stubs",
],
static_libs: [
"androidx.annotation_annotation",
@@ -264,6 +270,7 @@
"flag-junit",
"flag-junit",
"perfetto_trace_java_protos",
+ "platform-compat-test-rules",
"platform-test-annotations",
"testng",
],
@@ -278,8 +285,12 @@
"src/android/content/res/*.java",
"src/android/content/res/*.kt",
"src/android/database/CursorWindowTest.java",
+ "src/android/graphics/*.java",
+ "src/android/graphics/*.kt",
"src/android/os/**/*.java",
"src/android/telephony/PinResultTest.java",
+ "src/android/text/**/*.java",
+ "src/android/text/**/*.kt",
"src/android/util/**/*.java",
"src/android/view/DisplayAdjustmentsTests.java",
"src/android/view/DisplayInfoTest.java",
@@ -288,20 +299,21 @@
"src/com/android/internal/os/**/*.java",
"src/com/android/internal/power/EnergyConsumerStatsTest.java",
"src/com/android/internal/ravenwood/**/*.java",
-
- // Pull in R.java from FrameworksCoreTests-resonly, not from FrameworksCoreTests,
- // to avoid having a dependency to FrameworksCoreTests.
- // This way, when updating source files and running this test, we don't need to
- // rebuild the entire FrameworksCoreTests, which would be slow.
"src/com/android/internal/util/**/*.java",
":FrameworksCoreTestDoubles-sources",
":FrameworksCoreTests-aidl",
":FrameworksCoreTests-helpers",
+
+ // Pull in R.java from FrameworksCoreTests-resonly, not from FrameworksCoreTests,
+ // to avoid having a dependency to FrameworksCoreTests.
+ // This way, when updating source files and running this test, we don't need to
+ // rebuild the entire FrameworksCoreTests, which would be slow.
":FrameworksCoreTests-resonly{.aapt.srcjar}",
],
exclude_srcs: [
"src/android/content/res/FontScaleConverterActivityTest.java",
+ "src/android/graphics/GraphicsPerformanceTests.java",
],
resource_apk: "FrameworksCoreTests-resonly",
aidl: {
@@ -313,6 +325,7 @@
"res/xml/power_profile_test_cpu_legacy.xml",
"res/xml/power_profile_test_modem.xml",
],
+ sdk_version: "core_platform",
auto_gen_config: true,
team: "trendy_team_ravenwood",
}
diff --git a/core/tests/coretests/src/android/content/pm/SystemFeaturesCacheTest.java b/core/tests/coretests/src/android/content/pm/SystemFeaturesCacheTest.java
index ce4aa42..8b513cb 100644
--- a/core/tests/coretests/src/android/content/pm/SystemFeaturesCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/SystemFeaturesCacheTest.java
@@ -21,12 +21,16 @@
import static com.google.common.truth.Truth.assertThat;
-import android.os.Parcel;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeTrue;
+
import android.util.ArrayMap;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -36,6 +40,19 @@
private SystemFeaturesCache mCache;
+ private SystemFeaturesCache mOriginalSingletonCache;
+
+ @Before
+ public void setUp() {
+ mOriginalSingletonCache = SystemFeaturesCache.getInstance();
+ }
+
+ @After
+ public void tearDown() {
+ SystemFeaturesCache.clearInstance();
+ SystemFeaturesCache.setInstance(mOriginalSingletonCache);
+ }
+
@Test
public void testNoFeatures() throws Exception {
SystemFeaturesCache cache = new SystemFeaturesCache(new ArrayMap<String, FeatureInfo>());
@@ -84,29 +101,57 @@
}
@Test
- public void testParcel() throws Exception {
+ public void testGetAndSetFeatureVersions() throws Exception {
ArrayMap<String, FeatureInfo> features = new ArrayMap<>();
features.put(FEATURE_WATCH, createFeature(FEATURE_WATCH, 0));
SystemFeaturesCache cache = new SystemFeaturesCache(features);
- Parcel parcel = Parcel.obtain();
- SystemFeaturesCache parceledCache;
- try {
- parcel.writeParcelable(cache, 0);
- parcel.setDataPosition(0);
- parceledCache = parcel.readParcelable(getClass().getClassLoader());
- } finally {
- parcel.recycle();
- }
+ assertThat(cache.getSdkFeatureVersions().length)
+ .isEqualTo(PackageManager.SDK_FEATURE_COUNT);
- assertThat(parceledCache.maybeHasFeature(FEATURE_WATCH, 0))
+ SystemFeaturesCache clonedCache = new SystemFeaturesCache(cache.getSdkFeatureVersions());
+ assertThat(cache.getSdkFeatureVersions()).isEqualTo(clonedCache.getSdkFeatureVersions());
+
+ assertThat(clonedCache.maybeHasFeature(FEATURE_WATCH, 0))
.isEqualTo(cache.maybeHasFeature(FEATURE_WATCH, 0));
- assertThat(parceledCache.maybeHasFeature(FEATURE_PICTURE_IN_PICTURE, 0))
+ assertThat(clonedCache.maybeHasFeature(FEATURE_PICTURE_IN_PICTURE, 0))
.isEqualTo(cache.maybeHasFeature(FEATURE_PICTURE_IN_PICTURE, 0));
- assertThat(parceledCache.maybeHasFeature("custom.feature", 0))
+ assertThat(clonedCache.maybeHasFeature("custom.feature", 0))
.isEqualTo(cache.maybeHasFeature("custom.feature", 0));
}
+ @Test
+ public void testInvalidFeatureVersions() throws Exception {
+ // Raw feature version arrays must match the predefined SDK feature count.
+ int[] invalidFeatureVersions = new int[PackageManager.SDK_FEATURE_COUNT - 1];
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new SystemFeaturesCache(invalidFeatureVersions));
+ }
+
+ @Test
+ public void testSingleton() throws Exception {
+ ArrayMap<String, FeatureInfo> features = new ArrayMap<>();
+ features.put(FEATURE_WATCH, createFeature(FEATURE_WATCH, 0));
+ SystemFeaturesCache cache = new SystemFeaturesCache(features);
+
+ SystemFeaturesCache.clearInstance();
+ assertThrows(IllegalStateException.class, () -> SystemFeaturesCache.getInstance());
+
+ SystemFeaturesCache.setInstance(cache);
+ assertThat(SystemFeaturesCache.getInstance()).isEqualTo(cache);
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> SystemFeaturesCache.setInstance(new SystemFeaturesCache(features)));
+ }
+
+ @Test
+ public void testSingletonAutomaticallySetWithFeatureEnabled() {
+ assumeTrue(android.content.pm.Flags.cacheSdkSystemFeatures());
+ assertThat(SystemFeaturesCache.getInstance()).isNotNull();
+ }
+
private static FeatureInfo createFeature(String name, int version) {
FeatureInfo fi = new FeatureInfo();
fi.name = name;
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt
index 0e5d926..2c61442 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt
@@ -17,10 +17,8 @@
package android.content.res
import android.platform.test.annotations.Presubmit
-import android.platform.test.ravenwood.RavenwoodRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertWithMessage
-import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -28,9 +26,6 @@
@RunWith(AndroidJUnit4::class)
class FontScaleConverterTest {
- @get:Rule
- val ravenwoodRule: RavenwoodRule = RavenwoodRule.Builder().build()
-
@Test
fun straightInterpolation() {
val table = createTable(8f to 8f, 10f to 10f, 20f to 20f)
diff --git a/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
index 84bdbe0..263307e 100644
--- a/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
@@ -20,7 +20,9 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.DisabledOnRavenwood;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -37,6 +39,7 @@
// tests that we can decode bitmaps from MemoryFiles
@SmallTest
@Test
+ @DisabledOnRavenwood(blockedBy = MemoryFile.class)
public void testBitmapParcelFileDescriptor() throws Exception {
Bitmap bitmap1 = Bitmap.createBitmap(
new int[] { Color.BLUE }, 1, 1, Bitmap.Config.RGB_565);
diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
index 0126d36..61c3d78 100644
--- a/core/tests/coretests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.fail;
import android.hardware.HardwareBuffer;
+import android.platform.test.annotations.DisabledOnRavenwood;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -252,6 +253,7 @@
| GraphicBuffer.USAGE_SW_WRITE_OFTEN;
@Test
+ @DisabledOnRavenwood(blockedBy = HardwareBuffer.class)
public void testWrapHardwareBufferWithSrgbColorSpace() {
GraphicBuffer buffer = GraphicBuffer.create(10, 10, PixelFormat.RGBA_8888, GRAPHICS_USAGE);
Canvas canvas = buffer.lockCanvas();
@@ -265,6 +267,7 @@
}
@Test
+ @DisabledOnRavenwood(blockedBy = HardwareBuffer.class)
public void testWrapHardwareBufferWithDisplayP3ColorSpace() {
GraphicBuffer buffer = GraphicBuffer.create(10, 10, PixelFormat.RGBA_8888, GRAPHICS_USAGE);
Canvas canvas = buffer.lockCanvas();
diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java
index 56760d7..deb5157 100644
--- a/core/tests/coretests/src/android/graphics/PaintTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -97,6 +98,7 @@
@SmallTest
@Test
+ @DisabledOnRavenwood(bug = 391381043)
public void testHintingWidth() {
final Typeface fontTypeface = Typeface.createFromAsset(
InstrumentationRegistry.getInstrumentation().getContext().getAssets(), FONT_PATH);
@@ -143,6 +145,7 @@
}
@Test
+ @DisabledOnRavenwood(bug = 391381043)
public void testHasGlyph_variationSelectors() {
final Typeface fontTypeface = Typeface.createFromAsset(
InstrumentationRegistry.getInstrumentation().getContext().getAssets(),
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 2b6eda8f..dc3376e 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -35,9 +35,9 @@
import android.text.FontConfig;
import android.util.ArrayMap;
-import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.text.flags.Flags;
@@ -63,9 +63,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TypefaceSystemFallbackTest {
- private static final String SYSTEM_FONT_DIR = "/system/fonts/";
- private static final String SYSTEM_FONTS_XML = "/system/etc/fonts.xml";
-
private static final String[] TEST_FONT_FILES = {
"a3em.ttf", // Supports "a","b","c". The width of "a" is 3em, others are 1em.
"b3em.ttf", // Supports "a","b","c". The width of "b" is 3em, others are 1em.
@@ -118,8 +115,6 @@
@Before
public void setUp() {
- final AssetManager am =
- InstrumentationRegistry.getInstrumentation().getContext().getAssets();
for (final String fontFile : TEST_FONT_FILES) {
final String sourceInAsset = "fonts/" + fontFile;
copyAssetToFile(sourceInAsset, new File(TEST_FONT_DIR, fontFile));
@@ -216,7 +211,8 @@
FontConfig fontConfig;
try {
fontConfig = FontListParser.parse(
- SYSTEM_FONTS_XML, SYSTEM_FONT_DIR, null, TEST_OEM_DIR, null, 0, 0);
+ SystemFonts.LEGACY_FONTS_XML, SystemFonts.SYSTEM_FONT_DIR,
+ null, TEST_OEM_DIR, null, 0, 0);
} catch (IOException | XmlPullParserException e) {
throw new RuntimeException(e);
}
diff --git a/core/tests/coretests/src/android/graphics/TypefaceTest.java b/core/tests/coretests/src/android/graphics/TypefaceTest.java
index 80efa51..0c8b5ab 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceTest.java
@@ -26,6 +26,7 @@
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.SystemFonts;
import android.os.SharedMemory;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.text.FontConfig;
import android.util.ArrayMap;
@@ -196,6 +197,7 @@
@SmallTest
@Test
+ @DisabledOnRavenwood(blockedBy = SharedMemory.class)
public void testSerialize() throws Exception {
FontConfig fontConfig = SystemFonts.getSystemPreinstalledFontConfig();
Map<String, FontFamily[]> fallbackMap = SystemFonts.buildSystemFallback(fontConfig);
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
index 9383807..8ef105f 100644
--- a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
+++ b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
@@ -56,6 +56,7 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -116,7 +117,8 @@
@Test
public void testDisplayListenerIsCalled_WhenDisplayEventOccurs() throws RemoteException {
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
- ALL_DISPLAY_EVENTS, /* packageName= */ null);
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ true);
Mockito.verify(mDisplayManager)
.registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
IDisplayManagerCallback callback = mCallbackCaptor.getValue();
@@ -151,7 +153,7 @@
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE
| INTERNAL_EVENT_FLAG_DISPLAY_STATE,
- null);
+ null, /* isEventFilterExplicit */ true);
Mockito.verify(mDisplayManager)
.registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
IDisplayManagerCallback callback = mCallbackCaptor.getValue();
@@ -172,11 +174,80 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_DELAY_IMPLICIT_RR_REGISTRATION_UNTIL_RR_ACCESSED)
+ public void test_refreshRateRegistration_implicitRRCallbacksEnabled()
+ throws RemoteException {
+ // Subscription without supplied events doesn't subscribe to RR events
+ mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ false);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), eq(ALL_DISPLAY_EVENTS));
+
+ // After registering to refresh rate changes, subscription without supplied events subscribe
+ // to RR events
+ mDisplayManagerGlobal.registerForRefreshRateChanges();
+ mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ false);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), eq(ALL_DISPLAY_EVENTS
+ | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE));
+
+ // Assert all the existing listeners are also subscribed to RR events
+ CopyOnWriteArrayList<DisplayManagerGlobal.DisplayListenerDelegate> delegates =
+ mDisplayManagerGlobal.getDisplayListeners();
+ for (DisplayManagerGlobal.DisplayListenerDelegate delegate: delegates) {
+ assertEquals(ALL_DISPLAY_EVENTS | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
+ delegate.mInternalEventFlagsMask);
+ }
+
+ // Subscription to RR when events are supplied doesn't happen
+ mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ true);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), eq(ALL_DISPLAY_EVENTS));
+
+ // Assert one listeners are not subscribed to RR events
+ delegates = mDisplayManagerGlobal.getDisplayListeners();
+ int subscribedListenersCount = 0;
+ int nonSubscribedListenersCount = 0;
+ for (DisplayManagerGlobal.DisplayListenerDelegate delegate: delegates) {
+
+ if (delegate.isEventFilterExplicit()) {
+ assertEquals(ALL_DISPLAY_EVENTS, delegate.mInternalEventFlagsMask);
+ nonSubscribedListenersCount++;
+ } else {
+ assertEquals(ALL_DISPLAY_EVENTS | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
+ delegate.mInternalEventFlagsMask);
+ subscribedListenersCount++;
+ }
+ }
+
+ assertEquals(2, subscribedListenersCount);
+ assertEquals(1, nonSubscribedListenersCount);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_DELAY_IMPLICIT_RR_REGISTRATION_UNTIL_RR_ACCESSED)
+ public void test_refreshRateRegistration_implicitRRCallbacksDisabled()
+ throws RemoteException {
+ mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ false);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), eq(ALL_DISPLAY_EVENTS
+ | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE));
+ }
+
+ @Test
public void testDisplayListenerIsNotCalled_WhenClientIsNotSubscribed() throws RemoteException {
// First we subscribe to all events in order to test that the subsequent calls to
// registerDisplayListener will update the event mask.
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
- ALL_DISPLAY_EVENTS, /* packageName= */ null);
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ true);
Mockito.verify(mDisplayManager)
.registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
IDisplayManagerCallback callback = mCallbackCaptor.getValue();
@@ -184,21 +255,24 @@
int displayId = 1;
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
ALL_DISPLAY_EVENTS
- & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED, null);
+ & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED, null,
+ /* isEventFilterExplicit */ true);
callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
waitForHandler();
Mockito.verifyZeroInteractions(mDisplayListener);
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
ALL_DISPLAY_EVENTS
- & ~DISPLAY_CHANGE_EVENTS, null);
+ & ~DISPLAY_CHANGE_EVENTS, null,
+ /* isEventFilterExplicit */ true);
callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED);
waitForHandler();
Mockito.verifyZeroInteractions(mDisplayListener);
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
ALL_DISPLAY_EVENTS
- & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED, null);
+ & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED, null,
+ /* isEventFilterExplicit */ true);
callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
waitForHandler();
Mockito.verifyZeroInteractions(mDisplayListener);
@@ -218,11 +292,34 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_DELAY_IMPLICIT_RR_REGISTRATION_UNTIL_RR_ACCESSED)
+ public void test_registerNativeRefreshRateCallbacks_enablesRRImplicitRegistrations()
+ throws RemoteException {
+ // Registering the display listener without supplied events doesn't subscribe to RR events
+ mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ false);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), eq(ALL_DISPLAY_EVENTS));
+
+ // Native subscription for refresh rates is done
+ mDisplayManagerGlobal.registerNativeChoreographerForRefreshRateCallbacks();
+
+ // Registering the display listener without supplied events subscribe to RR events
+ mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
+ ALL_DISPLAY_EVENTS, /* packageName= */ null,
+ /* isEventFilterExplicit */ false);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), eq(ALL_DISPLAY_EVENTS
+ | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE));
+ }
+
+ @Test
public void testDisplayManagerGlobalRegistersWithDisplayManager_WhenThereAreListeners()
throws RemoteException {
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
- null);
+ null, /* isEventFilterExplicit */ true);
InOrder inOrder = Mockito.inOrder(mDisplayManager);
inOrder.verify(mDisplayManager)
@@ -260,9 +357,10 @@
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
| DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
- null /* packageName */);
+ null /* packageName */, /* isEventFilterExplicit */ true);
mDisplayManagerGlobal.registerDisplayListener(mDisplayListener2, mHandler,
- DISPLAY_CHANGE_EVENTS, null /* packageName */);
+ DISPLAY_CHANGE_EVENTS, null /* packageName */,
+ /* isEventFilterExplicit */ true);
mDisplayManagerGlobal.handleDisplayChangeFromWindowManager(321);
waitForHandler();
diff --git a/core/tests/coretests/src/android/os/BundleMergerTest.java b/core/tests/coretests/src/android/os/BundleMergerTest.java
index 43ed821..5379993 100644
--- a/core/tests/coretests/src/android/os/BundleMergerTest.java
+++ b/core/tests/coretests/src/android/os/BundleMergerTest.java
@@ -18,6 +18,7 @@
import static android.os.BundleMerger.STRATEGY_ARRAY_APPEND;
import static android.os.BundleMerger.STRATEGY_ARRAY_LIST_APPEND;
+import static android.os.BundleMerger.STRATEGY_ARRAY_UNION;
import static android.os.BundleMerger.STRATEGY_BOOLEAN_AND;
import static android.os.BundleMerger.STRATEGY_BOOLEAN_OR;
import static android.os.BundleMerger.STRATEGY_COMPARABLE_MAX;
@@ -28,6 +29,7 @@
import static android.os.BundleMerger.STRATEGY_NUMBER_INCREMENT_FIRST;
import static android.os.BundleMerger.STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD;
import static android.os.BundleMerger.STRATEGY_REJECT;
+import static android.os.BundleMerger.STRATEGY_STRING_APPEND;
import static android.os.BundleMerger.merge;
import static org.junit.Assert.assertArrayEquals;
@@ -204,6 +206,33 @@
}
@Test
+ public void testStrategyArrayUnion() throws Exception {
+ assertArrayEquals(new int[] {},
+ (int[]) merge(STRATEGY_ARRAY_UNION, new int[] {}, new int[] {}));
+ assertArrayEquals(new int[] {10},
+ (int[]) merge(STRATEGY_ARRAY_UNION, new int[] {10}, new int[] {}));
+ assertArrayEquals(new int[] {20},
+ (int[]) merge(STRATEGY_ARRAY_UNION, new int[] {}, new int[] {20}));
+ assertArrayEquals(new int[] {10, 20},
+ (int[]) merge(STRATEGY_ARRAY_UNION, new int[] {10}, new int[] {20}));
+ assertArrayEquals(new int[] {10, 20, 30, 40},
+ (int[]) merge(STRATEGY_ARRAY_UNION, new int[] {10, 30}, new int[] {20, 40}));
+ assertArrayEquals(new int[] {10, 20, 30},
+ (int[]) merge(STRATEGY_ARRAY_UNION, new int[] {10, 30}, new int[] {10, 20}));
+ assertArrayEquals(new int[] {10, 20},
+ (int[]) merge(STRATEGY_ARRAY_UNION, new int[] {10, 20}, new int[] {20}));
+ assertArrayEquals(new String[] {"a", "b"},
+ (String[]) merge(STRATEGY_ARRAY_UNION, new String[] {"a"}, new String[] {"b"}));
+ assertArrayEquals(new String[] {"a", "b", "c"},
+ (String[]) merge(STRATEGY_ARRAY_UNION, new String[] {"a", "b"},
+ new String[] {"b", "c"}));
+
+ assertThrows(Exception.class, () -> {
+ merge(STRATEGY_ARRAY_UNION, 10, 20);
+ });
+ }
+
+ @Test
public void testStrategyArrayListAppend() throws Exception {
assertEquals(arrayListOf(),
merge(STRATEGY_ARRAY_LIST_APPEND, arrayListOf(), arrayListOf()));
@@ -224,6 +253,18 @@
}
@Test
+ public void testStrategyStringAppend() throws Exception {
+ assertEquals("ab", merge(STRATEGY_STRING_APPEND, "a", "b"));
+ assertEquals("abc", merge(STRATEGY_STRING_APPEND, "a", "bc"));
+ assertEquals("abc", merge(STRATEGY_STRING_APPEND, "ab", "c"));
+ assertEquals("a,b,c,", merge(STRATEGY_STRING_APPEND, "a,", "b,c,"));
+
+ assertThrows(Exception.class, () -> {
+ merge(STRATEGY_STRING_APPEND, 10, 20);
+ });
+ }
+
+ @Test
public void testSetDefaultMergeStrategy() throws Exception {
final BundleMerger merger = new BundleMerger();
merger.setDefaultMergeStrategy(STRATEGY_FIRST);
diff --git a/core/tests/coretests/src/android/os/PerfettoTraceTest.java b/core/tests/coretests/src/android/os/PerfettoTraceTest.java
index c5c2554..6915015 100644
--- a/core/tests/coretests/src/android/os/PerfettoTraceTest.java
+++ b/core/tests/coretests/src/android/os/PerfettoTraceTest.java
@@ -77,6 +77,8 @@
private static final String TAG = "PerfettoTraceTest";
private static final String FOO = "foo";
private static final String BAR = "bar";
+ private static final String TEXT_ABOVE_4K_SIZE =
+ new String(new char[8192]).replace('\0', 'a');
private static final Category FOO_CATEGORY = new Category(FOO);
private static final int MESSAGE = 1234567;
@@ -106,8 +108,8 @@
PerfettoTrace.Session session = new PerfettoTrace.Session(true, traceConfig.toByteArray());
PerfettoTrace.instant(FOO_CATEGORY, "event")
- .addFlow(2)
- .addTerminatingFlow(3)
+ .setFlow(2)
+ .setTerminatingFlow(3)
.addArg("long_val", 10000000000L)
.addArg("bool_val", true)
.addArg("double_val", 3.14)
@@ -155,41 +157,6 @@
@Test
@RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
- public void testDebugAnnotationsWithLambda() throws Exception {
- TraceConfig traceConfig = getTraceConfig(FOO);
-
- PerfettoTrace.Session session = new PerfettoTrace.Session(true, traceConfig.toByteArray());
-
- PerfettoTrace.instant(FOO_CATEGORY, "event").addArg("long_val", 123L).emit();
-
- byte[] traceBytes = session.close();
-
- Trace trace = Trace.parseFrom(traceBytes);
-
- boolean hasTrackEvent = false;
- boolean hasDebugAnnotations = false;
- for (TracePacket packet: trace.getPacketList()) {
- TrackEvent event;
- if (packet.hasTrackEvent()) {
- hasTrackEvent = true;
- event = packet.getTrackEvent();
-
- if (TrackEvent.Type.TYPE_INSTANT.equals(event.getType())
- && event.getDebugAnnotationsCount() == 1) {
- hasDebugAnnotations = true;
-
- List<DebugAnnotation> annotations = event.getDebugAnnotationsList();
- assertThat(annotations.get(0).getIntValue()).isEqualTo(123L);
- }
- }
- }
-
- assertThat(hasTrackEvent).isTrue();
- assertThat(hasDebugAnnotations).isTrue();
- }
-
- @Test
- @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
public void testNamedTrack() throws Exception {
TraceConfig traceConfig = getTraceConfig(FOO);
@@ -440,7 +407,6 @@
boolean hasTrackEvent = false;
boolean hasSourceLocation = false;
-
for (TracePacket packet: trace.getPacketList()) {
TrackEvent event;
if (packet.hasTrackEvent()) {
@@ -467,6 +433,53 @@
@Test
@RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+ public void testProtoWithSlowPath() throws Exception {
+ TraceConfig traceConfig = getTraceConfig(FOO);
+
+ PerfettoTrace.Session session = new PerfettoTrace.Session(true, traceConfig.toByteArray());
+
+ PerfettoTrace.instant(FOO_CATEGORY, "event_proto")
+ .beginProto()
+ .beginNested(33L)
+ .addField(4L, 2L)
+ .addField(3, TEXT_ABOVE_4K_SIZE)
+ .endNested()
+ .addField(2001, "AIDL::IActivityManager")
+ .endProto()
+ .emit();
+
+ byte[] traceBytes = session.close();
+
+ Trace trace = Trace.parseFrom(traceBytes);
+
+ boolean hasTrackEvent = false;
+ boolean hasSourceLocation = false;
+ for (TracePacket packet: trace.getPacketList()) {
+ TrackEvent event;
+ if (packet.hasTrackEvent()) {
+ hasTrackEvent = true;
+ event = packet.getTrackEvent();
+
+ if (TrackEvent.Type.TYPE_INSTANT.equals(event.getType())
+ && event.hasSourceLocation()) {
+ SourceLocation loc = event.getSourceLocation();
+ if (TEXT_ABOVE_4K_SIZE.equals(loc.getFunctionName())
+ && loc.getLineNumber() == 2) {
+ hasSourceLocation = true;
+ }
+ }
+ }
+
+ collectInternedData(packet);
+ }
+
+ assertThat(hasTrackEvent).isTrue();
+ assertThat(hasSourceLocation).isTrue();
+ assertThat(mCategoryNames).contains(FOO);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
public void testProtoNested() throws Exception {
TraceConfig traceConfig = getTraceConfig(FOO);
diff --git a/core/tests/coretests/src/android/text/AndroidCharacterTest.java b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
index 1c5986a..819a5fb 100644
--- a/core/tests/coretests/src/android/text/AndroidCharacterTest.java
+++ b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertArrayEquals;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -26,6 +27,7 @@
@Presubmit
@SmallTest
+@DisabledOnRavenwood(reason = "No need to make j.l.Character match behavior of AndroidCharacter")
public class AndroidCharacterTest {
@Test
diff --git a/core/tests/coretests/src/android/text/SpanColorsTest.java b/core/tests/coretests/src/android/text/SpanColorsTest.java
index d2cb8c1..4cdbd08 100644
--- a/core/tests/coretests/src/android/text/SpanColorsTest.java
+++ b/core/tests/coretests/src/android/text/SpanColorsTest.java
@@ -20,6 +20,7 @@
import android.graphics.Color;
import android.graphics.drawable.ShapeDrawable;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
@@ -35,6 +36,7 @@
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood(blockedBy = ShapeDrawable.class)
public class SpanColorsTest {
private final TextPaint mWorkPaint = new TextPaint();
private SpanColors mSpanColors;
diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java
index a3e6a78..710d1e2 100644
--- a/core/tests/coretests/src/android/text/SpannableTest.java
+++ b/core/tests/coretests/src/android/text/SpannableTest.java
@@ -16,10 +16,10 @@
package android.text;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import android.platform.test.annotations.Presubmit;
-import android.test.MoreAsserts;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -50,13 +50,13 @@
// but other spans are not, unless the query region is empty, in
// in which case any abutting spans are returned.
spans = spannable.getSpans(0, 1, Object.class);
- MoreAsserts.assertEquals(new Object[]{emptySpan}, spans);
+ assertArrayEquals(new Object[]{emptySpan}, spans);
spans = spannable.getSpans(0, 2, Object.class);
- MoreAsserts.assertEquals(new Object[]{emptySpan, unemptySpan}, spans);
+ assertArrayEquals(new Object[]{emptySpan, unemptySpan}, spans);
spans = spannable.getSpans(1, 2, Object.class);
- MoreAsserts.assertEquals(new Object[]{emptySpan, unemptySpan}, spans);
+ assertArrayEquals(new Object[]{emptySpan, unemptySpan}, spans);
spans = spannable.getSpans(2, 2, Object.class);
- MoreAsserts.assertEquals(new Object[]{unemptySpan}, spans);
+ assertArrayEquals(new Object[]{unemptySpan}, spans);
}
@Test
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index 3541900..55f38b2 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -25,6 +25,7 @@
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.os.LocaleList;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import android.text.Layout.Alignment;
import android.text.method.EditorState;
@@ -726,6 +727,7 @@
}
@Test
+ @DisabledOnRavenwood(bug = 391342883)
public void testLocaleSpanAffectsHyphenation() {
TextPaint paint = new TextPaint();
paint.setTextLocale(Locale.US);
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index f552265..e38c880 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -18,6 +18,7 @@
import static android.text.TextUtils.formatSimple;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -28,7 +29,6 @@
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
-import android.test.MoreAsserts;
import android.text.style.StyleSpan;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
@@ -237,7 +237,7 @@
for (String s : splitter) {
strings.add(s);
}
- MoreAsserts.assertEquals(expectedStrings, strings.toArray(new String[]{}));
+ assertArrayEquals(expectedStrings, strings.toArray(new String[]{}));
}
@Test
diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java
index 59af6dd..c16393c 100644
--- a/core/tests/coretests/src/android/text/format/DateFormatTest.java
+++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java
@@ -74,8 +74,9 @@
DateFormatSymbols dfs = DateFormat.getIcuDateFormatSymbols(Locale.US);
assertEquals("AM", dfs.getAmPmStrings()[0]);
assertEquals("PM", dfs.getAmPmStrings()[1]);
- assertEquals("a", dfs.getAmpmNarrowStrings()[0]);
- assertEquals("p", dfs.getAmpmNarrowStrings()[1]);
+ // getAmpmNarrowStrings() is a @CorePlatformApi that we should stop using in framework
+ // assertEquals("a", dfs.getAmpmNarrowStrings()[0]);
+ // assertEquals("p", dfs.getAmpmNarrowStrings()[1]);
}
@Test
diff --git a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java
index a07d399..e542734 100644
--- a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java
+++ b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java
@@ -40,6 +40,7 @@
import android.icu.util.Calendar;
import android.icu.util.TimeZone;
import android.icu.util.ULocale;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -686,6 +687,7 @@
}
@Test
+ @DisabledOnRavenwood(bug = 391381043)
public void testIsLibcoreVFlagEnabled() {
// This flag has been fully ramped. It should never be false.
assertTrue(DateIntervalFormat.isLibcoreVFlagEnabled());
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index 47be893..a853d4a 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -21,6 +21,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.LocaleList;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -116,6 +117,7 @@
}
@Test
+ @DisabledOnRavenwood(reason = "DateFormat.set24HourTimePref is not available on host JVM")
public void testFormatSameDayTime() {
// This test assumes a default DateFormat.is24Hour setting.
DateFormat.set24HourTimePref(null);
diff --git a/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
index c8cb5f3..49f3373 100644
--- a/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -72,6 +73,7 @@
* Compares TimeMigrationUtils.formatSimpleDateTime() with the code it is replacing.
*/
@Test
+ @DisabledOnRavenwood(blockedBy = Time.class)
public void formatMillisAsDateTime_matchesOldBehavior() {
// A selection of interesting locales.
Locale[] locales = new Locale[] {
diff --git a/core/tests/coretests/src/android/text/format/TimeTest.java b/core/tests/coretests/src/android/text/format/TimeTest.java
index 6138ea1..29c5899 100644
--- a/core/tests/coretests/src/android/text/format/TimeTest.java
+++ b/core/tests/coretests/src/android/text/format/TimeTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import android.util.Log;
import android.util.TimeFormatException;
@@ -34,6 +35,7 @@
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood(blockedBy = Time.class)
public class TimeTest {
@Test
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index a7ff244..646e8f9 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -16,6 +16,7 @@
package android.text.method;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import android.text.InputType;
import android.util.KeyUtils;
@@ -41,6 +42,7 @@
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood(blockedBy = EditText.class)
public class BackspaceTest {
private EditText mTextView;
diff --git a/core/tests/coretests/src/android/text/method/EditorState.java b/core/tests/coretests/src/android/text/method/EditorState.java
index 4eff7a4..633fa11 100644
--- a/core/tests/coretests/src/android/text/method/EditorState.java
+++ b/core/tests/coretests/src/android/text/method/EditorState.java
@@ -16,7 +16,7 @@
package android.text.method;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -181,4 +181,3 @@
Assert.assertEquals(expected.mSelectionEnd, mSelectionEnd);
}
}
-
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 1e4024d..8044fd7 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -16,6 +16,7 @@
package android.text.method;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import android.text.InputType;
import android.util.KeyUtils;
@@ -40,6 +41,7 @@
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood(blockedBy = EditText.class)
public class ForwardDeleteTest {
private EditText mTextView;
diff --git a/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
index e2c1902..37ad204 100644
--- a/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
+++ b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
@@ -44,6 +45,7 @@
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood(blockedBy = View.class)
public class InsertModeTransformationMethodTest {
private static View sView;
private static final String TEXT = "abc def";
diff --git a/core/tests/coretests/src/android/text/util/LinkifyTest.java b/core/tests/coretests/src/android/text/util/LinkifyTest.java
index 52f3b2e..98bdb0b 100644
--- a/core/tests/coretests/src/android/text/util/LinkifyTest.java
+++ b/core/tests/coretests/src/android/text/util/LinkifyTest.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.os.LocaleList;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
@@ -46,6 +47,7 @@
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood(blockedBy = Linkify.class)
public class LinkifyTest {
private static final LocaleList LOCALE_LIST_US = new LocaleList(Locale.US);
diff --git a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
index d91541f..d6426b0 100644
--- a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
+++ b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
@@ -25,6 +25,7 @@
import android.app.Service;
import android.app.UiAutomation;
import android.graphics.Rect;
+import android.os.Process;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityEvent;
@@ -32,6 +33,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityTestActivity;
import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.accessibility.IWindowSurfaceInfoCallback;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -47,6 +49,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import java.util.List;
import java.util.concurrent.TimeoutException;
@@ -136,6 +139,20 @@
}
}
+ @Test
+ public void getWindowSurfaceInfo_shouldCallCallbackWithWindowSurfaceDataFromVri()
+ throws Exception {
+ final ViewRootImpl vri = mButton.getRootView().getViewRootImpl();
+ IWindowSurfaceInfoCallback callback = Mockito.mock(IWindowSurfaceInfoCallback.class);
+
+ sInstrumentation.runOnMainSync(() ->
+ mAccessibilityInteractionController.getWindowSurfaceInfoClientThread(callback));
+ sInstrumentation.waitForIdleSync();
+
+ Mockito.verify(callback).provideWindowSurfaceInfo(
+ vri.getWindowFlags(), Process.myUid(), vri.getSurfaceControl());
+ }
+
private void launchActivity() {
final Object waitObject = new Object();
final int[] location = new int[2];
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index e6361e1..6adceb9 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -230,7 +230,9 @@
new InsetsSourceControl(ID_STATUS_BAR, statusBars(), mLeash,
false /* initialVisible */, new Point(), Insets.NONE),
new int[1], hideTypes, new int[1], new int[1]);
- assertTrue(mRemoveSurfaceCalled);
+ if (!android.view.inputmethod.Flags.refactorInsetsController()) {
+ assertTrue(mRemoveSurfaceCalled);
+ }
assertEquals(0, hideTypes[0]);
});
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index a289df0..c40137f 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -16,8 +16,6 @@
package android.view;
-import static android.app.UiModeManager.MODE_NIGHT_NO;
-import static android.app.UiModeManager.MODE_NIGHT_YES;
import static android.util.SequenceUtils.getInitSeq;
import static android.view.HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING;
import static android.view.InputDevice.SOURCE_ROTARY_ENCODER;
@@ -69,10 +67,8 @@
import android.annotation.NonNull;
import android.app.Instrumentation;
import android.app.UiModeManager;
-import android.app.UiModeManager.ForceInvertType;
import android.content.Context;
import android.graphics.ForceDarkType;
-import android.graphics.ForceDarkType.ForceDarkTypeDef;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Binder;
@@ -97,12 +93,9 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ShellIdentityUtils;
-import com.android.compatibility.common.util.TestUtils;
import com.android.cts.input.BlockingQueueEventVerifier;
import com.android.window.flags.Flags;
-import com.google.common.truth.Expect;
-
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.AfterClass;
@@ -131,8 +124,6 @@
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
- @Rule
- public final Expect mExpect = Expect.create();
private ViewRootImpl mViewRootImpl;
private View mView;
@@ -1516,34 +1507,49 @@
}
@Test
- @RequiresFlagsEnabled(FLAG_FORCE_INVERT_COLOR)
- public void updateConfiguration_returnsExpectedForceDarkMode() {
- waitForSystemNightModeActivated(true);
+ public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() {
+ mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ Settings.Secure.putInt(
+ sContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+ /* value= */ 0
+ );
+ var uiModeManager = sContext.getSystemService(UiModeManager.class);
+ uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+ });
- verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
- UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
- verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
- UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
- verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
- UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
- verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
- UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+ sInstrumentation.runOnMainSync(() ->
+ mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+ );
- waitForSystemNightModeActivated(false);
-
- verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
- UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
- verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
- UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
- verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
- UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
- verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
- UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+ assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
}
@Test
- @EnableFlags(FLAG_FORCE_INVERT_COLOR)
+ public void forceInvertOnDarkThemeOff_forceDarkModeEnabled() {
+ mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ Settings.Secure.putInt(
+ sContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+ /* value= */ 1
+ );
+ var uiModeManager = sContext.getSystemService(UiModeManager.class);
+ uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+ });
+
+ sInstrumentation.runOnMainSync(() ->
+ mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+ );
+
+ assertThat(mViewRootImpl.determineForceDarkType())
+ .isEqualTo(ForceDarkType.FORCE_INVERT_COLOR_DARK);
+ }
+
+ @Test
public void forceInvertOffForceDarkOff_forceDarkModeDisabled() {
+ mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
ShellIdentityUtils.invokeWithShellPermissions(() -> {
Settings.Secure.putInt(
sContext.getContentResolver(),
@@ -1556,14 +1562,15 @@
});
sInstrumentation.runOnMainSync(() ->
- mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
+ mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+ );
assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
}
@Test
- @EnableFlags(FLAG_FORCE_INVERT_COLOR)
public void forceInvertOffForceDarkOn_forceDarkModeEnabled() {
+ mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
ShellIdentityUtils.invokeWithShellPermissions(() -> {
Settings.Secure.putInt(
sContext.getContentResolver(),
@@ -1575,7 +1582,8 @@
});
sInstrumentation.runOnMainSync(() ->
- mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
+ mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
+ );
assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.FORCE_DARK);
}
@@ -1782,39 +1790,4 @@
() -> view.getViewTreeObserver().removeOnDrawListener(listener));
}
}
-
- private void waitForSystemNightModeActivated(boolean active) {
- ShellIdentityUtils.invokeWithShellPermissions(() ->
- sInstrumentation.runOnMainSync(() -> {
- var uiModeManager = sContext.getSystemService(UiModeManager.class);
- uiModeManager.setNightModeActivated(active);
- }));
- sInstrumentation.waitForIdleSync();
- }
-
- private void verifyForceDarkType(boolean isAppInNightMode, boolean isForceInvertEnabled,
- @ForceInvertType int expectedForceInvertType,
- @ForceDarkTypeDef int expectedForceDarkType) {
- var uiModeManager = sContext.getSystemService(UiModeManager.class);
- ShellIdentityUtils.invokeWithShellPermissions(() -> {
- uiModeManager.setApplicationNightMode(
- isAppInNightMode ? MODE_NIGHT_YES : MODE_NIGHT_NO);
- Settings.Secure.putInt(
- sContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
- isForceInvertEnabled ? 1 : 0);
- });
-
- sInstrumentation.runOnMainSync(() ->
- mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
- try {
- TestUtils.waitUntil("Waiting for force invert state changed",
- () -> (uiModeManager.getForceInvertState() == expectedForceInvertType));
- } catch (Exception e) {
- Log.e(TAG, "Unexpected error trying to apply force invert state. " + e);
- e.printStackTrace();
- }
-
- mExpect.that(mViewRootImpl.determineForceDarkType()).isEqualTo(expectedForceDarkType);
- }
}
diff --git a/core/tests/coretests/src/android/view/ViewRootRectTrackerTest.java b/core/tests/coretests/src/android/view/ViewRootRectTrackerTest.java
new file mode 100644
index 0000000..c66e100
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewRootRectTrackerTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.view;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.testng.AssertJUnit.assertEquals;
+
+import android.graphics.Rect;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.collect.Lists;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ViewRootRectTrackerTest {
+ private ViewRootRectTracker mTracker;
+ private final List<Rect> mRects = Lists.newArrayList(new Rect(0, 0, 5, 5),
+ new Rect(5, 5, 10, 10));
+
+ @Before
+ public void setUp() {
+ mTracker = new ViewRootRectTracker(v -> Collections.emptyList());
+ }
+
+ @Test
+ public void setRootRectsAndComputeTest() {
+ mTracker.setRootRects(mRects);
+ mTracker.computeChanges();
+ assertEquals(mRects, mTracker.getLastComputedRects());
+ }
+
+ @Test
+ public void waitingForComputeChangesTest() {
+ mTracker.setRootRects(mRects);
+ assertTrue(mTracker.isWaitingForComputeChanges());
+ mTracker.computeChangedRects();
+ assertFalse(mTracker.isWaitingForComputeChanges());
+
+ View mockView = mock(View.class);
+ mTracker.updateRectsForView(mockView);
+ assertTrue(mTracker.isWaitingForComputeChanges());
+ mTracker.computeChangedRects();
+ assertFalse(mTracker.isWaitingForComputeChanges());
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
index 3239598..0ba2d85 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.annotation.SuppressLint;
import android.platform.test.annotations.IgnoreUnderRavenwood;
import android.platform.test.ravenwood.RavenwoodRule;
import android.util.SparseArray;
@@ -287,6 +288,7 @@
0, lastUidCpuTimes.size());
}
+ @SuppressLint("CheckResult")
@Test
public void testAddDeltaFromBpf() {
LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 5);
diff --git a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
index 7e5d0a4..959e121 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertThrows;
+import android.annotation.SuppressLint;
import android.os.BadParcelableException;
import android.os.Parcel;
import android.platform.test.ravenwood.RavenwoodRule;
@@ -176,6 +177,7 @@
assertCounts(newCounter, 0, new long[]{116, 232, 364, 528});
}
+ @SuppressLint("CheckResult")
private void assertCounts(LongArrayMultiStateCounter counter, int state, long[] expected) {
long[] counts = new long[expected.length];
counter.getCounts(counts, state);
diff --git a/graphics/java/android/framework_graphics.aconfig b/graphics/java/android/framework_graphics.aconfig
index a63cbee..fdbee3c 100644
--- a/graphics/java/android/framework_graphics.aconfig
+++ b/graphics/java/android/framework_graphics.aconfig
@@ -42,3 +42,11 @@
description: "Add DISPLAY_BT2020 ColorSpace support"
bug: "344038816"
}
+
+flag {
+ name: "gradient_drawable_shape_rounded_cap"
+ is_fixed_read_only: true
+ namespace: "core_graphics"
+ description: "Make GradientDrawable support drawing ring with rounded stroke cap."
+ bug: "380000245"
+}
diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java
index 683c157..5296ee8 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -23,6 +23,7 @@
* @removed
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class AvoidXfermode extends Xfermode {
// these need to match the enum in AvoidXfermode.h on the native side
diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java
index 9b9be244..9f60534 100644
--- a/graphics/java/android/graphics/BLASTBufferQueue.java
+++ b/graphics/java/android/graphics/BLASTBufferQueue.java
@@ -26,6 +26,7 @@
/**
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class BLASTBufferQueue {
// Note: This field is accessed by native code.
public long mNativeObject; // BLASTBufferQueue*
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index a2a0f49..0ca58cc 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -48,6 +48,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public abstract class BaseCanvas {
/**
* Should only be assigned in constructors (or setBitmap if software canvas),
diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java
index 5b1fa7b..0511bd1 100644
--- a/graphics/java/android/graphics/BaseRecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -44,6 +44,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BaseRecordingCanvas extends Canvas {
public BaseRecordingCanvas(long nativeCanvas) {
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 0c4ea79..cd5a54c 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -51,6 +51,7 @@
import java.util.ArrayList;
import java.util.WeakHashMap;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class Bitmap implements Parcelable {
private static final String TAG = "Bitmap";
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 1c20141..a5535c8 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -41,6 +41,7 @@
* Creates Bitmap objects from various sources, including files, streams,
* and byte-arrays.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BitmapFactory {
private static final int DECODE_BUFFER_SIZE = 16 * 1024;
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 29112af..9b3f715 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -37,6 +37,7 @@
* to get a decoded Bitmap of the specified region.
*
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class BitmapRegionDecoder {
private long mNativeBitmapRegionDecoder;
private boolean mRecycled;
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index dcfff62..ac3543a 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -31,6 +31,7 @@
* Shader used to draw a bitmap as a texture. The bitmap can be repeated or
* mirrored by setting the tiling mode.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BitmapShader extends Shader {
/**
* Prevent garbage collection.
diff --git a/graphics/java/android/graphics/BlendMode.java b/graphics/java/android/graphics/BlendMode.java
index c6ae680..c07af4e 100644
--- a/graphics/java/android/graphics/BlendMode.java
+++ b/graphics/java/android/graphics/BlendMode.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public enum BlendMode {
/**
diff --git a/graphics/java/android/graphics/BlendModeColorFilter.java b/graphics/java/android/graphics/BlendModeColorFilter.java
index d4e2373..d5dd0d3c 100644
--- a/graphics/java/android/graphics/BlendModeColorFilter.java
+++ b/graphics/java/android/graphics/BlendModeColorFilter.java
@@ -23,6 +23,7 @@
* A color filter that can be used to tint the source pixels using a single
* color and a specific {@link BlendMode}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class BlendModeColorFilter extends ColorFilter {
@ColorInt final int mColor;
diff --git a/graphics/java/android/graphics/BlurMaskFilter.java b/graphics/java/android/graphics/BlurMaskFilter.java
index f3064f8..22ed524 100644
--- a/graphics/java/android/graphics/BlurMaskFilter.java
+++ b/graphics/java/android/graphics/BlurMaskFilter.java
@@ -22,6 +22,7 @@
* inside, or straddles, the original mask's border, is controlled by the
* Blur enum.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class BlurMaskFilter extends MaskFilter {
public enum Blur {
diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java
index 46640d7..27b695c 100644
--- a/graphics/java/android/graphics/Camera.java
+++ b/graphics/java/android/graphics/Camera.java
@@ -21,6 +21,7 @@
* generate a matrix that can be applied, for instance, on a
* {@link Canvas}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Camera {
/**
* Creates a new camera, with empty transformations.
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 28c2ca3..9137150b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -54,6 +54,7 @@
* <a href="{@docRoot}guide/topics/graphics/2d-graphics.html">
* Canvas and Drawables</a> developer guide.</p></div>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Canvas extends BaseCanvas {
private static int sCompatibilityVersion = 0;
private static boolean sCompatibilityRestore = false;
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
index e949584..755161d 100644
--- a/graphics/java/android/graphics/CanvasProperty.java
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -25,6 +25,7 @@
* TODO: Make public?
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class CanvasProperty<T> {
private VirtualRefBasePtr mProperty;
diff --git a/graphics/java/android/graphics/ColorFilter.java b/graphics/java/android/graphics/ColorFilter.java
index 7050325..918f26d 100644
--- a/graphics/java/android/graphics/ColorFilter.java
+++ b/graphics/java/android/graphics/ColorFilter.java
@@ -23,6 +23,7 @@
* each pixel drawn with that paint. This is an abstract class that should
* never be used directly.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ColorFilter {
private static class NoImagePreloadHolder {
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index bfdf318..cb78a83 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -27,6 +27,7 @@
*
* @see ColorMatrix
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ColorMatrixColorFilter extends ColorFilter {
@UnsupportedAppUsage
private final ColorMatrix mMatrix = new ColorMatrix();
diff --git a/graphics/java/android/graphics/Compatibility.java b/graphics/java/android/graphics/Compatibility.java
index 747fbf1..f89a4f7 100644
--- a/graphics/java/android/graphics/Compatibility.java
+++ b/graphics/java/android/graphics/Compatibility.java
@@ -21,6 +21,7 @@
* specified by the app.
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class Compatibility {
private Compatibility() {}
diff --git a/graphics/java/android/graphics/ComposePathEffect.java b/graphics/java/android/graphics/ComposePathEffect.java
index 7d59ece..b380d2e 100644
--- a/graphics/java/android/graphics/ComposePathEffect.java
+++ b/graphics/java/android/graphics/ComposePathEffect.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ComposePathEffect extends PathEffect {
/**
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index e714568..57a11d2 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -22,6 +22,7 @@
/** A subclass of shader that returns the composition of two other shaders, combined by
an {@link android.graphics.Xfermode} subclass.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ComposeShader extends Shader {
Shader mShaderA;
diff --git a/graphics/java/android/graphics/CornerPathEffect.java b/graphics/java/android/graphics/CornerPathEffect.java
index 8f4d7d9..37f0d29 100644
--- a/graphics/java/android/graphics/CornerPathEffect.java
+++ b/graphics/java/android/graphics/CornerPathEffect.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class CornerPathEffect extends PathEffect {
/**
diff --git a/graphics/java/android/graphics/DashPathEffect.java b/graphics/java/android/graphics/DashPathEffect.java
index ef3ebe8..ff3c376 100644
--- a/graphics/java/android/graphics/DashPathEffect.java
+++ b/graphics/java/android/graphics/DashPathEffect.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DashPathEffect extends PathEffect {
/**
diff --git a/graphics/java/android/graphics/DiscretePathEffect.java b/graphics/java/android/graphics/DiscretePathEffect.java
index 3b3c9c9..77f9845 100644
--- a/graphics/java/android/graphics/DiscretePathEffect.java
+++ b/graphics/java/android/graphics/DiscretePathEffect.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DiscretePathEffect extends PathEffect {
/**
diff --git a/graphics/java/android/graphics/DrawFilter.java b/graphics/java/android/graphics/DrawFilter.java
index c7fdcb2..505a830 100644
--- a/graphics/java/android/graphics/DrawFilter.java
+++ b/graphics/java/android/graphics/DrawFilter.java
@@ -22,6 +22,7 @@
* can disable/enable antialiasing, or change the color for everything this is
* drawn.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class DrawFilter {
/**
diff --git a/graphics/java/android/graphics/EmbossMaskFilter.java b/graphics/java/android/graphics/EmbossMaskFilter.java
index 003678a..f0a661f 100644
--- a/graphics/java/android/graphics/EmbossMaskFilter.java
+++ b/graphics/java/android/graphics/EmbossMaskFilter.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class EmbossMaskFilter extends MaskFilter {
/**
* Create an emboss maskfilter
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 88f0e8e..09022ee 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -41,6 +41,7 @@
* @deprecated Use {@link android.graphics.fonts.FontFamily} instead.
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class FontFamily {
private static String TAG = "FontFamily";
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 13c4a94..8d0f128 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -48,6 +48,7 @@
* Parser for font config files.
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class FontListParser {
private static final String TAG = "FontListParser";
diff --git a/graphics/java/android/graphics/ForceDarkType.java b/graphics/java/android/graphics/ForceDarkType.java
index 396b037..d21aef3 100644
--- a/graphics/java/android/graphics/ForceDarkType.java
+++ b/graphics/java/android/graphics/ForceDarkType.java
@@ -29,6 +29,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ForceDarkType {
/**
* Force dark disabled: normal, default operation.
diff --git a/graphics/java/android/graphics/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
index 3b8f466..5202138 100644
--- a/graphics/java/android/graphics/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -38,6 +38,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class FrameInfo {
public long[] frameInfo = new long[FRAME_INFO_SIZE];
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index 63ca3b8..7fc13db 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -86,6 +86,7 @@
* for these functions cancels out and does not affect the result, so other bases may be used
* if preferred.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class Gainmap implements Parcelable {
/** @hide */
diff --git a/graphics/java/android/graphics/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java
index 6705b25..4982851 100644
--- a/graphics/java/android/graphics/GraphicBuffer.java
+++ b/graphics/java/android/graphics/GraphicBuffer.java
@@ -28,6 +28,7 @@
* @hide
*/
@SuppressWarnings("UnusedDeclaration")
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class GraphicBuffer implements Parcelable {
// Note: keep usage flags in sync with GraphicBuffer.h and gralloc.h
public static final int USAGE_SW_READ_NEVER = 0x0;
diff --git a/graphics/java/android/graphics/GraphicsProtos.java b/graphics/java/android/graphics/GraphicsProtos.java
index 6bc41d3..fa7eaf9 100644
--- a/graphics/java/android/graphics/GraphicsProtos.java
+++ b/graphics/java/android/graphics/GraphicsProtos.java
@@ -24,6 +24,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class GraphicsProtos {
/** GraphicsProtos can never be an instance */
private GraphicsProtos() {}
diff --git a/graphics/java/android/graphics/GraphicsStatsService.java b/graphics/java/android/graphics/GraphicsStatsService.java
index 7a012bc..d0b9998 100644
--- a/graphics/java/android/graphics/GraphicsStatsService.java
+++ b/graphics/java/android/graphics/GraphicsStatsService.java
@@ -74,6 +74,7 @@
* for the process to use.
*
* @hide */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class GraphicsStatsService extends IGraphicsStats.Stub {
public static final String GRAPHICS_STATS_SERVICE = "graphicsstats";
diff --git a/graphics/java/android/graphics/HardwareBufferRenderer.java b/graphics/java/android/graphics/HardwareBufferRenderer.java
index e04f13c..8179870 100644
--- a/graphics/java/android/graphics/HardwareBufferRenderer.java
+++ b/graphics/java/android/graphics/HardwareBufferRenderer.java
@@ -55,6 +55,7 @@
* HardwareBufferRenderer will never clear contents before each draw invocation so previous contents
* in the {@link HardwareBuffer} target will be preserved across renders.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class HardwareBufferRenderer implements AutoCloseable {
private static final ColorSpace DEFAULT_COLORSPACE = ColorSpace.get(Named.SRGB);
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 65854dd..3444f84 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -79,6 +79,7 @@
* Failure to do so will cause the render thread to stall on that surface, blocking all
* HardwareRenderer instances.</p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class HardwareRenderer {
private static final String LOG_TAG = "HardwareRenderer";
@@ -658,6 +659,13 @@
}
/**
+ * @hide
+ */
+ public void addObserver(long nativeObserver) {
+ nAddObserver(mNativeProxy, nativeObserver);
+ }
+
+ /**
* TODO: Public API this?
*
* @hide
@@ -667,6 +675,13 @@
}
/**
+ * @hide
+ */
+ public void removeObserver(long nativeObserver) {
+ nRemoveObserver(mNativeProxy, nativeObserver);
+ }
+
+ /**
* Sets the desired color mode on this renderer. Whether or not the actual rendering
* will use the requested colorMode depends on the hardware support for such rendering.
*
diff --git a/graphics/java/android/graphics/HardwareRendererObserver.java b/graphics/java/android/graphics/HardwareRendererObserver.java
index d5a6a2f..9926378 100644
--- a/graphics/java/android/graphics/HardwareRendererObserver.java
+++ b/graphics/java/android/graphics/HardwareRendererObserver.java
@@ -28,6 +28,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class HardwareRendererObserver {
private final long[] mFrameMetrics;
private final Handler mHandler;
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 6395179..419929a 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -44,6 +44,7 @@
import android.net.Uri;
import android.os.Build;
import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodIgnore;
import android.system.ErrnoException;
import android.system.Os;
import android.util.DisplayMetrics;
@@ -173,6 +174,7 @@
* });
* </pre>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class ImageDecoder implements AutoCloseable {
/**
* Source of encoded image data.
@@ -1987,6 +1989,7 @@
* Check if HEVC decoder is supported by the device.
*/
@SuppressWarnings("AndroidFrameworkCompatChange")
+ @RavenwoodIgnore(blockedBy = MediaCodecList.class)
private static boolean isHevcDecoderSupported() {
synchronized (sIsHevcDecoderSupportedLock) {
if (sIsHevcDecoderSupportedInitialized) {
@@ -2010,6 +2013,7 @@
* Checks if the device supports decoding 10-bit AV1.
*/
@SuppressWarnings("AndroidFrameworkCompatChange") // This is not an app-visible API.
+ @RavenwoodIgnore(blockedBy = MediaCodecList.class)
private static boolean isP010SupportedForAV1() {
synchronized (sIsP010SupportedLock) {
if (sIsP010SupportedFlagsInitialized) {
@@ -2025,6 +2029,7 @@
* This method is called by JNI.
*/
@SuppressWarnings("unused")
+ @RavenwoodIgnore(blockedBy = MediaCodecList.class)
private static boolean isP010SupportedForHEVC() {
synchronized (sIsP010SupportedLock) {
if (sIsP010SupportedFlagsInitialized) {
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index b4899f9..4c9f5ac 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -24,6 +24,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class ImageFormat {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
diff --git a/graphics/java/android/graphics/LayerRasterizer.java b/graphics/java/android/graphics/LayerRasterizer.java
index 25155ab..1a44248 100644
--- a/graphics/java/android/graphics/LayerRasterizer.java
+++ b/graphics/java/android/graphics/LayerRasterizer.java
@@ -20,6 +20,7 @@
* @removed feature is not supported by hw-accerlerated or PDF backends
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class LayerRasterizer extends Rasterizer {
public LayerRasterizer() { }
diff --git a/graphics/java/android/graphics/LeakyTypefaceStorage.java b/graphics/java/android/graphics/LeakyTypefaceStorage.java
index 618e60d..25a84369 100644
--- a/graphics/java/android/graphics/LeakyTypefaceStorage.java
+++ b/graphics/java/android/graphics/LeakyTypefaceStorage.java
@@ -32,6 +32,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class LeakyTypefaceStorage {
private static final Object sLock = new Object();
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index fe73a1a..1afdc77 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -40,6 +40,7 @@
* </pre>
* The result is pinned to the <code>[0..255]</code> range for each channel.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class LightingColorFilter extends ColorFilter {
@ColorInt
private int mMul;
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 0879371..c6566c9 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -24,6 +24,7 @@
import android.os.Build;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class LinearGradient extends Shader {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private float mX0;
diff --git a/graphics/java/android/graphics/MaskFilter.java b/graphics/java/android/graphics/MaskFilter.java
index d474315..b490650 100644
--- a/graphics/java/android/graphics/MaskFilter.java
+++ b/graphics/java/android/graphics/MaskFilter.java
@@ -21,6 +21,7 @@
* an alpha-channel mask before drawing it. A subclass of MaskFilter may be
* installed into a Paint. Blur and emboss are implemented as subclasses of MaskFilter.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class MaskFilter {
protected void finalize() throws Throwable {
diff --git a/graphics/java/android/graphics/Mesh.java b/graphics/java/android/graphics/Mesh.java
index 6be8332..f4d841b 100644
--- a/graphics/java/android/graphics/Mesh.java
+++ b/graphics/java/android/graphics/Mesh.java
@@ -37,6 +37,7 @@
* for the mesh. Once generated, a mesh object can be drawn through
* {@link Canvas#drawMesh(Mesh, BlendMode, Paint)}
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Mesh {
private long mNativeMeshWrapper;
private boolean mIsIndexed;
diff --git a/graphics/java/android/graphics/MeshSpecification.java b/graphics/java/android/graphics/MeshSpecification.java
index b1aae7f..9c7e948 100644
--- a/graphics/java/android/graphics/MeshSpecification.java
+++ b/graphics/java/android/graphics/MeshSpecification.java
@@ -72,6 +72,7 @@
* These should be kept in mind when generating a mesh specification, as exceeding them will
* lead to errors.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class MeshSpecification {
long mNativeMeshSpec;
diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index 9c9535d..cefe391 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -27,6 +27,7 @@
* @deprecated Prefer {@link android.graphics.drawable.AnimatedImageDrawable}.
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Movie {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private long mNativeMovie;
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 382269f..00df23f 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -32,6 +32,7 @@
* using a WYSIWYG graphics editor.
* </p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class NinePatch {
/**
* Struct of inset information attached to a 9 patch bitmap.
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 3d4dccf..a0ca098 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -66,6 +66,7 @@
* The Paint class holds the style and color information about how to draw
* geometries, text and bitmaps.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Paint {
private static final String TAG = "Paint";
diff --git a/graphics/java/android/graphics/PaintFlagsDrawFilter.java b/graphics/java/android/graphics/PaintFlagsDrawFilter.java
index 2326611..f4c49b1 100644
--- a/graphics/java/android/graphics/PaintFlagsDrawFilter.java
+++ b/graphics/java/android/graphics/PaintFlagsDrawFilter.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PaintFlagsDrawFilter extends DrawFilter {
/**
* Subclass of DrawFilter that affects every paint by first clearing
diff --git a/graphics/java/android/graphics/PathDashPathEffect.java b/graphics/java/android/graphics/PathDashPathEffect.java
index 2b6a6ed..dc92e6c 100644
--- a/graphics/java/android/graphics/PathDashPathEffect.java
+++ b/graphics/java/android/graphics/PathDashPathEffect.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PathDashPathEffect extends PathEffect {
public enum Style {
diff --git a/graphics/java/android/graphics/PathEffect.java b/graphics/java/android/graphics/PathEffect.java
index 3292501..9bb7193 100644
--- a/graphics/java/android/graphics/PathEffect.java
+++ b/graphics/java/android/graphics/PathEffect.java
@@ -21,6 +21,7 @@
* the geometry of a drawing primitive before it is transformed by the
* canvas' matrix and drawn.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PathEffect {
protected void finalize() throws Throwable {
diff --git a/graphics/java/android/graphics/PathIterator.java b/graphics/java/android/graphics/PathIterator.java
index d7caabf..1ed70d0 100644
--- a/graphics/java/android/graphics/PathIterator.java
+++ b/graphics/java/android/graphics/PathIterator.java
@@ -34,6 +34,7 @@
* <code>PathIterator</code> can be used to query a given {@link Path} object, to discover its
* operations and point values.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PathIterator implements Iterator<PathIterator.Segment> {
private final float[] mPointsArray;
@@ -47,9 +48,11 @@
private static final boolean IS_DALVIK = "dalvik".equalsIgnoreCase(
System.getProperty("java.vm.name"));
- private static final NativeAllocationRegistry sRegistry =
- NativeAllocationRegistry.createMalloced(
- PathIterator.class.getClassLoader(), nGetFinalizer());
+ private static class NoImagePreloadHolder {
+ private static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ PathIterator.class.getClassLoader(), nGetFinalizer());
+ }
/**
* The <code>Verb</code> indicates the operation for a given segment of a path. These
@@ -69,6 +72,11 @@
public static final int VERB_CLOSE = 5;
public static final int VERB_DONE = 6;
+
+ static {
+ // Keep <cinit> exist in bytecode
+ }
+
/**
* Returns a {@link PathIterator} object for this path, which can be used to query the
* data (operations and points) in the path. Iterators can only be used on Path objects
@@ -90,7 +98,7 @@
mPointsArray = new float[POINT_ARRAY_SIZE];
mPointsAddress = 0;
}
- sRegistry.registerNativeAllocation(this, mNativeIterator);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeIterator);
}
/**
diff --git a/graphics/java/android/graphics/PathMeasure.java b/graphics/java/android/graphics/PathMeasure.java
index 2c6cfa5..4d123db 100644
--- a/graphics/java/android/graphics/PathMeasure.java
+++ b/graphics/java/android/graphics/PathMeasure.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PathMeasure {
private Path mPath;
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index ee4165b..54eb2bc 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -33,6 +33,7 @@
* <p class="note"><strong>Note:</strong> Prior to API level 23 a picture cannot
* be replayed on a hardware accelerated canvas.</p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Picture {
private PictureCanvas mRecordingCanvas;
// TODO: Figure out if this was a false-positive
diff --git a/graphics/java/android/graphics/PixelXorXfermode.java b/graphics/java/android/graphics/PixelXorXfermode.java
index 27884e0..6427852 100644
--- a/graphics/java/android/graphics/PixelXorXfermode.java
+++ b/graphics/java/android/graphics/PixelXorXfermode.java
@@ -20,6 +20,7 @@
* @removed
*/
@Deprecated
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PixelXorXfermode extends Xfermode {
public PixelXorXfermode(int opColor) {
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index eb940e2..730a804 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -26,6 +26,7 @@
*
* Consider using {@link BlendMode} instead as it provides a wider variety of tinting options
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PorterDuff {
/**
* {@usesMathJax}
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index 0700f21..777ef6c 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -25,6 +25,7 @@
* A color filter that can be used to tint the source pixels using a single
* color and a specific {@link PorterDuff Porter-Duff composite mode}.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PorterDuffColorFilter extends ColorFilter {
@ColorInt
private int mColor;
diff --git a/graphics/java/android/graphics/PorterDuffXfermode.java b/graphics/java/android/graphics/PorterDuffXfermode.java
index 83d0507..e10d7370 100644
--- a/graphics/java/android/graphics/PorterDuffXfermode.java
+++ b/graphics/java/android/graphics/PorterDuffXfermode.java
@@ -23,6 +23,7 @@
* information on the available alpha compositing and blending modes.</p>
*
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class PorterDuffXfermode extends Xfermode {
/**
* Create an xfermode that uses the specified porter-duff mode.
diff --git a/graphics/java/android/graphics/PostProcessor.java b/graphics/java/android/graphics/PostProcessor.java
index 6fed39b..066214a 100644
--- a/graphics/java/android/graphics/PostProcessor.java
+++ b/graphics/java/android/graphics/PostProcessor.java
@@ -37,6 +37,7 @@
*
* <p>Supplied to ImageDecoder via {@link ImageDecoder#setPostProcessor setPostProcessor}.</p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public interface PostProcessor {
/**
* Do any processing after (for example) decoding.
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index e582e66..06e92ea 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -24,6 +24,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class RadialGradient extends Shader {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private float mX;
diff --git a/graphics/java/android/graphics/Rasterizer.java b/graphics/java/android/graphics/Rasterizer.java
index 5750954..5e67da5 100644
--- a/graphics/java/android/graphics/Rasterizer.java
+++ b/graphics/java/android/graphics/Rasterizer.java
@@ -24,6 +24,7 @@
/**
* @removed feature is not supported by hw-accerlerated or PDF backends
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Rasterizer {
protected void finalize() throws Throwable { }
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index cc5b3b9..a56f461 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -33,6 +33,7 @@
* {@link RenderNode#endRecording()} is called. It must not be retained beyond that as it is
* internally reused.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class RecordingCanvas extends BaseRecordingCanvas {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index 2970873..e2215d4 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -23,6 +23,7 @@
import android.os.Parcelable;
import android.util.Pools.SynchronizedPool;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Region implements Parcelable {
private static final int MAX_POOL_SIZE = 10;
diff --git a/graphics/java/android/graphics/RegionIterator.java b/graphics/java/android/graphics/RegionIterator.java
index 443b23c..5d74487 100644
--- a/graphics/java/android/graphics/RegionIterator.java
+++ b/graphics/java/android/graphics/RegionIterator.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class RegionIterator {
/**
diff --git a/graphics/java/android/graphics/RenderEffect.java b/graphics/java/android/graphics/RenderEffect.java
index b8a4685..06bfb82 100644
--- a/graphics/java/android/graphics/RenderEffect.java
+++ b/graphics/java/android/graphics/RenderEffect.java
@@ -30,6 +30,7 @@
* Additionally a {@link RenderEffect} can be applied to a View's backing RenderNode through
* {@link android.view.View#setRenderEffect(RenderEffect)}
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class RenderEffect {
private static class RenderEffectHolder {
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 03a8b30..fa41876 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -192,6 +192,7 @@
* top-level content is desired, and finally calling {@link Surface#unlockCanvasAndPost(Canvas)}.
* </p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class RenderNode {
// Use a Holder to allow static initialization in the boot image.
diff --git a/graphics/java/android/graphics/RuntimeColorFilter.java b/graphics/java/android/graphics/RuntimeColorFilter.java
index a64acfe..06aecc3 100644
--- a/graphics/java/android/graphics/RuntimeColorFilter.java
+++ b/graphics/java/android/graphics/RuntimeColorFilter.java
@@ -37,6 +37,7 @@
* </pre>
*/
@FlaggedApi(Flags.FLAG_RUNTIME_COLOR_FILTERS_BLENDERS)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class RuntimeColorFilter extends ColorFilter {
private String mAgsl;
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index db2376e..6464f72 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -248,6 +248,7 @@
* the bitmap), remember that the coordinates are local to the canvas.</p>
*
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class RuntimeShader extends Shader {
private static class NoImagePreloadHolder {
diff --git a/graphics/java/android/graphics/RuntimeXfermode.java b/graphics/java/android/graphics/RuntimeXfermode.java
index c8a0b1a..1e20bd3 100644
--- a/graphics/java/android/graphics/RuntimeXfermode.java
+++ b/graphics/java/android/graphics/RuntimeXfermode.java
@@ -39,6 +39,7 @@
* </pre>
*/
@FlaggedApi(Flags.FLAG_RUNTIME_COLOR_FILTERS_BLENDERS)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class RuntimeXfermode extends Xfermode {
private static class NoImagePreloadHolder {
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 4d6bead..369fab4 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -29,6 +29,7 @@
* paint.setShader(shader). After that any object (other than a bitmap) that is
* drawn with that paint will get its color(s) from the shader.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Shader {
private static class NoImagePreloadHolder {
diff --git a/graphics/java/android/graphics/SumPathEffect.java b/graphics/java/android/graphics/SumPathEffect.java
index 8fedc31..3543e10 100644
--- a/graphics/java/android/graphics/SumPathEffect.java
+++ b/graphics/java/android/graphics/SumPathEffect.java
@@ -16,6 +16,7 @@
package android.graphics;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SumPathEffect extends PathEffect {
/**
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 5caedba..df384ea 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -78,6 +78,7 @@
* frame-available callback is called on an arbitrary thread, so unless special care is taken {@link
* #updateTexImage} should not be called directly from the callback.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SurfaceTexture {
private final Looper mCreatorLooper;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 3a29395..9421925 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -23,6 +23,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class SweepGradient extends Shader {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private float mCx;
diff --git a/graphics/java/android/graphics/TableMaskFilter.java b/graphics/java/android/graphics/TableMaskFilter.java
index 204f970..ca7627c 100644
--- a/graphics/java/android/graphics/TableMaskFilter.java
+++ b/graphics/java/android/graphics/TableMaskFilter.java
@@ -21,6 +21,7 @@
/**
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TableMaskFilter extends MaskFilter {
public TableMaskFilter(byte[] table) {
diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java
index ef3f7f7..681c48e 100644
--- a/graphics/java/android/graphics/TemporaryBuffer.java
+++ b/graphics/java/android/graphics/TemporaryBuffer.java
@@ -23,6 +23,7 @@
/**
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TemporaryBuffer {
@UnsupportedAppUsage
public static char[] obtain(int len) {
diff --git a/graphics/java/android/graphics/TextureLayer.java b/graphics/java/android/graphics/TextureLayer.java
index ac1bd69..981b78a 100644
--- a/graphics/java/android/graphics/TextureLayer.java
+++ b/graphics/java/android/graphics/TextureLayer.java
@@ -29,6 +29,7 @@
*
* @hide TODO: Make this a SystemApi for b/155905258
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class TextureLayer implements AutoCloseable {
private HardwareRenderer mRenderer;
private VirtualRefBasePtr mFinalizer;
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 874b847..d1aca34 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -42,6 +42,7 @@
import android.os.Trace;
import android.provider.FontRequest;
import android.provider.FontsContract;
+import android.ravenwood.annotation.RavenwoodReplace;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.text.FontConfig;
@@ -86,6 +87,7 @@
* textSize, textSkewX, textScaleX to specify
* how text appears when drawn (and measured).
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Typeface {
private static String TAG = "Typeface";
@@ -93,9 +95,11 @@
/** @hide */
public static final boolean ENABLE_LAZY_TYPEFACE_INITIALIZATION = true;
- private static final NativeAllocationRegistry sRegistry =
- NativeAllocationRegistry.createMalloced(
- Typeface.class.getClassLoader(), nativeGetReleaseFunc());
+ private static class NoImagePreloadHolder {
+ static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ Typeface.class.getClassLoader(), nativeGetReleaseFunc());
+ }
/** The default NORMAL typeface object */
public static final Typeface DEFAULT = null;
@@ -1284,7 +1288,7 @@
}
native_instance = ni;
- mCleaner = sRegistry.registerNativeAllocation(this, native_instance);
+ mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance);
mStyle = nativeGetStyle(ni);
mWeight = nativeGetWeight(ni);
mIsVariationInstance = nativeIsVariationInstance(ni);
@@ -1560,9 +1564,23 @@
}
static {
+ staticInitializer();
+ }
+
+ @RavenwoodReplace(reason = "Prevent circular reference on host side JVM", bug = 337329128)
+ private static void staticInitializer() {
+ init();
+ }
+
+ private static void staticInitializer$ravenwood() {
+ /* no-op */
+ }
+
+ /** @hide */
+ public static void init() {
// Preload Roboto-Regular.ttf in Zygote for improving app launch performance.
- preloadFontFile("/system/fonts/Roboto-Regular.ttf");
- preloadFontFile("/system/fonts/RobotoStatic-Regular.ttf");
+ preloadFontFile(SystemFonts.SYSTEM_FONT_DIR + "Roboto-Regular.ttf");
+ preloadFontFile(SystemFonts.SYSTEM_FONT_DIR + "RobotoStatic-Regular.ttf");
String locale = SystemProperties.get("persist.sys.locale", "en-US");
String script = ULocale.addLikelySubtags(ULocale.forLanguageTag(locale)).getScript();
@@ -1642,6 +1660,21 @@
setSystemFontMap(typefaceMap);
}
+ /**
+ * {@link #loadPreinstalledSystemFontMap()} does not actually initialize the native
+ * system font APIs. Add a new method to actually load the font files without going
+ * through SharedMemory.
+ *
+ * @hide
+ */
+ public static void loadNativeSystemFonts() {
+ synchronized (SYSTEM_FONT_MAP_LOCK) {
+ for (var type : sSystemFontMap.values()) {
+ nativeAddFontCollections(type.native_instance);
+ }
+ }
+ }
+
static {
if (!ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
loadPreinstalledSystemFontMap();
diff --git a/graphics/java/android/graphics/Xfermode.java b/graphics/java/android/graphics/Xfermode.java
index fb689e4..eda9e3c 100644
--- a/graphics/java/android/graphics/Xfermode.java
+++ b/graphics/java/android/graphics/Xfermode.java
@@ -28,4 +28,5 @@
* specified in the Modes enum. When an Xfermode is assigned to a Paint, then
* objects drawn with that paint have the xfermode applied.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Xfermode {}
diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java
index b0c7f20..2b7f404 100644
--- a/graphics/java/android/graphics/YuvImage.java
+++ b/graphics/java/android/graphics/YuvImage.java
@@ -32,6 +32,7 @@
* To compress a rectangle region in the YUV data, users have to specify the
* region by left, top, width and height.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class YuvImage {
/**
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 29d033e..ff1dc93 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -16,7 +16,11 @@
package android.graphics.drawable;
+import static com.android.graphics.flags.Flags.FLAG_GRADIENT_DRAWABLE_SHAPE_ROUNDED_CAP;
+import static com.android.graphics.flags.Flags.gradientDrawableShapeRoundedCap;
+
import android.annotation.ColorInt;
+import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -125,8 +129,14 @@
*/
public static final int RING = 3;
+ /**
+ * Shape is an arc.
+ */
+ @FlaggedApi(FLAG_GRADIENT_DRAWABLE_SHAPE_ROUNDED_CAP)
+ public static final int ARC = 4;
+
/** @hide */
- @IntDef({RECTANGLE, OVAL, LINE, RING})
+ @IntDef({RECTANGLE, OVAL, LINE, RING, ARC})
@Retention(RetentionPolicy.SOURCE)
public @interface Shape {}
@@ -167,6 +177,17 @@
@Retention(RetentionPolicy.SOURCE)
public @interface RadiusType {}
+ private static final int BUTT = 0;
+
+ private static final int ROUND = 1;
+
+ private static final int SQUARE = 2;
+
+ /** @hide */
+ @IntDef({BUTT, ROUND, SQUARE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StrokeCap {}
+
private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
@@ -191,6 +212,8 @@
private boolean mMutated;
private Path mRingPath;
private boolean mPathIsDirty = true;
+ private Path mArcPath;
+ private Path mArcOutlinePath;
/** Current gradient radius, valid when {@link #mGradientIsDirty} is false. */
private float mGradientRadius;
@@ -850,6 +873,55 @@
}
break;
}
+ case ARC:
+ if (gradientDrawableShapeRoundedCap()) {
+ // TODO(b/394988176): Consider applying ARC drawing logic to RING shape.
+ float centerX = mRect.centerX();
+ float centerY = mRect.centerY();
+ float thickness =
+ st.mThickness != -1 ? st.mThickness
+ : mRect.width() / st.mThicknessRatio;
+ float radius = st.mInnerRadius != -1 ? st.mInnerRadius
+ : mRect.width() / st.mInnerRadiusRatio;
+ radius -= thickness;
+ float sweep = st.mUseLevelForShape ? (360.0f * getLevel() / 10000.0f) : 360f;
+ mRect.set(centerX - radius, centerY - radius, centerX + radius,
+ centerY + radius);
+
+ // Prepare paint. Set style to STROKE for purpose of drawing line ARC.
+ mFillPaint.setStyle(Paint.Style.STROKE);
+ mFillPaint.setStrokeWidth(thickness);
+ mFillPaint.setStrokeCap(getStrokeLineCapForPaint(st.mStrokeCap));
+ canvas.drawArc(mRect, 0.0f, sweep, /* useCenter= */ false, mFillPaint);
+
+ if (haveStroke) {
+ if (mArcPath == null) {
+ mArcPath = new Path();
+ } else {
+ mArcPath.reset();
+ }
+ if (mArcOutlinePath == null) {
+ mArcOutlinePath = new Path();
+ } else {
+ mArcOutlinePath.reset();
+ }
+ if (sweep == 360f) {
+ mArcPath.addOval(mRect, Path.Direction.CW);
+ } else {
+ mArcPath.arcTo(mRect, 0.0f, sweep, /* forceMoveTo= */ false);
+ }
+
+ // The arc path doesn't have width. So, to get the outline of the result arc
+ // shape, we need to apply the paint effect to the path; then use the
+ // output as the result outline.
+ mFillPaint.getFillPath(mArcPath, mArcOutlinePath);
+ canvas.drawPath(mArcOutlinePath, mStrokePaint);
+ }
+
+ // Restore to FILL
+ mFillPaint.setStyle(Paint.Style.FILL);
+ break;
+ }
case RING:
Path path = buildRing(st);
canvas.drawPath(path, mFillPaint);
@@ -993,6 +1065,36 @@
}
/**
+ * Return current drawable's stroke line cap. Note that this is only respected when drawable is
+ * {@link Shape#ARC}.
+ *
+ * @return the {@link StrokeCap} of current drawable.
+ * @attr ref android.R.styleable#GradientDrawable_strokeCap
+ * @see #setStrokeCap(int)
+ *
+ * @hide
+ */
+ @StrokeCap
+ public int getStrokeCap() {
+ return mGradientState.mStrokeCap;
+ }
+
+ /**
+ * Configure the stroke line cap type that drawable will use while drawing. Note that this is
+ * only respected when drawable is {@link Shape#ARC}.
+ *
+ * @param strokeCapType the stroke line cap type that the drawable will use while drawing.
+ * @attr ref android.R.styleable#GradientDrawable_strokeCap
+ * @see #getStrokeCap
+ *
+ * @hide
+ */
+ public void setStrokeCap(@StrokeCap int strokeCapType) {
+ mGradientState.mStrokeCap = strokeCapType;
+ invalidateSelf();
+ }
+
+ /**
* Configure the padding of the gradient shape
* @param left Left padding of the gradient shape
* @param top Top padding of the gradient shape
@@ -1066,6 +1168,15 @@
return ringPath;
}
+ private Paint.Cap getStrokeLineCapForPaint(@StrokeCap int strokeLineCap) {
+ return switch (strokeLineCap) {
+ case BUTT -> Paint.Cap.BUTT;
+ case ROUND -> Paint.Cap.ROUND;
+ case SQUARE -> Paint.Cap.SQUARE;
+ default -> Paint.Cap.SQUARE;
+ };
+ }
+
/**
* Changes this drawable to use a single color instead of a gradient.
* <p>
@@ -1484,7 +1595,7 @@
state.mShape = a.getInt(R.styleable.GradientDrawable_shape, state.mShape);
state.mDither = a.getBoolean(R.styleable.GradientDrawable_dither, state.mDither);
- if (state.mShape == RING) {
+ if (state.mShape == RING || state.mShape == ARC) {
state.mInnerRadius = a.getDimensionPixelSize(
R.styleable.GradientDrawable_innerRadius, state.mInnerRadius);
@@ -1503,6 +1614,9 @@
state.mUseLevelForShape = a.getBoolean(
R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape);
+
+ state.mStrokeCap = a.getInt(
+ R.styleable.GradientDrawable_strokeCap, state.mStrokeCap);
}
final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1);
@@ -2045,6 +2159,9 @@
public int mInnerRadius = -1;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050218)
public int mThickness = -1;
+ @UnsupportedAppUsage(trackingBug = 380000245)
+ @StrokeCap public int mStrokeCap = ROUND;
+
public boolean mDither = false;
public Insets mOpticalInsets = Insets.NONE;
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 2893177..8be3400 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -44,6 +44,7 @@
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Collections;
@@ -54,6 +55,7 @@
/**
* A font class can be used for creating FontFamily.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class Font {
private static final String TAG = "Font";
@@ -293,7 +295,14 @@
int capacity = assetStream.available();
ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
buffer.order(ByteOrder.nativeOrder());
- assetStream.read(buffer.array(), buffer.arrayOffset(), assetStream.available());
+ if (buffer.hasArray()) {
+ assetStream.read(buffer.array(), buffer.arrayOffset(), assetStream.available());
+ } else {
+ // Direct buffer does not have a backing array on Ravenwood,
+ // wrap it with a channel and read from it
+ var ch = Channels.newChannel(assetStream);
+ ch.read(buffer.duplicate());
+ }
if (assetStream.read() != -1) {
throw new IOException("Unable to access full contents of " + path);
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
index b7bf055..732a5f3 100644
--- a/graphics/java/android/graphics/fonts/FontCustomizationParser.java
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
@@ -43,6 +43,7 @@
*
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class FontCustomizationParser {
private static final String TAG = "FontCustomizationParser";
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 5a7b0bb..0ab4639 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -66,6 +66,7 @@
* </p>
*
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class FontFamily {
private static final String TAG = "FontFamily";
diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java
index abcafb6..305ab3b 100644
--- a/graphics/java/android/graphics/fonts/FontFileUtil.java
+++ b/graphics/java/android/graphics/fonts/FontFileUtil.java
@@ -32,6 +32,7 @@
* Provides a utility for font file operations.
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class FontFileUtil {
private FontFileUtil() {} // Do not instantiate
diff --git a/graphics/java/android/graphics/fonts/FontStyle.java b/graphics/java/android/graphics/fonts/FontStyle.java
index 48969aa..b3ddbed 100644
--- a/graphics/java/android/graphics/fonts/FontStyle.java
+++ b/graphics/java/android/graphics/fonts/FontStyle.java
@@ -44,6 +44,7 @@
* </p>
*
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class FontStyle {
private static final String TAG = "FontStyle";
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
index 30a248b..1d71594 100644
--- a/graphics/java/android/graphics/fonts/FontVariationAxis.java
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -31,6 +31,7 @@
/**
* Class that holds information about single font variation axis.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class FontVariationAxis {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final int mTag;
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 0e25c34..599c426 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -25,6 +25,7 @@
import android.graphics.FontListParser;
import android.graphics.Typeface;
import android.os.LocaleList;
+import android.ravenwood.annotation.RavenwoodReplace;
import android.text.FontConfig;
import android.util.ArrayMap;
import android.util.Log;
@@ -32,6 +33,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.ravenwood.RavenwoodEnvironment;
import org.xmlpull.v1.XmlPullParserException;
@@ -50,23 +52,46 @@
/**
* Provides the system font configurations.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class SystemFonts {
private static final String TAG = "SystemFonts";
- private static final String FONTS_XML = "/system/etc/font_fallback.xml";
- private static final String LEGACY_FONTS_XML = "/system/etc/fonts.xml";
+ private static final String FONTS_XML = getFontsXmlDir() + "font_fallback.xml";
+ /** @hide */
+ public static final String LEGACY_FONTS_XML = getFontsXmlDir() + "fonts.xml";
/** @hide */
- public static final String SYSTEM_FONT_DIR = "/system/fonts/";
+ public static final String SYSTEM_FONT_DIR = getSystemFontDir();
private static final String OEM_XML = "/product/etc/fonts_customization.xml";
/** @hide */
public static final String OEM_FONT_DIR = "/product/fonts/";
+ private static final String DEVICE_FONTS_XML_DIR = "/system/etc/";
+ private static final String DEVICE_FONT_DIR = "/system/fonts/";
+
private SystemFonts() {} // Do not instansiate.
private static final Object LOCK = new Object();
private static @GuardedBy("sLock") Set<Font> sAvailableFonts;
+ @RavenwoodReplace
+ private static String getFontsXmlDir() {
+ return DEVICE_FONTS_XML_DIR;
+ }
+
+ private static String getFontsXmlDir$ravenwood() {
+ return RavenwoodEnvironment.getInstance().getRavenwoodRuntimePath() + "fonts/";
+ }
+
+ @RavenwoodReplace
+ private static String getSystemFontDir() {
+ return DEVICE_FONT_DIR;
+ }
+
+ private static String getSystemFontDir$ravenwood() {
+ return RavenwoodEnvironment.getInstance().getRavenwoodRuntimePath() + "fonts/";
+ }
+
/**
* Returns all available font files in the system.
*
diff --git a/graphics/java/android/graphics/text/GraphemeBreak.java b/graphics/java/android/graphics/text/GraphemeBreak.java
index f82b2fd..0bc1e3b 100644
--- a/graphics/java/android/graphics/text/GraphemeBreak.java
+++ b/graphics/java/android/graphics/text/GraphemeBreak.java
@@ -17,6 +17,7 @@
package android.graphics.text;
/** @hide */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class GraphemeBreak {
private GraphemeBreak() { }
diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java
index 5a1086c..fa3cfbd 100644
--- a/graphics/java/android/graphics/text/LineBreakConfig.java
+++ b/graphics/java/android/graphics/text/LineBreakConfig.java
@@ -24,12 +24,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
-import android.app.ActivityThread;
import android.os.Build;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
+import dalvik.system.VMRuntime;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
@@ -41,6 +42,7 @@
* <a href="https://www.w3.org/TR/css-text-3/#line-break-property" class="external">
* line-break property</a> for more information.
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class LineBreakConfig implements Parcelable {
/**
* No hyphenation preference is specified.
@@ -484,8 +486,7 @@
* @hide
*/
public static @LineBreakStyle int getResolvedLineBreakStyle(@Nullable LineBreakConfig config) {
- final int targetSdkVersion = ActivityThread.currentApplication().getApplicationInfo()
- .targetSdkVersion;
+ final int targetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
final int defaultStyle;
final int vicVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM;
if (targetSdkVersion >= vicVersion) {
@@ -519,8 +520,7 @@
*/
public static @LineBreakWordStyle int getResolvedLineBreakWordStyle(
@Nullable LineBreakConfig config) {
- final int targetSdkVersion = ActivityThread.currentApplication().getApplicationInfo()
- .targetSdkVersion;
+ final int targetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
final int defaultWordStyle;
final int vicVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM;
if (targetSdkVersion >= vicVersion) {
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 94de066..29135b8 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -91,6 +91,7 @@
* </pre>
* </p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class LineBreaker {
/** @hide */
@IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index 884268a..f58d531 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -56,6 +56,7 @@
* </pre>
* </p>
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class MeasuredText {
private static final String TAG = "MeasuredText";
diff --git a/graphics/java/android/graphics/text/PositionedGlyphs.java b/graphics/java/android/graphics/text/PositionedGlyphs.java
index 43216ba..31125ff 100644
--- a/graphics/java/android/graphics/text/PositionedGlyphs.java
+++ b/graphics/java/android/graphics/text/PositionedGlyphs.java
@@ -46,6 +46,7 @@
* @see TextRunShaper#shapeTextRun(char[], int, int, int, int, float, float, boolean, Paint)
* @see TextRunShaper#shapeTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public final class PositionedGlyphs {
private static class NoImagePreloadHolder {
private static final NativeAllocationRegistry REGISTRY =
diff --git a/graphics/java/android/graphics/text/TextRunShaper.java b/graphics/java/android/graphics/text/TextRunShaper.java
index 19ea04a..f1e3d67 100644
--- a/graphics/java/android/graphics/text/TextRunShaper.java
+++ b/graphics/java/android/graphics/text/TextRunShaper.java
@@ -40,6 +40,7 @@
* @see android.text.TextShaper#shapeText(CharSequence, int, int, TextDirectionHeuristic, TextPaint,
* TextShaper.GlyphsConsumer)
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class TextRunShaper {
private TextRunShaper() {} // Do not instantiate
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index eb59d6ef..7ab9e2e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -705,8 +705,7 @@
}
private static boolean isOverlayTransitionSupported() {
- return Flags.moveAnimationOptionsToChange()
- && Flags.activityEmbeddingOverlayPresentationFlag();
+ return Flags.activityEmbeddingOverlayPresentationFlag();
}
@NonNull
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index a08f88a..1e72d64 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -184,3 +184,13 @@
description: "Try out bubble bar on phones"
bug: "394869612"
}
+
+flag {
+ name: "enable_bubble_task_view_listener"
+ namespace: "multitasking"
+ description: "Use the same taskview listener for bubble bar and floating"
+ bug: "272102927"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml b/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml
index 95cd1c7..800ea74 100644
--- a/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml
@@ -2,6 +2,7 @@
package="com.android.wm.shell.multivalenttests">
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
+ <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
<application android:debuggable="true" android:supportsRtl="true" >
<uses-library android:name="android.test.runner" />
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt
index 9ebc3d7..3aefcd5 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.bubbles
+import android.app.ActivityOptions
import android.app.Notification
import android.app.PendingIntent
import android.content.ComponentName
@@ -24,6 +25,8 @@
import android.content.pm.ShortcutInfo
import android.graphics.drawable.Icon
import android.os.UserHandle
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
import android.view.View
@@ -33,6 +36,7 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.android.internal.protolog.ProtoLog
+import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_ANYTHING
import com.android.wm.shell.R
import com.android.wm.shell.bubbles.Bubbles.BubbleMetadataFlagListener
import com.android.wm.shell.common.TestShellExecutor
@@ -41,6 +45,7 @@
import com.android.wm.shell.taskview.TaskViewTaskController
import com.google.common.truth.Truth.assertThat
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
@@ -48,6 +53,7 @@
import org.mockito.Mockito.reset
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
@@ -61,6 +67,9 @@
@RunWith(AndroidJUnit4::class)
class BubbleTaskViewListenerTest {
+ @get:Rule
+ val setFlagsRule = SetFlagsRule()
+
private val context = ApplicationProvider.getApplicationContext<Context>()
private var taskViewController = mock<TaskViewController>()
@@ -155,9 +164,22 @@
}
getInstrumentation().waitForIdleSync()
- // ..so it's pending intent-based, and launches that
+ // ..so it's pending intent-based, so the pending intent should be active
assertThat(b.isPendingIntentActive).isTrue()
- verify(taskViewController).startActivity(any(), eq(pendingIntent), any(), any(), any())
+
+ val intentCaptor = argumentCaptor<Intent>()
+ val optionsCaptor = argumentCaptor<ActivityOptions>()
+
+ verify(taskViewController).startActivity(any(),
+ eq(pendingIntent),
+ intentCaptor.capture(),
+ optionsCaptor.capture(),
+ any())
+ val intentFlags = intentCaptor.lastValue.flags
+ assertThat((intentFlags and Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0).isTrue()
+ assertThat((intentFlags and Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0).isTrue()
+ assertThat(optionsCaptor.lastValue.launchedFromBubble).isTrue()
+ assertThat(optionsCaptor.lastValue.taskAlwaysOnTop).isTrue()
}
@Test
@@ -178,12 +200,52 @@
}
getInstrumentation().waitForIdleSync()
- assertThat(b.isPendingIntentActive).isFalse()
- verify(taskViewController).startShortcutActivity(any(), eq(shortcutInfo), any(), any())
+ val optionsCaptor = argumentCaptor<ActivityOptions>()
+
+ assertThat(b.isPendingIntentActive).isFalse() // not triggered for shortcut chats
+ verify(taskViewController).startShortcutActivity(any(),
+ eq(shortcutInfo),
+ optionsCaptor.capture(),
+ any())
+ assertThat(optionsCaptor.lastValue.launchedFromBubble).isTrue()
+ assertThat(optionsCaptor.lastValue.isApplyActivityFlagsForBubbles).isTrue()
+ assertThat(optionsCaptor.lastValue.taskAlwaysOnTop).isTrue()
+ }
+
+ @EnableFlags(FLAG_ENABLE_BUBBLE_ANYTHING)
+ @Test
+ fun onInitialized_shortcutBubble() {
+ val shortcutInfo = ShortcutInfo.Builder(context)
+ .setId("mockShortcutId")
+ .build()
+
+ val b = createShortcutBubble(shortcutInfo)
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isChat).isFalse()
+ assertThat(b.isShortcut).isTrue()
+ assertThat(b.shortcutInfo).isNotNull()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ val optionsCaptor = argumentCaptor<ActivityOptions>()
+
+ assertThat(b.isPendingIntentActive).isFalse() // chat only triggers setting it active
+ verify(taskViewController).startShortcutActivity(any(),
+ eq(shortcutInfo),
+ optionsCaptor.capture(),
+ any())
+ assertThat(optionsCaptor.lastValue.launchedFromBubble).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.isApplyActivityFlagsForBubbles).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.isApplyMultipleTaskFlagForShortcut).isTrue()
+ assertThat(optionsCaptor.lastValue.taskAlwaysOnTop).isTrue()
}
@Test
- fun onInitialized_appBubble() {
+ fun onInitialized_appBubble_intent() {
val b = createAppBubble()
bubbleTaskViewListener.setBubble(b)
@@ -194,11 +256,83 @@
}
getInstrumentation().waitForIdleSync()
- assertThat(b.isPendingIntentActive).isFalse()
- verify(taskViewController).startActivity(any(), any(), anyOrNull(), any(), any())
+ val intentCaptor = argumentCaptor<Intent>()
+ val optionsCaptor = argumentCaptor<ActivityOptions>()
+
+ assertThat(b.isPendingIntentActive).isFalse() // chat only triggers setting it active
+ verify(taskViewController).startActivity(any(),
+ any(),
+ intentCaptor.capture(),
+ optionsCaptor.capture(),
+ any())
+
+ assertThat((intentCaptor.lastValue.flags
+ and Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0).isTrue()
+ assertThat(optionsCaptor.lastValue.launchedFromBubble).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.isApplyActivityFlagsForBubbles).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.taskAlwaysOnTop).isTrue()
}
@Test
+ fun onInitialized_appBubble_pendingIntent() {
+ val b = createAppBubble(usePendingIntent = true)
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isApp).isTrue()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ val intentCaptor = argumentCaptor<Intent>()
+ val optionsCaptor = argumentCaptor<ActivityOptions>()
+
+ assertThat(b.isPendingIntentActive).isFalse() // chat only triggers setting it active
+ verify(taskViewController).startActivity(any(),
+ any(),
+ intentCaptor.capture(),
+ optionsCaptor.capture(),
+ any())
+
+ assertThat((intentCaptor.lastValue.flags
+ and Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0).isTrue()
+ assertThat(optionsCaptor.lastValue.launchedFromBubble).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.isApplyActivityFlagsForBubbles).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.taskAlwaysOnTop).isTrue()
+ }
+
+ @Test
+ fun onInitialized_noteBubble() {
+ val b = createNoteBubble()
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isNote).isTrue()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ val intentCaptor = argumentCaptor<Intent>()
+ val optionsCaptor = argumentCaptor<ActivityOptions>()
+
+ assertThat(b.isPendingIntentActive).isFalse() // chat only triggers setting it active
+ verify(taskViewController).startActivity(any(),
+ any(),
+ intentCaptor.capture(),
+ optionsCaptor.capture(),
+ any())
+
+ assertThat((intentCaptor.lastValue.flags
+ and Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0).isTrue()
+ assertThat(optionsCaptor.lastValue.launchedFromBubble).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.isApplyActivityFlagsForBubbles).isFalse() // chat only
+ assertThat(optionsCaptor.lastValue.taskAlwaysOnTop).isTrue()
+ }
+
+
+ @Test
fun onInitialized_preparingTransition() {
val b = createAppBubble()
bubbleTaskViewListener.setBubble(b)
@@ -416,13 +550,24 @@
assertThat(isNew).isTrue()
}
- private fun createAppBubble(): Bubble {
+ private fun createAppBubble(usePendingIntent: Boolean = false): Bubble {
val target = Intent(context, TestActivity::class.java)
target.setPackage(context.packageName)
+ if (usePendingIntent) {
+ // Robolectric doesn't seem to play nice with PendingIntents, have to mock it.
+ val pendingIntent = mock<PendingIntent>()
+ whenever(pendingIntent.intent).thenReturn(target)
+ return Bubble.createAppBubble(pendingIntent, mock<UserHandle>(),
+ mainExecutor, bgExecutor)
+ }
return Bubble.createAppBubble(target, mock<UserHandle>(), mock<Icon>(),
mainExecutor, bgExecutor)
}
+ private fun createShortcutBubble(shortcutInfo: ShortcutInfo): Bubble {
+ return Bubble.createShortcutBubble(shortcutInfo, mainExecutor, bgExecutor)
+ }
+
private fun createNoteBubble(): Bubble {
val target = Intent(context, TestActivity::class.java)
target.setPackage(context.packageName)
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index 5444c26..b4d594f 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Verdeelde skerm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Sweef"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Verander aspekverhouding"</string>
<string name="close_text" msgid="4986518933445178928">"Maak toe"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Maak kieslys toe"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Maak kieslys oop"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimeer skerm"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Verander grootte"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App kan nie hierheen geskuif word nie"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Verander grootte van linkerkantse venster"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Verander grootte van regterkantse venster"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimeer of stel venstergrootte terug"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Gaan na deelskermmodus"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Gaan na werkskermvenstermodus"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Verander grootte van linkerkantse venster"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Verander grootte van regterkantse venster"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimeer of stel venstergrootte terug"</string>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index f3bc29d..9ec8001 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"የተከፈለ ማያ ገፅ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ተጨማሪ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ተንሳፋፊ"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"ምጥጥነ ገፅታ ለውጥ"</string>
<string name="close_text" msgid="4986518933445178928">"ዝጋ"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"ምናሌ ዝጋ"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ምናሌን ክፈት"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"የማያ ገጹ መጠን አሳድግ"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"መጠን ቀይር"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"መተግበሪያ ወደዚህ መንቀሳቀስ አይችልም"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"የመተግበሪያ መስኮትን ወደ ግራ መጠን ቀይር"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"የመተግበሪያ መስኮትን ወደ ቀኝ መጠን ቀይር"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"የመስኮት መጠንን አሳድግ ወይም ወደነበረበት መልስ"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ወደ የተከፈለ ማያ ገፅ ሁነታ ግባ"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ወደ የዴስክቶፕ መስኮት ሁነታ ግባ"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"መስኮትን ወደ ግራ መጠን ቀይር"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"መስኮትን ወደ ቀኝ መጠን ቀይር"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"የመስኮት መጠንን አሳድግ ወይም ወደነበረበት መልስ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 60f27cf..1680922 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"العرض المخصّص للكمبيوتر المكتبي"</string>
<string name="split_screen_text" msgid="1396336058129570886">"تقسيم الشاشة"</string>
<string name="more_button_text" msgid="3655388105592893530">"المزيد"</string>
<string name="float_button_text" msgid="9221657008391364581">"نافذة عائمة"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"تغيير نسبة العرض إلى الارتفاع"</string>
<string name="close_text" msgid="4986518933445178928">"إغلاق"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"إغلاق القائمة"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"فتح القائمة"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (العرض المخصّص للكمبيوتر المكتبي)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"تكبير الشاشة إلى أقصى حدّ"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"تغيير الحجم"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"لا يمكن نقل التطبيق إلى هنا"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"تغيير حجم نافذة التطبيق بمحاذاتها إلى اليمين"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"تغيير حجم نافذة التطبيق بمحاذاتها إلى اليسار"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"تكبير حجم النافذة أو استعادته"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"تفعيل \"وضع تقسيم الشاشة\""</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"تفعيل وضع عرض المحتوى في النافذة الحالية على سطح المكتب"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"فتح القائمة"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"تفعيل \"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g>\""</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"تغيير حجم النافذة بمحاذاتها إلى اليمين"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"تغيير حجم النافذة بمحاذاتها إلى اليسار"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"تكبير حجم النافذة أو استعادته"</string>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index 0f43347..05860c2 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"বিভাজিত স্ক্ৰীন"</string>
<string name="more_button_text" msgid="3655388105592893530">"অধিক"</string>
<string name="float_button_text" msgid="9221657008391364581">"ওপঙা"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"আকাৰৰ অনুপাত সলনি কৰক"</string>
<string name="close_text" msgid="4986518933445178928">"বন্ধ কৰক"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"মেনু বন্ধ কৰক"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"মেনু খোলক"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"স্ক্ৰীন মেক্সিমাইজ কৰক"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"আকাৰ সলনি কৰক"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ইয়ালৈ এপ্টো আনিব নোৱাৰি"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"বাওঁফালে এপ্ ৱিণ্ড’ৰ আকাৰ সলনি কৰক"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"সোঁফালে এপ্ ৱিণ্ড’ৰ আকাৰ সলনি কৰক"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ৱিণ্ড’ৰ আকাৰ মেক্সিমাইজ বা পুনঃস্থাপন কৰক"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"বিভাজিত-স্ক্ৰীন ম’ড দিয়ক"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ডেস্কটপ ৱিণ্ড’ইং ম’ড দিয়ক"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"সোঁফাললৈ ৱিণ্ড’ৰ আকাৰ সলনি কৰক"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"বাওঁফাললৈ ৱিণ্ড’ৰ আকাৰ সলনি কৰক"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ৱিণ্ড’ৰ আকাৰ মেক্সিমাইজ বা পুনঃস্থাপন কৰক"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index aced354..ea64749 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ardı"</string>
<string name="float_button_text" msgid="9221657008391364581">"Üzən pəncərə"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Tərəflər nisbətini dəyişin"</string>
<string name="close_text" msgid="4986518933445178928">"Bağlayın"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Menyunu bağlayın"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menyunu açın"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranı maksimum böyüdün"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Ölçüsünü dəyişin"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Tətbiqi bura köçürmək mümkün deyil"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Tətbiq pəncərəsinin ölçüsünü sola dəyişin"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Tətbiq pəncərəsinin ölçüsünü sağa dəyişin"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Pəncərə ölçüsünü artırın və ya bərpa edin"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Bölünmüş ekran rejiminə daxil olun"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Masaüstü pəncərə rejiminə daxil olun"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Pəncərə ölçüsünü sola dəyişin"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Pəncərə ölçüsünü sağa dəyişin"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Pəncərə ölçüsünü artırın və ya bərpa edin"</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 b07c612..deec04f 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Prikaz za računare"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Podeljeni ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Još"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plutajuće"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Promeni razmeru"</string>
<string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite meni"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvorite meni"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (prikaz za računare)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Povećaj ekran"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Promeni veličinu"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacija ne može da se premesti ovde"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Promenite veličinu prozora aplikacije nalevo"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Promenite veličinu prozora aplikacije nadesno"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Uvećajte ili vratite veličinu prozora"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Uđite u režim podeljenog ekrana"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Uđite u režim prozora na računaru"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Otvorite Meni"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Unesite <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Promenite veličinu prozora nalevo"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Promenite veličinu prozora nadesno"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Uvećajte ili vratite veličinu prozora"</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index 4c2950b..d26c37b 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Версія для камп’ютараў"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Падзяліць экран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Яшчэ"</string>
<string name="float_button_text" msgid="9221657008391364581">"Зрабіць рухомым акном"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Змяніць суадносіны бакоў"</string>
<string name="close_text" msgid="4986518933445178928">"Закрыць"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Закрыць меню"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Адкрыць меню"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (версія для камп’ютараў)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Разгарнуць на ўвесь экран"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Змяніць памер"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Нельга перамясціць сюды праграму"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Змяніць памер акна (злева)"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Змяніць памер акна (справа)"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Разгарнуць акно ці аднавіць яго памер"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Уключыць рэжым падзеленага экрана"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Уключыць рэжым вокнаў працоўнага стала"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Адкрыць меню"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Увесці \"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g>\""</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Змяніць памер акна і перамясціць да левага краю"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Змяніць памер акна і перамясціць да правага краю"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Разгарнуць акно ці аднавіць яго памер"</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index fcc4d83..0bb5960 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Разделяне на екрана"</string>
<string name="more_button_text" msgid="3655388105592893530">"Още"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плаващо"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Промяна на съотношението"</string>
<string name="close_text" msgid="4986518933445178928">"Затваряне"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Затваряне на менюто"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Отваряне на менюто"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Увеличаване на екрана"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Преоразмеряване"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Приложението не може да бъде преместено тук"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Преоразмеряване на прозореца на приложението наляво"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Преоразмеряване на прозореца на приложението надясно"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Увеличаване или възстановяване на размера на прозореца"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Активиране на режима за разделен екран"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Активиране на режима за настолни компютри"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Преоразмеряване на прозореца наляво"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Преоразмеряване на прозореца надясно"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Увеличаване или възстановяване на размера на прозореца"</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index b2c435e..ae63e04 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"স্প্লিট স্ক্রিন"</string>
<string name="more_button_text" msgid="3655388105592893530">"আরও"</string>
<string name="float_button_text" msgid="9221657008391364581">"ফ্লোট"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"অ্যাস্পেক্ট রেশিও পরিবর্তন করুন"</string>
<string name="close_text" msgid="4986518933445178928">"বন্ধ করুন"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"\'মেনু\' বন্ধ করুন"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"মেনু খুলুন"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"স্ক্রিন বড় করুন"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ছোট বড় করুন"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"অ্যাপটি এখানে সরানো যাবে না"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"বাঁদিকে অ্যাপ উইন্ডো রিসাইজ করুন"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ডানদিকে অ্যাপ উইন্ডো রিসাইজ করুন"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"উইন্ডো সাইজ বড় বা রিস্টোর করুন"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"স্প্লিট স্ক্রিন মোডে প্রবেশ করুন"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ডেস্কটপ উইন্ডোইং মোডে প্রবেশ করুন"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"বাঁদিকে উইন্ডো রিসাইজ করুন"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ডানদিকে উইন্ডো রিসাইজ করুন"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"উইন্ডো সাইজ বড় বা রিস্টোর করুন"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 8c1619c..b7c76b5 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Prikaz na računalu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Podijeljeni ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Više"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebdeći"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Promjena formata slike"</string>
<string name="close_text" msgid="4986518933445178928">"Zatvaranje"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zatvaranje menija"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvaranje menija"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (prikaz na računalu)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimiziraj ekran"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Promijeni veličinu"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Ne možete premjestiti aplikaciju ovdje"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Promjena veličine prozora aplikacije lijevo"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Promjena veličine prozora aplikacije desno"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimiziranje ili vraćanje veličine prozora"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Pokretanje načina rada podijeljenog ekrana"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Pokretanje načina rada s prozorima na radnoj površini"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Otvorite izbornik"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Unesite <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Promjena veličine prozora i poravnanje lijevo"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Promjena veličine prozora i poravnanje desno"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimiziranje ili vraćanje veličine prozora"</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 37802f4..80dd380 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Més"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotant"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Canvia la relació d\'aspecte"</string>
<string name="close_text" msgid="4986518933445178928">"Tanca"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Tanca el menú"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Obre el menú"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximitza la pantalla"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Canvia la mida"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"L\'aplicació no es pot moure aquí"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Canvia la mida de la finestra de l\'aplicació a l\'esquerra"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Canvia la mida de la finestra de l\'aplicació a la dreta"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximitza o restaura la mida de la finestra"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Entra al mode de pantalla dividida"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Entra al mode d\'enfinestrament a l\'escriptori"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Canvia la mida de la finestra a l\'esquerra"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Canvia la mida de la finestra a la dreta"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximitza o restaura la mida de la finestra"</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index c4514eb..e47d1f6 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Zobrazení na počítači"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Rozdělená obrazovka"</string>
<string name="more_button_text" msgid="3655388105592893530">"Více"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plovoucí"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Změnit poměr stran"</string>
<string name="close_text" msgid="4986518933445178928">"Zavřít"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zavřít nabídku"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otevřít nabídku"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (zobrazení na počítači)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximalizovat obrazovku"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Změnit velikost"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikaci sem nelze přesunout"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Změnit velikost okna aplikace vlevo"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Změnit velikost okna aplikace vpravo"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximalizovat nebo obnovit velikost okna"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Přechod do režimu rozdělené obrazovky"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Přejít do režimu okenního systému pro počítače"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Otevřít nabídku"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Přejít do režimu <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Přichytit okno vlevo"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Přichytit okno vpravo"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximalizovat nebo obnovit velikost okna"</string>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index e662a16..c465ce3 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Opdelt skærm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mere"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svævende"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Skift billedformat"</string>
<string name="close_text" msgid="4986518933445178928">"Luk"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Luk menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Åbn menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimér skærm"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Tilpas størrelse"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Apps kan ikke flyttes hertil"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Juster størrelsen på appvinduet til venstre"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Juster størrelsen på appvinduet til højre"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimer eller gendan vinduesstørrelse"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Åbn opdelt skærm"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Åbn tilstanden for vinduer på computeren"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Juster størrelsen på vinduet til venstre"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Juster størrelsen på vinduet til højre"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimer eller gendan vinduesstørrelse"</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 7b21719..567dd7a 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Splitscreen"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mehr"</string>
<string name="float_button_text" msgid="9221657008391364581">"Frei schwebend"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Seitenverhältnis ändern"</string>
<string name="close_text" msgid="4986518933445178928">"Schließen"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Menü schließen"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menü öffnen"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Bildschirm maximieren"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Größe ändern"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Die App kann nicht hierher verschoben werden"</string>
@@ -142,13 +144,15 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Wiederherstellen"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Links andocken"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Rechts andocken"</string>
- <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Größe des linken App-Fensters anpassen"</string>
- <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Größe des rechten App-Fensters anpassen"</string>
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Größe des App-Fensters links anpassen"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Größe des App-Fensters rechts anpassen"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Fenstergröße maximieren oder wiederherstellen"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Splitscreen-Modus aktivieren"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Desktop-Fenstermodus aktivieren"</string>
- <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Fenstergröße links anpassen"</string>
- <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Fenstergröße rechts anpassen"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Fenstergröße nach links anpassen"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Fenstergröße nach rechts anpassen"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Fenstergröße maximieren oder wiederherstellen"</string>
<string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Fenstergröße maximieren oder wiederherstellen"</string>
<string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"App-Fenster minimieren"</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index eb45a31..489a4ce 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Διαχωρισμός οθόνης"</string>
<string name="more_button_text" msgid="3655388105592893530">"Περισσότερα"</string>
<string name="float_button_text" msgid="9221657008391364581">"Κινούμενο"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Αλλαγή λόγου διαστάσεων"</string>
<string name="close_text" msgid="4986518933445178928">"Κλείσιμο"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Κλείσιμο μενού"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Άνοιγμα μενού"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Μεγιστοποίηση οθόνης"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Αλλαγή μεγέθους"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Δεν είναι δυνατή η μετακίνηση της εφαρμογής εδώ"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Αλλαγή μεγέθους παραθύρου εφαρμογής αριστερά"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Αλλαγή μεγέθους παραθύρου εφαρμογής δεξιά"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Μεγιστοποίηση ή επαναφορά μεγέθους παραθύρου"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Είσοδος στη λειτουργία διαχωρισμού οθόνης"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Είσοδος στη λειτουργία προσαρμογής σε παράθυρο υπολογιστή"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Αλλαγή μεγέθους παραθύρου προς τα αριστερά"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Αλλαγή μεγέθους παραθύρου προς τα δεξιά"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Μεγιστοποίηση ή επαναφορά μεγέθους παραθύρου"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index 8dc27da..1a3d422 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Change aspect ratio"</string>
<string name="close_text" msgid="4986518933445178928">"Close"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Resize"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Resize app window left"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Resize app window right"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximise or restore window size"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Enter split-screen mode"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Enter desktop windowing mode"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Resize window to left"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Resize window to right"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximise or restore window size"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index 20d141e..e552f95 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Desktop View"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Change aspect ratio"</string>
<string name="close_text" msgid="4986518933445178928">"Close"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Close Menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open Menu"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (Desktop View)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximize Screen"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Resize"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Resize app window left"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Resize app window right"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximize or restore window size"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Enter split screen mode"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Enter desktop windowing mode"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Open Menu"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Enter <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Resize window to left"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Resize window to right"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximize or restore window size"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index 8dc27da..1a3d422 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Change aspect ratio"</string>
<string name="close_text" msgid="4986518933445178928">"Close"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Resize"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Resize app window left"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Resize app window right"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximise or restore window size"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Enter split-screen mode"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Enter desktop windowing mode"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Resize window to left"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Resize window to right"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximise or restore window size"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index 8dc27da..1a3d422 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Change aspect ratio"</string>
<string name="close_text" msgid="4986518933445178928">"Close"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Resize"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Resize app window left"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Resize app window right"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximise or restore window size"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Enter split-screen mode"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Enter desktop windowing mode"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Resize window to left"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Resize window to right"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximise or restore window size"</string>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 24c2bed..93aa1b6 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Más"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Cambiar relación de aspecto"</string>
<string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir el menú"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Cambiar el tamaño"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"No se puede mover la app aquí"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ajustar el tamaño de la ventana de la app hacia la izquierda"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ajustar el tamaño de la ventana de la app hacia la derecha"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizar o restablecer el tamaño de la ventana"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Activar el modo de pantalla dividida"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Ingresar al modo ventana de computadora"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ajustar el tamaño de la ventana hacia la izquierda"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ajustar el tamaño de la ventana hacia la derecha"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizar o restablecer el tamaño de la ventana"</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index dd9635d..27c5b80 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Más"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Cambiar relación de aspecto"</string>
<string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir menú"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Cambiar tamaño"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"La aplicación no se puede mover aquí"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Cambiar tamaño de la ventana de la aplicación izquierda"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Cambiar tamaño de la ventana de la aplicación derecha"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizar o restaurar tamaño de la ventana"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Activar modo Pantalla dividida"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Activar modo Escritorio basado en ventanas"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Cambiar tamaño de la ventana a la izquierda"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Cambiar tamaño de la ventana a la derecha"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizar o restaurar tamaño de la ventana"</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 56b5f0b..c8ab83e 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Jagatud ekraanikuva"</string>
<string name="more_button_text" msgid="3655388105592893530">"Rohkem"</string>
<string name="float_button_text" msgid="9221657008391364581">"Hõljuv"</string>
@@ -132,11 +133,12 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Kuvasuhte muutmine"</string>
<string name="close_text" msgid="4986518933445178928">"Sule"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Sule menüü"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ava menüü"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Kuva täisekraanil"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Suuruse muutmine"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Rakendust ei saa siia teisaldada"</string>
- <string name="desktop_mode_maximize_menu_immersive_button_text" msgid="559492223133829481">"Kaasahaarav"</string>
+ <string name="desktop_mode_maximize_menu_immersive_button_text" msgid="559492223133829481">"Mahuta"</string>
<string name="desktop_mode_maximize_menu_immersive_restore_button_text" msgid="4900114367354709257">"Taasta"</string>
<string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimeeri"</string>
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Taasta"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Rakenduse akna suuruse muutmine vasakul"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Rakenduse akna suuruse muutmine paremal"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Akna suuruse maksimeerimine või taastamine"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Poolitatud ekraani režiimi sisenemine"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Töölaua akende kuvamise režiimi sisenemine"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Akna suuruse muutmine, vasakule"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Akna suuruse muutmine, paremale"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Akna suuruse maksimeerimine või taastamine"</string>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 9898af0..abd92ab 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Pantaila zatitzea"</string>
<string name="more_button_text" msgid="3655388105592893530">"Gehiago"</string>
<string name="float_button_text" msgid="9221657008391364581">"Leiho gainerakorra"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Aldatu aspektu-erlazioa"</string>
<string name="close_text" msgid="4986518933445178928">"Itxi"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Itxi menua"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ireki menua"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Handitu pantaila"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Aldatu tamaina"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikazioa ezin da hona ekarri"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Aldatu aplikazioaren leihoaren tamaina eta eraman ezkerrera"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Aldatu aplikazioaren leihoaren tamaina eta eraman eskuinera"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizatu edo leheneratu leihoaren tamaina"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Sartu pantaila zatituaren moduan"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Sartu ordenagailuan leihoak erabiltzeko moduan"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Aldatu leihoaren tamaina eta eraman ezkerrera"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Aldatu leihoaren tamaina eta eraman eskuinera"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizatu edo leheneratu leihoaren tamaina"</string>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 22ef61f..651635a 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"صفحهٔ دونیمه"</string>
<string name="more_button_text" msgid="3655388105592893530">"بیشتر"</string>
<string name="float_button_text" msgid="9221657008391364581">"شناور"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"تغییر نسبت ابعادی"</string>
<string name="close_text" msgid="4986518933445178928">"بستن"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"بستن منو"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"باز کردن منو"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"بزرگ کردن صفحه"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"تغییر اندازه"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"برنامه را نمیتوان به اینجا منتقل کرد"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"تغییر اندازه پنجره برنامه در چپ"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"تغییر اندازه پنجره برنامه در راست"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"بیشینهسازی یا بازیابی اندازه پنجره"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ورود به حالت صفحه تقسیمشده"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"رفتن به حالت پردازش پنجرهای میز کار"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"تغییر اندازه پنجره به چپ"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"تغییر اندازه پنجره به راست"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"بیشینهسازی یا بازیابی اندازه پنجره"</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index b23c833..47e9ea3 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Jaettu näyttö"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lisää"</string>
<string name="float_button_text" msgid="9221657008391364581">"Kelluva ikkuna"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Vaihda kuvasuhdetta"</string>
<string name="close_text" msgid="4986518933445178928">"Sulje"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Sulje valikko"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Avaa valikko"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Suurenna näyttö"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Muuta kokoa"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Sovellusta ei voi siirtää tänne"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Muuta vasemmanpuoleisen sovellusikkunan kokoa"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Muuta oikeanpuoleisen sovellusikkunan kokoa"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Suurenna ikkuna tai palauta ikkunan koko"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Avaa kahtia jaettu näyttö"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Siirry työpöydän ikkunointitilaan"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Muuta vasemmanpuoleisen ikkunan kokoa"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Muuta vasemmanpuoleisen ikkunan kokoa"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Suurenna ikkuna tai palauta ikkunan koko"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 34b5b0a..dc2025f 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Affichage sur un ordinateur de bureau"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Écran divisé"</string>
<string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flottant"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Modifier les proportions"</string>
<string name="close_text" msgid="4986518933445178928">"Fermer"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ouvrir le menu"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (affichage sur un ordinateur de bureau)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Agrandir l\'écran"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Redimensionner"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Impossible de déplacer l\'appli ici"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionner la fenêtre de l\'appli à gauche"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionner la fenêtre de l\'appli à droite"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Agrandir ou restaurer la taille de la fenêtre"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Entrer en mode Écran divisé"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Entrer en mode Fenêtrage bureau"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Ouvrir le menu"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Entrez <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionner la fenêtre vers la gauche"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionner la fenêtre vers la droite"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Agrandir ou restaurer la taille de la fenêtre"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index be41bba..038a90d 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string>
<string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flottante"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Modifier le format"</string>
<string name="close_text" msgid="4986518933445178928">"Fermer"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ouvrir le menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Mettre en plein écran"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Redimensionner"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Impossible de déplacer l\'appli ici"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionner la fenêtre de l\'appli vers la gauche"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionner la fenêtre de l\'appli vers la droite"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Agrandir ou restaurer la taille de la fenêtre"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Passer en mode Écran partagé"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Activer le mode fenêtrage du bureau"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionner la fenêtre vers la gauche"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionner la fenêtre vers la droite"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Agrandir ou restaurer la taille de la fenêtre"</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index aa2f639..a2a6b3e 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Máis"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Cambiar a proporción"</string>
<string name="close_text" msgid="4986518933445178928">"Pechar"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Pechar o menú"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir o menú"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Cambiar tamaño"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Non se pode mover aquí a aplicación"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Axustar o tamaño da ventá da aplicación á esquerda"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Axustar o tamaño da ventá da aplicación á dereita"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizar ou restaurar o tamaño da ventá"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Entrar no modo de pantalla dividida"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Entrar no modo de ventás do ordenador"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Axustar o tamaño da ventá á esquerda"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Axustar o tamaño da ventá á dereita"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizar ou restaurar o tamaño da ventá"</string>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index dcd5738..196784b 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"ડેસ્કટૉપ વ્યૂ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"સ્ક્રીનને વિભાજિત કરો"</string>
<string name="more_button_text" msgid="3655388105592893530">"વધુ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ફ્લોટિંગ વિન્ડો"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"સાપેક્ષ ગુણોત્તર બદલો"</string>
<string name="close_text" msgid="4986518933445178928">"બંધ કરો"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"મેનૂ બંધ કરો"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"મેનૂ ખોલો"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (ડેસ્કટૉપ વ્યૂ)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"સ્ક્રીન કરો મોટી કરો"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"કદ બદલો"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ઍપ અહીં ખસેડી શકાતી નથી"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ડાબી બાજુથી ઍપની વિન્ડોનું કદ બદલો"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"જમણી બાજુથી ઍપની વિન્ડોનું કદ બદલો"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"વિન્ડોનું કદ મહત્તમ કરો અથવા રિસ્ટોર કરો"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"સ્ક્રીન-વિભાજન મોડ દાખલ કરો"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ડેસ્કટૉપ વિન્ડો મોડ દાખલ કરો"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"મેનૂ ખોલો"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g> દાખલ કરો"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ડાબી બાજુ વિન્ડોનું કદ બદલો"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"જમણી બાજુ વિન્ડોનું કદ બદલો"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"વિન્ડોનું કદ મહત્તમ કરો અથવા રિસ્ટોર કરો"</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 4bf2d92..f1f2a0a 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन मोड"</string>
<string name="more_button_text" msgid="3655388105592893530">"ज़्यादा देखें"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ़्लोट"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) बदलें"</string>
<string name="close_text" msgid="4986518933445178928">"बंद करें"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"मेन्यू बंद करें"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"मेन्यू खोलें"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रीन को बड़ा करें"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"साइज़ बदलें"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ऐप्लिकेशन को यहां मूव नहीं किया जा सकता"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ऐप्लिकेशन विंडो का साइज़ बाईं ओर से बदलें"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ऐप्लिकेशन विंडो का साइज़ दाईं ओर से बदलें"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"विंडो को बड़ा करें या उसका साइज़ पहले जैसा करें"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"स्प्लिट स्क्रीन मोड में चालू करें"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"डेस्कटॉप विंडो मोड में जाएं"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"विंडो का साइज़ बाईं ओर से बदलें"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"विंडो का साइज़ दाईं ओर से बढ़ाएं"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"विंडो को बड़ा करें या उसका साइज़ पहले जैसा करें"</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 157822c..b1187dc 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Prikaz na računalu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Razdvojeni zaslon"</string>
<string name="more_button_text" msgid="3655388105592893530">"Više"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plutajući"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Promijeni omjer slike"</string>
<string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite izbornik"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvaranje izbornika"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (prikaz na računalu)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimalno povećaj zaslon"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Promijeni veličinu"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacija se ne može premjestiti ovdje"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Promijeni veličinu prozora aplikacije ulijevo"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Promijeni veličinu prozora aplikacije udesno"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimiziraj ili vrati veličinu prozora"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Pokreni način podijeljenog zaslona"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Pokreni način prikaza u prozorima na računalu"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Otvorite izbornik"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Unesite <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Promijeni veličinu prozora ulijevo"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Promijeni veličinu prozora udesno"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimiziraj ili vrati veličinu prozora"</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 546a465..5d52c48 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Osztott képernyő"</string>
<string name="more_button_text" msgid="3655388105592893530">"Továbbiak"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebegő"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Méretarány módosítása"</string>
<string name="close_text" msgid="4986518933445178928">"Bezárás"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Menü bezárása"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menü megnyitása"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Képernyő méretének maximalizálása"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Átméretezés"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Az alkalmazás nem helyezhető át ide"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Alkalmazásablak átméretezése balra"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Alkalmazásablak átméretezése jobbra"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Ablak teljes méretre állítása vagy visszaállítása"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Belépés osztott képernyős módba"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Asztali ablakkezelési mód indítása"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ablak átméretezése balra"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ablak átméretezése jobbra"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Ablak teljes méretre állítása vagy visszaállítása"</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index 39a395f..b7b4422 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Տրոհված էկրան"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ավելին"</string>
<string name="float_button_text" msgid="9221657008391364581">"Լողացող պատուհան"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Փոխել կողմերի հարաբերակցությունը"</string>
<string name="close_text" msgid="4986518933445178928">"Փակել"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Փակել ընտրացանկը"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Բացել ընտրացանկը"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ծավալել էկրանը"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Փոխել չափը"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Հավելվածը հնարավոր չէ տեղափոխել այստեղ"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ձգել հավելվածի պատուհանը դեպի ձախ"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ձգել հավելվածի պատուհանը դեպի աջ"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Ծավալել կամ վերականգնել պատուհանի չափսը"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Մտնել էկրանի տրոհման ռեժիմ"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Մտնել համակարգչի ռեժիմ"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ձգել պատուհանը դեպի ձախ"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ձգել պատուհանը դեպի աջ"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Ծավալել կամ վերականգնել պատուհանի չափսը"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 09ce525..a3ed7c3 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Layar Terpisah"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lainnya"</string>
<string name="float_button_text" msgid="9221657008391364581">"Mengambang"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Ubah rasio aspek"</string>
<string name="close_text" msgid="4986518933445178928">"Tutup"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Buka Menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Perbesar Layar"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Ubah ukuran"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikasi tidak dapat dipindahkan ke sini"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ubah ukuran jendela aplikasi ke kiri"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ubah ukuran jendela aplikasi ke kanan"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimalkan atau pulihkan ukuran jendela"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Masuk ke mode layar terpisah"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Masuk ke mode windowing desktop"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ubah ukuran jendela ke kiri"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ubah ukuran jendela ke kanan"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimalkan atau pulihkan ukuran jendela"</string>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 61c1d0e..e8ecad1 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Skjáskipting"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meira"</string>
<string name="float_button_text" msgid="9221657008391364581">"Reikult"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Breyta myndhlutfalli"</string>
<string name="close_text" msgid="4986518933445178928">"Loka"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Loka valmynd"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Opna valmynd"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Stækka skjá"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Breyta stærð"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Ekki er hægt að færa forritið hingað"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Breyta stærð forritsglugga til vinstri"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Breyta stærð forritsglugga til hægri"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Hámarka eða endurheimta stærð glugga"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Skipta skjánum"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Opna gluggastillingu í tölvu"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Breyta stærð glugga til vinstri"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Breyta stærð glugga til hægri"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Hámarka eða endurheimta stærð glugga"</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index fab259e..630e9ee 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Schermo diviso"</string>
<string name="more_button_text" msgid="3655388105592893530">"Altro"</string>
<string name="float_button_text" msgid="9221657008391364581">"Mobile"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Cambia proporzioni"</string>
<string name="close_text" msgid="4986518933445178928">"Chiudi"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Chiudi il menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Apri il menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Massimizza schermo"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Ridimensiona"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Impossibile spostare l\'app qui"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ridimensiona la finestra dell\'app a sinistra"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ridimensiona la finestra dell\'app a destra"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Ingrandisci o ripristina le dimensioni della finestra"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Attiva la modalità schermo diviso"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Attiva la modalità finestre del desktop"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ridimensiona la finestra a sinistra"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ridimensiona la finestra a destra"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Ingrandisci o ripristina le dimensioni della finestra"</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index b164b11..102d646 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"מסך מפוצל"</string>
<string name="more_button_text" msgid="3655388105592893530">"עוד"</string>
<string name="float_button_text" msgid="9221657008391364581">"בלונים"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"שינוי יחס הגובה-רוחב"</string>
<string name="close_text" msgid="4986518933445178928">"סגירה"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"סגירת התפריט"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"פתיחת התפריט"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"הגדלת המסך"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"שינוי הגודל"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"לא ניתן להעביר את האפליקציה לכאן"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"שינוי הגודל של חלון האפליקציה שמשמאל"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"שינוי הגודל של חלון האפליקציה שמימין"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"שחזור של גודל החלון או הגדלת החלון"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"כניסה למצב מסך מפוצל"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"כניסה למצב שינוי הגודל של החלונות בממשק המחשב"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"שינוי גודל החלון שמשמאל"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"שינוי גודל החלון שמימין"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"שחזור של גודל החלון או הגדלת החלון"</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 3fe2a51..ac0df9c 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"デスクトップ ビュー"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分割画面"</string>
<string name="more_button_text" msgid="3655388105592893530">"その他"</string>
<string name="float_button_text" msgid="9221657008391364581">"フローティング"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"アスペクト比を変更"</string>
<string name="close_text" msgid="4986518933445178928">"閉じる"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"メニューを閉じる"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"メニューを開く"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g>(デスクトップ ビュー)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"画面の最大化"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"サイズ変更"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"アプリはここに移動できません"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"アプリ ウィンドウを左側にサイズ変更する"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"アプリ ウィンドウを右側にサイズ変更する"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ウィンドウを最大化する、またはウィンドウを元のサイズに戻す"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"分割画面モードに切り替える"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"デスクトップ ウィンドウ モードに切り替える"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"メニューを開く"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g>に切り替え"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ウィンドウを左側にサイズ変更する"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ウィンドウを右側にサイズ変更する"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ウィンドウを最大化する、またはウィンドウを元のサイズに戻す"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 1be19af..84fab6f 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"დესკტოპის ხედი"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ეკრანის გაყოფა"</string>
<string name="more_button_text" msgid="3655388105592893530">"სხვა"</string>
<string name="float_button_text" msgid="9221657008391364581">"ფარფატი"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"თანაფარდობის შეცვლა"</string>
<string name="close_text" msgid="4986518933445178928">"დახურვა"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"მენიუს დახურვა"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"მენიუს გახსნა"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (დესკტოპის ხედი)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"აპლიკაციის გაშლა სრულ ეკრანზე"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ზომის შეცვლა"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"აპის აქ გადატანა შეუძლებელია"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"აპის მარცხენა ფანჯრის ზომის შეცვლა"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"აპის მარჯვენა ფანჯრის ზომის შეცვლა"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ფანჯრის მაქსიმალურ ზომამდე გაზრდა ან აღდგენა"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"გაყოფილი ეკრანის რეჟიმში შესვლა"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"დესკტოპის ფანჯრის რეჟიმში შესვლა"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"მენიუს გახსნა"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"შეიყვანეთ <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ფანჯრის ზომის შეცვლა მარცხნივ"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ფანჯრის ზომის შეცვლა მარჯვნივ"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ფანჯრის მაქსიმალურ ზომამდე გაზრდა ან აღდგენა"</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index 5bd8519..31a0153 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлу"</string>
<string name="more_button_text" msgid="3655388105592893530">"Қосымша"</string>
<string name="float_button_text" msgid="9221657008391364581">"Қалқыма"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Арақатынасты өзгерту"</string>
<string name="close_text" msgid="4986518933445178928">"Жабу"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Мәзірді жабу"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Мәзірді ашу"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Экранды ұлғайту"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Өлшемін өзгерту"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Қолданба бұл жерге қойылмайды."</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Қолданба терезесінің өлшемін сол жақтан өзгерту"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Қолданба терезесінің өлшемін оң жақтан өзгерту"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Терезе өлшемін ұлғайту не қалпына келтіру"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Экранды бөлу режиміне өту"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Жұмыс үстелінің терезе режиміне өту"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Терезе өлшемін сол жаққа өзгерту"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Терезе өлшемін оң жаққа өзгерту"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Терезе өлшемін ұлғайту не қалпына келтіру"</string>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index f511897..9a7db67 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"មុខងារបំបែកអេក្រង់"</string>
<string name="more_button_text" msgid="3655388105592893530">"ច្រើនទៀត"</string>
<string name="float_button_text" msgid="9221657008391364581">"អណ្ដែត"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"ប្ដូរសមាមាត្រ"</string>
<string name="close_text" msgid="4986518933445178928">"បិទ"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"បិទម៉ឺនុយ"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"បើកម៉ឺនុយ"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ពង្រីកអេក្រង់"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ប្ដូរទំហំ"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"មិនអាចផ្លាស់ទីកម្មវិធីមកទីនេះបានទេ"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ប្ដូរទំហំវិនដូកម្មវិធីទៅឆ្វេង"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ប្ដូរទំហំវិនដូកម្មវិធីទៅស្ដាំ"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ស្ដារ ឬបង្កើនទំហំវិនដូជាអតិបរមា"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ចូលទៅមុខងារបំបែកអេក្រង់"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ចូលទៅមុខងារវិនដូកុំព្យូទ័រ"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ប្ដូរទំហំវិនដូទៅឆ្វេង"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ប្ដូរទំហំវិនដូទៅស្ដាំ"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ស្ដារ ឬបង្កើនទំហំវិនដូជាអតិបរមា"</string>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 3bd5527..e9fa2cf 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
<string name="more_button_text" msgid="3655388105592893530">"ಇನ್ನಷ್ಟು"</string>
<string name="float_button_text" msgid="9221657008391364581">"ಫ್ಲೋಟ್"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"ದೃಶ್ಯಾನುಪಾತವನ್ನು ಬದಲಾಯಿಸಿ"</string>
<string name="close_text" msgid="4986518933445178928">"ಮುಚ್ಚಿ"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"ಮೆನು ಮುಚ್ಚಿ"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ಮೆನು ತೆರೆಯಿರಿ"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಮ್ಯಾಕ್ಸಿಮೈಸ್ ಮಾಡಿ"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ಮರುಗಾತ್ರಗೊಳಿಸಿ"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ಆ್ಯಪ್ ಅನ್ನು ಇಲ್ಲಿಗೆ ಸರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ಮರುಗಾತ್ರಗೊಳಿಸಿ ಆ್ಯಪ್ ವಿಂಡೋ ಎಡ"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ಮರುಗಾತ್ರಗೊಳಿಸಿ ಆ್ಯಪ್ ವಿಂಡೋ ಬಲ"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ವಿಂಡೋ ಗಾತ್ರವನ್ನು ಗರಿಷ್ಠಗೊಳಿಸಿ ಅಥವಾ ಮರುಸ್ಥಾಪಿಸಿ"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಮೋಡ್ಗೆ ಪ್ರವೇಶಿಸಿ"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ಡೆಸ್ಕ್ಟಾಪ್ ವಿಂಡೋಯಿಂಗ್ ಮೋಡ್ಗೆ ಪ್ರವೇಶಿಸಿ"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ಮರುಗಾತ್ರಗೊಳಿಸಿ ವಿಂಡೋವನ್ನು ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ಮರುಗಾತ್ರಗೊಳಿಸಿ ವಿಂಡೋವನ್ನು ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ವಿಂಡೋ ಗಾತ್ರವನ್ನು ಗರಿಷ್ಠಗೊಳಿಸಿ ಅಥವಾ ಮರುಸ್ಥಾಪಿಸಿ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 65add57..dcdbaba 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"데스크톱 뷰"</string>
<string name="split_screen_text" msgid="1396336058129570886">"화면 분할"</string>
<string name="more_button_text" msgid="3655388105592893530">"더보기"</string>
<string name="float_button_text" msgid="9221657008391364581">"플로팅"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"가로세로 비율 변경"</string>
<string name="close_text" msgid="4986518933445178928">"닫기"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"메뉴 닫기"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"메뉴 열기"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g>(데스크톱 뷰)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"화면 최대화"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"크기 조절"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"앱을 여기로 이동할 수 없음"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"앱 창 크기 왼쪽으로 조절"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"앱 창 크기 오른쪽으로 조절"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"창 최대화 또는 크기 복원"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"화면 분할 모드 시작"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"데스크톱 창 모드 시작"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"메뉴 열기"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g> 입력"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"창 크기 왼쪽으로 조절"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"창 크기 오른쪽으로 조절"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"창 최대화 또는 크기 복원"</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 96c2226..3716741 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлүү"</string>
<string name="more_button_text" msgid="3655388105592893530">"Дагы"</string>
<string name="float_button_text" msgid="9221657008391364581">"Калкыма"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Тараптардын катнашын өзгөртүү"</string>
<string name="close_text" msgid="4986518933445178928">"Жабуу"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Менюну жабуу"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Менюну ачуу"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Экранды чоңойтуу"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Өлчөмүн өзгөртүү"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Колдонмону бул жерге жылдырууга болбойт"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Колдонмонун терезесинин өлчөмүн солго өзгөртүү"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Колдонмонун терезесинин өлчөмүн оңго өзгөртүү"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Терезенин өлчөмүн чоңойтуу же калыбына келтирүү"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Экранды бөлүү режимине өтүү"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Иш тактанын терезелери режимине өтүү"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Терезенин өлчөмүн солго өзгөртүү"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Терезенин өлчөмүн оңго өзгөртүү"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Терезенин өлчөмүн чоңойтуу же калыбына келтирүү"</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 9337efc..a1d9d29 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"ແບ່ງໜ້າຈໍ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ເພີ່ມເຕີມ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ລອຍ"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"ປ່ຽນອັດຕາສ່ວນຮູບ"</string>
<string name="close_text" msgid="4986518933445178928">"ປິດ"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"ປິດເມນູ"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ເປີດເມນູ"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ປັບຈໍໃຫຍ່ສຸດ"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ປັບຂະໜາດ"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ບໍ່ສາມາດຍ້າຍແອັບມາບ່ອນນີ້ໄດ້"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ປັບຂະໜາດໜ້າຈໍແອັບໄປທາງຊ້າຍ"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ປັບຂະໜາດໜ້າຈໍແອັບໄປທາງຂວາ"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ຂະຫຍາຍ ຫຼື ຄືນຄ່າຂະໜາດໜ້າຈໍ"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ເຂົ້າສູ່ໂໝດແບ່ງໜ້າຈໍ"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ເຂົ້າສູ່ໂໝດໜ້າຈໍເດັສທັອບ"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ປັບຂະໜາດໜ້າຈໍໄປທາງຊ້າຍ"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ປັບຂະໜາດໜ້າຈໍໄປທາງຂວາ"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ຂະຫຍາຍ ຫຼື ຄືນຄ່າຂະໜາດໜ້າຈໍ"</string>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index ede2564..7ebd43d 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Rodinio versija staliniams kompiuteriams"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Išskaidyto ekrano režimas"</string>
<string name="more_button_text" msgid="3655388105592893530">"Daugiau"</string>
<string name="float_button_text" msgid="9221657008391364581">"Slankusis langas"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Keisti kraštinių santykį"</string>
<string name="close_text" msgid="4986518933445178928">"Uždaryti"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Uždaryti meniu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Atidaryti meniu"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ (rodinio versija staliniams kompiuteriams)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Išskleisti ekraną"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Pakeisti dydį"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Programos negalima perkelti čia"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Pakeisti programos lango dydį kairėje"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Pakeisti programos lango dydį dešinėje"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Padidinti arba atkurti lango dydį"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Išskaidyto ekrano režimo įjungimas"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Įjungti darbalaukio pateikimo lange režimą"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Atidaryti meniu"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Eiti į „<xliff:g id="WINDOWING_MODE">%1$s</xliff:g>“"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Pakeisti lango dydį kairėje"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Pakeisti lango dydį dešinėje"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Padidinti arba atkurti lango dydį"</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index 24a969b..3fcbbe2 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Sadalīt ekrānu"</string>
<string name="more_button_text" msgid="3655388105592893530">"Vairāk"</string>
<string name="float_button_text" msgid="9221657008391364581">"Peldošs"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Mainīt malu attiecību"</string>
<string name="close_text" msgid="4986518933445178928">"Aizvērt"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Aizvērt izvēlni"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Atvērt izvēlni"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimizēt ekrānu"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Mainīt lielumu"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Lietotni nevar pārvietot šeit."</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Mainīt lietotnes loga lielumu uz kreiso pusi"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Mainīt lietotnes loga lielumu uz labo pusi"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimizēt vai atjaunot loga lielumu"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Ieslēgt ekrāna sadalīšanas režīmu"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Ieslēgt darbvirsmas logu režīmu"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Mainīt loga lielumu uz kreiso pusi"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Mainīt loga lielumu uz labo pusi"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimizēt vai atjaunot loga lielumu"</string>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index f7177ac..76b62ec1 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Поделен екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Повеќе"</string>
<string name="float_button_text" msgid="9221657008391364581">"Лебдечко"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Промени го соодносот"</string>
<string name="close_text" msgid="4986518933445178928">"Затворете"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Затворете го менито"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Отвори го менито"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Максимизирај го екранот"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Промени ја гол."</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Апликацијата не може да се премести овде"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Променете ја големината на прозорецот на апликацијата одлево"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Променете ја големината на прозорецот на апликацијата оддесно"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Максимизирајте или вратете ја големината на прозорецот"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Влезете во „Режим на поделен екран“"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Влезете во „Режим со прозорци на работната површина“"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Променете ја големината на прозорецот налево"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Променете ја големината на прозорецот надесно"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Максимизирајте или вратете ја големината на прозорецот"</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 89215b6..d9d0cf9 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"സ്ക്രീൻ വിഭജനം"</string>
<string name="more_button_text" msgid="3655388105592893530">"കൂടുതൽ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ഫ്ലോട്ട്"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"വീക്ഷണ അനുപാതം മാറ്റുക"</string>
<string name="close_text" msgid="4986518933445178928">"അടയ്ക്കുക"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"മെനു അടയ്ക്കുക"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"മെനു തുറക്കുക"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"സ്ക്രീൻ വലുതാക്കുക"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"വലുപ്പം മാറ്റുക"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ആപ്പ് ഇവിടേക്ക് നീക്കാനാകില്ല"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ഇടത് ആപ്പ് വിൻഡോ വലുപ്പം മാറ്റുക"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"വലത് ആപ്പ് വിൻഡോ വലുപ്പം മാറ്റുക"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"വിന്ഡോ വലുപ്പം വലുതാക്കുക അല്ലെങ്കിൽ പഴയത് പുനഃസ്ഥാപിക്കുക"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"സ്പ്ലിറ്റ് സ്ക്രീൻ മോഡിൽ പ്രവേശിക്കുക"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ഡെസ്ക്ടോപ്പ് വിൻഡോയിംഗ് മോഡിൽ പ്രവേശിക്കുക"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ഇടത്തേക്ക് ആപ്പ് വിൻഡോ വലുപ്പം മാറ്റുക"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"വലത്തേക്ക് ആപ്പ് വിൻഡോ വലുപ്പം മാറ്റുക"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"വിന്ഡോ വലുപ്പം വലുതാക്കുക അല്ലെങ്കിൽ പഴയത് പുനഃസ്ഥാപിക്കുക"</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index b38026c..875ecea 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Дэлгэцийг хуваах"</string>
<string name="more_button_text" msgid="3655388105592893530">"Бусад"</string>
<string name="float_button_text" msgid="9221657008391364581">"Хөвөгч"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Аспектын харьцааг өөрчлөх"</string>
<string name="close_text" msgid="4986518933445178928">"Хаах"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Цэсийг хаах"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Цэсийг нээх"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Дэлгэцийг томруулах"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Хэмжээг өөрчлөх"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Аппыг ийш зөөх боломжгүй"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Аппын цонхны хэмжээг зүүн тал руу өөрчлөх"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Аппын цонхны хэмжээг баруун тал руу өөрчлөх"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Цонхны хэмжээг томруулах эсвэл сэргээх"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Дэлгэц хуваах горимд орох"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Дэлгэцийн цонхны горимд орох"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Цонхны хэмжээг зүүн тал руу өөрчлөх"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Цонхны хэмжээг баруун тал руу өөрчлөх"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Цонхны хэмжээг томруулах эсвэл сэргээх"</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index d9c1d1f..73c16e6 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन"</string>
<string name="more_button_text" msgid="3655388105592893530">"आणखी"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"आस्पेक्ट रेशो बदला"</string>
<string name="close_text" msgid="4986518933445178928">"बंद करा"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"मेनू बंद करा"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"मेनू उघडा"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रीन मोठी करा"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"आकार बदला"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"अॅप इथे हलवू शकत नाही"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"अॅप विंडोचा डावीकडून आकार बदला"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"अॅप विंडोचा उजवीकडून आकार बदला"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"विंडोचा आकार मोठा करा किंवा रिस्टोअर करा"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"स्प्लिट स्क्रीन मोड एंटर करा"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"डेस्कटॉप विंडोइंग मोड एंटर करा"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"अॅप विंडोचा डावीकडे आकार बदला"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"अॅप विंडोचा उजवीकडे आकार बदला"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"विंडोचा आकार मोठा करा किंवा रिस्टोअर करा"</string>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index a54ef14..81e00c5 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Paparan Desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Skrin Pisah"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lagi"</string>
<string name="float_button_text" msgid="9221657008391364581">"Terapung"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Tukar nisbah bidang"</string>
<string name="close_text" msgid="4986518933445178928">"Tutup"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Buka Menu"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (Paparan Desktop)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimumkan Skrin"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Ubah saiz"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Apl tidak boleh dialihkan ke sini"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Butang kiri ubah saiz tetingkap apl"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Butang kanan ubah saiz tetingkap apl"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimumkan atau pulihkan saiz tetingkap"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Masuki mod skrin pisah"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Masuki mod tetingkap desktop"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Buka Menu"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Masukkan <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ubah saiz tetingkap ke sebelah kiri"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ubah saiz tetingkap ke sebelah kanan"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimumkan atau pulihkan saiz tetingkap"</string>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 1f4db6d..be7cca5 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"မျက်နှာပြင် ခွဲ၍ပြသရန်"</string>
<string name="more_button_text" msgid="3655388105592893530">"ပိုပြပါ"</string>
<string name="float_button_text" msgid="9221657008391364581">"မျှောရန်"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"အချိုးအစား ပြောင်းရန်"</string>
<string name="close_text" msgid="4986518933445178928">"ပိတ်ရန်"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"မီနူး ပိတ်ရန်"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"မီနူး ဖွင့်ရန်"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"စခရင်ကို ချဲ့မည်"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"အရွယ်ပြင်ရန်"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"အက်ပ်ကို ဤနေရာသို့ ရွှေ့၍မရပါ"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"အက်ပ်ဝင်းဒိုး ဘယ်ဘက်ကို အရွယ်ပြင်ရန်"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"အက်ပ်ဝင်းဒိုး ညာဘက်ကို အရွယ်ပြင်ရန်"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ဝင်းဒိုးအရွယ်အစားကို ချဲ့ရန် (သို့) ပြန်ပြောင်းရန်"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"မျက်နှာပြင်ခွဲပြခြင်းမုဒ်သို့ ဝင်ရန်"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ဒက်စ်တော့ ဝင်းဒိုးမုဒ်သို့ ဝင်ရန်"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ဝင်းဒိုးကို ဘယ်ဘက်သို့ အရွယ်ပြင်ရန်"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ဝင်းဒိုးကို ညာဘက်သို့ အရွယ်ပြင်ရန်"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ဝင်းဒိုးအရွယ်အစားကို ချဲ့ရန် (သို့) ပြန်ပြောင်းရန်"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 586a50f..c213b7b 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Delt skjerm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svevende"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Endre høyde/bredde-forholdet"</string>
<string name="close_text" msgid="4986518933445178928">"Lukk"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Lukk menyen"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Åpne menyen"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimer skjermen"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Endre størrelse"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Appen kan ikke flyttes hit"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Endre størrelsen på appvinduet til venstre"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Endre størrelsen på appvinduet til høyre"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimer eller gjenopprett størrelsen på vinduet"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Start modusen for delt skjerm"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Start vindusmodus for skrivebordet"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Endre størrelsen på vinduet til venstre"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Endre størrelsen på vinduet til høyre"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimer eller gjenopprett størrelsen på vinduet"</string>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index f66fb1d..e5f4cbe 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रिन"</string>
<string name="more_button_text" msgid="3655388105592893530">"थप"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"एस्पेक्ट रेसियो परिवर्तन गर्नुहोस्"</string>
<string name="close_text" msgid="4986518933445178928">"बन्द गर्नुहोस्"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"मेनु बन्द गर्नुहोस्"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"मेनु खोल्नुहोस्"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रिन ठुलो बनाउनुहोस्"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"आकार बदल्नुहोस्"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"एप सारेर यहाँ ल्याउन सकिएन"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"एपको विन्डोको आकार बदलेर बायाँतिर लैजानुहोस्"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"एपको विन्डोको आकार बदलेर दायाँतिर लैजानुहोस्"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"विन्डोको आकार म्याक्सिमाइज गर्नुहोस् वा रिस्टोर गर्नुहोस्"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"स्प्लिट स्क्रिन मोड प्रयोग गर्नुहोस्"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"डेस्कटप विन्डोइङ मोड प्रयोग गर्नुहोस्"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"विन्डोको आकार बदलेर बायाँतिर लैजानुहोस्"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"विन्डोको आकार बदलेर दायाँतिर लैजानुहोस्"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"विन्डोको आकार म्याक्सिमाइज गर्नुहोस् वा रिस्टोर गर्नुहोस्"</string>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 20bc65a..8396b3e 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Desktopweergave"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Gesplitst scherm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Zwevend"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Beeldverhouding wijzigen"</string>
<string name="close_text" msgid="4986518933445178928">"Sluiten"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Menu sluiten"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menu openen"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (desktopweergave)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Scherm maximaliseren"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Formaat aanpassen"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Kan de app niet hierheen verplaatsen"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Formaat van app-venster naar links aanpassen"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Formaat van app-venster naar rechts aanpassen"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Formaat van venster maximaliseren of herstellen"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Modus voor gesplitst scherm openen"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Modus voor desktopvensterfuncties openen"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Menu openen"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g> openen"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Formaat van venster naar links aanpassen"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Formaat van venster naar rechts aanpassen"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Formaat van venster maximaliseren of herstellen"</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index edb5208..182ea46d8 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ଅଧିକ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ଫ୍ଲୋଟ"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"ଚଉଡ଼ା ଓ ଉଚ୍ଚତାର ଅନୁପାତ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
<string name="close_text" msgid="4986518933445178928">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"ମେନୁ ବନ୍ଦ କରନ୍ତୁ"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ମେନୁ ଖୋଲନ୍ତୁ"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ସ୍କ୍ରିନକୁ ବଡ଼ କରନ୍ତୁ"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ରିସାଇଜ କରନ୍ତୁ"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ଆପକୁ ଏଠାକୁ ମୁଭ କରାଯାଇପାରିବ ନାହିଁ"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ଆପ ୱିଣ୍ଡୋ ରିସାଇଜ କରିବା ପାଇଁ ବାମ ବଟନ"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ଆପ ୱିଣ୍ଡୋ ରିସାଇଜ କରିବା ପାଇଁ ଡାହାଣ ବଟନ"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ୱିଣ୍ଡୋ ସାଇଜକୁ ମେକ୍ସିମାଇଜ କିମ୍ବା ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ମୋଡରେ ପ୍ରବେଶ କରନ୍ତୁ"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ଡେସ୍କଟପ ୱିଣ୍ଡୋଇଂ ମୋଡରେ ପ୍ରବେଶ କରନ୍ତୁ"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ବାମପଟକୁ ୱିଣ୍ଡୋ ରିସାଇଜ କରନ୍ତୁ"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ଡାହାଣପଟକୁ ୱିଣ୍ଡୋ ରିସାଇଜ କରନ୍ତୁ"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ୱିଣ୍ଡୋ ସାଇଜକୁ ମେକ୍ସିମାଇଜ କିମ୍ବା ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 29de4c4..3bc730b 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"ਡੈਸਕਟਾਪ ਦ੍ਰਿਸ਼"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ਹੋਰ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ਫ਼ਲੋਟ"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"ਆਕਾਰ ਅਨੁਪਾਤ ਬਦਲੋ"</string>
<string name="close_text" msgid="4986518933445178928">"ਬੰਦ ਕਰੋ"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"ਮੀਨੂ ਬੰਦ ਕਰੋ"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ਮੀਨੂ ਖੋਲ੍ਹੋ"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (ਡੈਸਕਟਾਪ ਦ੍ਰਿਸ਼)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ਸਕ੍ਰੀਨ ਦਾ ਆਕਾਰ ਵਧਾਓ"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ਆਕਾਰ ਬਦਲੋ"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ਐਪ ਨੂੰ ਇੱਥੇ ਨਹੀਂ ਲਿਜਾਇਆ ਜਾ ਸਕਦਾ"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ਐਪ ਵਿੰਡੋ ਦਾ ਆਕਾਰ ਬਦਲ ਕੇ ਖੱਬੇ ਪਾਸੇ ਕਰੋ"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ਐਪ ਵਿੰਡੋ ਦਾ ਆਕਾਰ ਬਦਲ ਕੇ ਸੱਜੇ ਪਾਸੇ ਕਰੋ"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ਵਿੰਡੋ ਦਾ ਆਕਾਰ ਵਧਾਓ ਜਾਂ ਮੁੜ-ਬਹਾਲ ਕਰੋ"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਮੋਡ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ਡੈਸਕਟਾਪ ਵਿੰਡੋ ਮੋਡ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"ਮੀਨੂ ਖੋਲ੍ਹੋ"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Enter <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ਵਿੰਡੋ ਦਾ ਆਕਾਰ ਬਦਲ ਕੇ ਖੱਬੇ ਪਾਸੇ ਕਰੋ"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ਵਿੰਡੋ ਦਾ ਆਕਾਰ ਬਦਲ ਕੇ ਸੱਜੇ ਪਾਸੇ ਕਰੋ"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ਵਿੰਡੋ ਦਾ ਆਕਾਰ ਵਧਾਓ ਜਾਂ ਮੁੜ-ਬਹਾਲ ਕਰੋ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 47ee80e..9a1bf33 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Podzielony ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Więcej"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pływające"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Zmień format obrazu"</string>
<string name="close_text" msgid="4986518933445178928">"Zamknij"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zamknij menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otwórz menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksymalizuj ekran"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Zmień rozmiar"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Nie można przenieść aplikacji tutaj"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Zmień rozmiar okna aplikacji po lewej"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Zmień rozmiar okna aplikacji po prawej"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Zmaksymalizuj lub przywróć rozmiar okna"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Włącz tryb podzielonego ekranu"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Włącz tryb okien na pulpicie"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Zmień rozmiar okna do lewej"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Zmień rozmiar okna do prawej"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Zmaksymalizuj lub przywróć rozmiar okna"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 0a3ea70..3e019ec 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Versão para computadores"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Mudar a proporção"</string>
<string name="close_text" msgid="4986518933445178928">"Fechar"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir o menu"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (versão para computadores)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ampliar tela"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Redimensionar"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Não é possível mover o app para cá"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionar janela do app para a esquerda"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionar janela do app para a direita"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizar ou restaurar o tamanho da janela"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Entrar no modo de tela dividida"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Entrar no modo de janela do computador"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Abrir o menu"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Entrar no <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionar janela para a esquerda"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionar janela para a direita"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizar ou restaurar o tamanho da janela"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index c9d196b..0ca0e8e 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Vista de computador"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ecrã dividido"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flutuar"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Alterar formato"</string>
<string name="close_text" msgid="4986518933445178928">"Fechar"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir menu"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (vista de computador)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar ecrã"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Redimensionar"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Não é possível mover a app para aqui"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionar janela da app para a esquerda"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionar janela da app para a direita"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizar ou restaurar tamanho da janela"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Aceder ao modo de ecrã dividido"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Aceder ao modo de janelas de computador"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Abrir menu"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Entrar no modo <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionar janela para a esquerda"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionar janela para a direita"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizar ou restaurar tamanho da janela"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 0a3ea70..3e019ec 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Versão para computadores"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Mudar a proporção"</string>
<string name="close_text" msgid="4986518933445178928">"Fechar"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir o menu"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (versão para computadores)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ampliar tela"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Redimensionar"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Não é possível mover o app para cá"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionar janela do app para a esquerda"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionar janela do app para a direita"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizar ou restaurar o tamanho da janela"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Entrar no modo de tela dividida"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Entrar no modo de janela do computador"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Abrir o menu"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Entrar no <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionar janela para a esquerda"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionar janela para a direita"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizar ou restaurar o tamanho da janela"</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index a3313b6..f71d93b 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Ecran împărțit"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mai multe"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotantă"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Schimbă raportul de dimensiuni"</string>
<string name="close_text" msgid="4986518933445178928">"Închide"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Închide meniul"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Deschide meniul"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizează fereastra"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Redimensionează"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplicația nu poate fi mutată aici"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionează fereastra aplicației la stânga"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionează fereastra aplicației la dreapta"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizează sau restabilește dimensiunea ferestrei"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Accesează modul ecran împărțit"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Accesează modul de windowing pe desktop"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionează fereastra la stânga"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionează fereastra la dreapta"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizează sau restabilește dimensiunea ferestrei"</string>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 5b20b2b..adc6f32 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Версия для ПК"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Разделить экран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ещё"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плавающее окно"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Изменить соотношение сторон"</string>
<string name="close_text" msgid="4986518933445178928">"Закрыть"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Закрыть меню"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Открыть меню"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" (версия для ПК)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Развернуть на весь экран"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Изменить размер"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Приложение нельзя сюда переместить"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Растянуть окно приложения влево"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Растянуть окно приложения вправо"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Развернуть окно или восстановить его размер"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Перейти в режим разделения экрана"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Перейти в режим компьютера"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Открыть меню"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Открыть в режиме \"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g>\""</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Растянуть окно влево"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Растянуть окно вправо"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Развернуть окно или восстановить его размер"</string>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index f0ef1d1..b7b2863 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"බෙදුම් තිරය"</string>
<string name="more_button_text" msgid="3655388105592893530">"තව"</string>
<string name="float_button_text" msgid="9221657008391364581">"පාවෙන"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"දර්ශන අනුපාතය වෙනස් කරන්න"</string>
<string name="close_text" msgid="4986518933445178928">"වසන්න"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"මෙනුව වසන්න"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"මෙනුව විවෘත කරන්න"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"තිරය උපරිම කරන්න"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ප්රතිප්රමාණය කරන්න"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"යෙදුම මෙතැනට ගෙන යා නොහැක"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"යෙදුම් කවුළුව වමට ප්රතිප්රමාණ කරන්න"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"යෙදුම් කවුළුව දකුණට ප්රතිප්රමාණ කරන්න"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"කවුළු ප්රමාණය උපරිම කරන්න හෝ ප්රතිසාධනය කරන්න"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"බෙදුම් තිර මාදිලියට ඇතුළු වන්න"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ඩෙස්ක්ටොප කවුළුකරණ මාදිලියට ඇතුළු වන්න"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"කවුළුව වමට ප්රතිප්රමාණ කරන්න"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"කවුළුව දකුණට ප්රතිප්රමාණ කරන්න"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"කවුළු ප්රමාණය උපරිම කරන්න හෝ ප්රතිසාධනය කරන්න"</string>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index 688c217..ede0cdd 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Zobrazenie v počítači"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Rozdelená obrazovka"</string>
<string name="more_button_text" msgid="3655388105592893530">"Viac"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plávajúce"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Zmeniť pomer strán"</string>
<string name="close_text" msgid="4986518933445178928">"Zavrieť"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zavrieť ponuku"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvoriť ponuku"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (zobrazenie v počítači)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximalizovať obrazovku"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Zmeniť veľkosť"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikácia sa sem nedá presunúť"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Zmeniť veľkosť okna aplikácie vľavo"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Zmeniť veľkosť okna aplikácie vpravo"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximalizovať alebo obnoviť veľkosť okna"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Spustiť režim rozdelenej obrazovky"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Prejsť na režim okien na pracovnej ploche"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Otvoriť ponuku"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Zadať <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Zmeniť veľkosť okna vľavo"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Zmeniť veľkosť okna vpravo"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximalizovať alebo obnoviť veľkosť okna"</string>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 69eb3e3..5f1f6ef 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Pogled za namizni računalnik"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Razdeljen zaslon"</string>
<string name="more_button_text" msgid="3655388105592893530">"Več"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebdeče"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Sprememba razmerja stranic"</string>
<string name="close_text" msgid="4986518933445178928">"Zapri"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zapri meni"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Odpri meni"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (pogled za namizni računalnik)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimiraj zaslon"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Spremeni velikost"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacije ni mogoče premakniti sem"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Sprememba velikosti okna aplikacije na levi"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Sprememba velikosti okna aplikacije na desni"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Povečava ali obnovitev velikosti okna"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Vklop načina razdeljenega zaslona"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Vklop načina prikaza v oknu na namizju"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Odpiranje menija"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Odpiranje pogleda <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Sprememba velikosti okna na levi"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Sprememba velikosti okna na desni"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Povečava ali obnovitev velikosti okna"</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index fcb0aa6..ea26bc6 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Ekrani i ndarë"</string>
<string name="more_button_text" msgid="3655388105592893530">"Më shumë"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pluskuese"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Ndrysho raportin e pamjes"</string>
<string name="close_text" msgid="4986518933445178928">"Mbyll"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Mbyll menynë"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Hap menynë"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimizo ekranin"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Ndrysho përmasat"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacioni nuk mund të zhvendoset këtu"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ndrysho përmasat e dritares së aplikacionit majtas"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ndrysho përmasat e dritares së aplikacionit djathtas"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimizo ose restauro madhësinë e dritares"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Hyr në modalitetin e ekranit të ndarë"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Hyr në modalitetin e dritareve në desktop"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ndrysho përmasat e dritares në të majtë"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ndrysho përmasat e dritares në të djathtë"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimizo ose restauro madhësinë e dritares"</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 6a2ffcd..ea7a1bb 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Приказ за рачунаре"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Подељени екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Још"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плутајуће"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Промени размеру"</string>
<string name="close_text" msgid="4986518933445178928">"Затворите"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Затворите мени"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Отворите мени"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (приказ за рачунаре)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Повећај екран"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Промени величину"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Апликација не може да се премести овде"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Промените величину прозора апликације налево"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Промените величину прозора апликације надесно"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Увећајте или вратите величину прозора"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Уђите у режим подељеног екрана"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Уђите у режим прозора на рачунару"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Отворите Мени"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Унесите <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Промените величину прозора налево"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Промените величину прозора надесно"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Увећајте или вратите величину прозора"</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index a9df476..f3e53d0e 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"Datorvy"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Delad skärm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svävande"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Ändra bildformat"</string>
<string name="close_text" msgid="4986518933445178928">"Stäng"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Stäng menyn"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Öppna menyn"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (datorvy)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximera skärmen"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Ändra storlek"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Det går inte att flytta appen hit"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ändra storlek på appfönstret åt vänster"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ändra storlek på appfönstret åt höger"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximera eller återställ fönsterstorleken"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Starta läget för delad skärm"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Starta datorläget"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"Öppna menyn"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"Ange <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ändra storlek på fönstret åt vänster"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ändra storlek på fönstret åt höger"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximera eller återställ fönsterstorleken"</string>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index a3c9a0d..51aacac 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Gawa Skrini"</string>
<string name="more_button_text" msgid="3655388105592893530">"Zaidi"</string>
<string name="float_button_text" msgid="9221657008391364581">"Inayoelea"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Badilisha uwiano"</string>
<string name="close_text" msgid="4986518933445178928">"Funga"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Funga Menyu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Fungua Menyu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Panua Dirisha kwenye Skrini"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Badilisha ukubwa"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Imeshindwa kuhamishia programu hapa"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Badilisha ukubwa wa dirisha la programu kushoto"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Badilisha ukubwa wa dirisha la programu kulia"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Panua au urejeshe ukubwa wa dirisha"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Ingia katika hali ya skrini iliyogawanywa"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Ingia katika hali ya madirisha ya kompyuta ya mezani"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Badilisha ukubwa wa dirisha kushoto"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Badilisha ukubwa wa dirisha kulia"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Panua au urejeshe ukubwa wa dirisha"</string>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index b1b8c7f..0c7206c 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"திரையைப் பிரிக்கும்"</string>
<string name="more_button_text" msgid="3655388105592893530">"கூடுதல் விருப்பத்தேர்வுகள்"</string>
<string name="float_button_text" msgid="9221657008391364581">"மிதக்கும் சாளரம்"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"தோற்ற விகிதத்தை மாற்று"</string>
<string name="close_text" msgid="4986518933445178928">"மூடும்"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"மெனுவை மூடும்"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"மெனுவைத் திறக்கும்"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"திரையைப் பெரிதாக்கு"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"அளவை மாற்று"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ஆப்ஸை இங்கே நகர்த்த முடியாது"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ஆப்ஸ் சாளரத்தின் இடதுபுறத்தில் அளவை மாற்றும்"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ஆப்ஸ் சாளரத்தின் வலதுபுறத்தில் அளவை மாற்றும்"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"சாளரத்தின் அளவைப் பெரிதாக்கும்/மீட்டெடுக்கும்"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"திரைப் பிரிப்புப் பயன்முறையில் உள்நுழையும்"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"டெஸ்க்டாப் சாளரப் பயன்முறையில் உள்நுழையும்"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"சாளரத்தை இடதுபுறமாக அளவு மாற்றும்"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"சாளரத்தை வலதுபுறமாக அளவு மாற்றும்"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"சாளரத்தின் அளவைப் பெரிதாக்கும்/மீட்டெடுக்கும்"</string>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 932f831..f7cf43e 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"డెస్క్టాప్ వీక్షణ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"స్ప్లిట్ స్క్రీన్"</string>
<string name="more_button_text" msgid="3655388105592893530">"మరిన్ని"</string>
<string name="float_button_text" msgid="9221657008391364581">"ఫ్లోట్"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"ఆకార నిష్పత్తిని మార్చండి"</string>
<string name="close_text" msgid="4986518933445178928">"మూసివేయండి"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"మెనూను మూసివేయండి"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"మెనూను తెరవండి"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (డెస్క్టాప్ వీక్షణ)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"స్క్రీన్ సైజ్ను పెంచండి"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"సైజ్ మార్చండి"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"యాప్ను ఇక్కడకి తరలించడం సాధ్యం కాదు"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"యాప్ విండో ఎడమ వైపు సైజ్ మార్చండి"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"యాప్ విండో కుడి వైపు సైజ్ మార్చండి"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"విండో సైజ్ను మ్యాగ్జిమైజ్ చేయండి లేదా రీస్టోర్ చేయండి"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"స్ప్లిట్ స్క్రీన్ మోడ్ను ఉపయోగించండి"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"డెస్క్టాప్ విండోయింగ్ మోడ్ను ఎంటర్ చేయండి"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"మెనూను తెరవండి"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"<xliff:g id="WINDOWING_MODE">%1$s</xliff:g>ను ఎంటర్ చేయండి"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"విండో ఎడమ వైపునకు సైజ్ను మార్చండి"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"విండో కుడి వైపునకు సైజ్ను మార్చండి"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"విండో సైజ్ను మ్యాగ్జిమైజ్ చేయండి లేదా రీస్టోర్ చేయండి"</string>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index e157474..77cd2e2 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -119,7 +119,7 @@
<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>
+ <string name="desktop_text" msgid="1582173066857454541">"มุมมองบนเดสก์ท็อป"</string>
<string name="split_screen_text" msgid="1396336058129570886">"แยกหน้าจอ"</string>
<string name="more_button_text" msgid="3655388105592893530">"เพิ่มเติม"</string>
<string name="float_button_text" msgid="9221657008391364581">"ล่องลอย"</string>
@@ -132,7 +132,7 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"เปลี่ยนสัดส่วนการแสดงผล"</string>
<string name="close_text" msgid="4986518933445178928">"ปิด"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"ปิดเมนู"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"เปิดเมนู"</string>
+ <string name="desktop_mode_app_header_chip_text" msgid="8300164817452574565">"<xliff:g id="APP_NAME">%1$s</xliff:g> (มุมมองบนเดสก์ท็อป)"</string>
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ขยายหน้าจอให้ใหญ่สุด"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"ปรับขนาด"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ย้ายแอปมาที่นี่ไม่ได้"</string>
@@ -145,8 +145,8 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ปรับขนาดหน้าต่างแอปไปทางซ้าย"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ปรับขนาดหน้าต่างแอปไปทางขวา"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ขยายหรือคืนค่าขนาดหน้าต่าง"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"เข้าสู่โหมดแยกหน้าจอ"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"เข้าสู่โหมดหน้าต่างเดสก์ท็อป"</string>
+ <string name="app_handle_chip_accessibility_announce" msgid="499881698947450536">"เปิดเมนู"</string>
+ <string name="app_handle_menu_accessibility_announce" msgid="7928858564852785398">"เข้าสู่ <xliff:g id="WINDOWING_MODE">%1$s</xliff:g>"</string>
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ปรับขนาดหน้าต่างไปทางซ้าย"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ปรับขนาดหน้าต่างไปทางขวา"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ขยายหรือคืนค่าขนาดหน้าต่าง"</string>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 7f29704..5787e10 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"Higit pa"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Baguhin ang aspect ratio"</string>
<string name="close_text" msgid="4986518933445178928">"Isara"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Isara ang Menu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Buksan ang Menu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"I-maximize ang Screen"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"I-resize"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Hindi mailipat dito ang app"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"I-resize pakaliwa ang window ng app"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"I-resize pakanan ang window ng app"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"I-maximize o i-restore ang laki ng window"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Pumunta sa split screen mode"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Pumunta sa desktop windowing mode"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"I-resize pakaliwa ang window"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"I-resize pakanan ang window"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"I-maximize o i-restore ang laki ng window"</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 6a5d1ab..28b2a7d 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Daha Fazla"</string>
<string name="float_button_text" msgid="9221657008391364581">"Havada Süzülen"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"En boy oranını değiştir"</string>
<string name="close_text" msgid="4986518933445178928">"Kapat"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Menüyü kapat"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menüyü aç"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranı Büyüt"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Yeniden boyutlandır"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Uygulama buraya taşınamıyor"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Uygulama penceresini sola yeniden boyutlandır"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Uygulama penceresini sağa yeniden boyutlandır"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Pencereyi ekranı kaplayacak şekilde büyüt veya önceki boyutuna döndür"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Bölünmüş ekran moduna gir"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Masaüstü pencereleme moduna gir"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Pencereyi sola yeniden boyutlandır"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Pencereyi sağa yeniden boyutlandır"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Pencereyi ekranı kaplayacak şekilde büyüt veya önceki boyutuna döndür"</string>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 7f4e91d..f5693ca 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Розділити екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Більше"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плаваюче вікно"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Змінити формат"</string>
<string name="close_text" msgid="4986518933445178928">"Закрити"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Закрити меню"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Відкрити меню"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Розгорнути екран"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Змінити розмір"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Сюди не можна перемістити додаток"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Змінити розмір вікна додатка ліворуч"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Змінити розмір вікна додатка праворуч"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Розгорнути вікно або відновити його розмір"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Увімкнути режим розділення екрана"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Увімкнути режим вікон для комп’ютера"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Змінити розмір вікна ліворуч"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Змінити розмір вікна праворуч"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Розгорнути вікно або відновити його розмір"</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index f461d40..a801b5e 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"اسپلٹ اسکرین"</string>
<string name="more_button_text" msgid="3655388105592893530">"مزید"</string>
<string name="float_button_text" msgid="9221657008391364581">"فلوٹ"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"تناسبی شرح کو تبدیل کریں"</string>
<string name="close_text" msgid="4986518933445178928">"بند کریں"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"مینیو بند کریں"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"مینو کھولیں"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"اسکرین کو بڑا کریں"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"سائز تبدیل کریں"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ایپ کو یہاں منتقل نہیں کیا جا سکتا"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"دائیں طرف ایپ ونڈو کا سائز تبدیل کریں"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ایپ ونڈو کا سائز بائیں طرف تبدیل کریں"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ونڈو کا سائز زیادہ سے زیادہ یا بحال کریں"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"سپلٹ اسکرین موڈ میں داخل ہوں"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ڈیسک ٹاپ ونڈو وضع میں داخل ہوں"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"دائیں طرف ونڈو کا سائز تبدیل کریں"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ونڈو کا سائز بائیں طرف تبدیل کریں"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ونڈو کا سائز زیادہ سے زیادہ یا بحال کریں"</string>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 7c6a2a2..9fbbdc8 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Ekranni ikkiga ajratish"</string>
<string name="more_button_text" msgid="3655388105592893530">"Yana"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pufakli"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Tomonlar nisbatini oʻzgartirish"</string>
<string name="close_text" msgid="4986518933445178928">"Yopish"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Menyuni yopish"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menyuni ochish"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranni yoyish"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Oʻlchamini oʻzgartirish"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Ilova bu yerga surilmaydi"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ilova chap oynasi oʻlchamini oʻzgartirish"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ilova oʻng oynasi oʻlchamini oʻzgartirish"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Oyna oʻlchamini kengaytirish yoki asliga qaytarish"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Ajratilgan ekran rejimiga kirish"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Kompyuter rejimiga kirish"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Oyna oʻlchamini chapga oʻzgartirish"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Oyna oʻlchamini oʻngga oʻzgartirish"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Oyna oʻlchamini kengaytirish yoki asliga qaytarish"</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index e7cacc3..b40a4e6 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Chia đôi màn hình"</string>
<string name="more_button_text" msgid="3655388105592893530">"Tuỳ chọn khác"</string>
<string name="float_button_text" msgid="9221657008391364581">"Nổi"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Thay đổi tỷ lệ khung hình"</string>
<string name="close_text" msgid="4986518933445178928">"Đóng"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Đóng trình đơn"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Mở Trình đơn"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Mở rộng màn hình"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Đổi kích thước"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Không di chuyển được ứng dụng đến đây"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Đổi kích thước và chuyển cửa sổ ứng dụng sang trái"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Đổi kích thước và chuyển cửa sổ ứng dụng sang phải"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Phóng to hoặc khôi phục kích thước cửa sổ"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Mở chế độ chia đôi màn hình"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Mở chế độ cửa sổ trên máy tính"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Đổi kích thước và chuyển cửa sổ sang trái"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Đổi kích thước và chuyển cửa sổ sang phải"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Phóng to hoặc khôi phục kích thước cửa sổ"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 562a0ee0..45cd25b 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"分屏"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"悬浮"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"更改宽高比"</string>
<string name="close_text" msgid="4986518933445178928">"关闭"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"关闭菜单"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"打开菜单"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"最大化屏幕"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"调整大小"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"无法将应用移至此处"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"调整应用窗口大小并贴靠左侧"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"调整应用窗口大小并贴靠右侧"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"将窗口最大化或恢复大小"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"进入分屏模式"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"进入桌面设备窗口化模式"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"调整窗口大小并贴靠左侧"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"调整窗口大小并贴靠右侧"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"将窗口最大化或恢复大小"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index eecd9f2..d2c22da 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"分割螢幕"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"變更長寬比"</string>
<string name="close_text" msgid="4986518933445178928">"關閉"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"打開選單"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"畫面最大化"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"調整大小"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"應用程式無法移至這裡"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"調整左邊應用程式視窗大小"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"調整右邊應用程式視窗大小"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"將視窗放到最大或者還原視窗大小"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"進入分割螢幕模式"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"進入桌面視窗模式"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"將視窗移去左邊調整大小"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"將視窗移去右邊調整大小"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"將視窗放到最大或者還原視窗大小"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index c157c193..0984fad 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"分割畫面"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"變更顯示比例"</string>
<string name="close_text" msgid="4986518933445178928">"關閉"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"開啟選單"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"畫面最大化"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"調整大小"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"應用程式無法移至此處"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"調整應用程式視窗大小並向左貼齊"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"調整應用程式視窗大小並向右貼齊"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"將視窗最大化或還原大小"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"進入分割畫面模式"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"進入電腦視窗化模式"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"調整應用程式視窗大小並向左貼齊"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"調整應用程式視窗大小並向右貼齊"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"將視窗最大化或還原大小"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index a7ba6d2..13f8ed1 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -119,7 +119,8 @@
<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>
+ <!-- no translation found for desktop_text (1582173066857454541) -->
+ <skip />
<string name="split_screen_text" msgid="1396336058129570886">"Hlukanisa isikrini"</string>
<string name="more_button_text" msgid="3655388105592893530">"Okwengeziwe"</string>
<string name="float_button_text" msgid="9221657008391364581">"Iflowuthi"</string>
@@ -132,7 +133,8 @@
<string name="change_aspect_ratio_text" msgid="9104456064548212806">"Shintsha ukubukeka kwesilinganiselo"</string>
<string name="close_text" msgid="4986518933445178928">"Vala"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Vala Imenyu"</string>
- <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Vula Imenyu"</string>
+ <!-- no translation found for desktop_mode_app_header_chip_text (8300164817452574565) -->
+ <skip />
<string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Khulisa Isikrini Sifike Ekugcineni"</string>
<string name="desktop_mode_maximize_menu_snap_text" msgid="5673738963174074006">"Shintsha usayizi"</string>
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"I-app ayikwazi ukuhanjiswa lapha"</string>
@@ -145,8 +147,10 @@
<string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Shintsha usayizi we-app yewindi ngakwesokunxele"</string>
<string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Shintsha usayizi we-app yewindi ngakwesokudla"</string>
<string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Khulisa noma buyisela usayizi wewindi"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Faka imodi yokuhlukanisa isikrini"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Faka imodi yokwenza iwindi yedeskithophu"</string>
+ <!-- no translation found for app_handle_chip_accessibility_announce (499881698947450536) -->
+ <skip />
+ <!-- no translation found for app_handle_menu_accessibility_announce (7928858564852785398) -->
+ <skip />
<string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Shintsha usayizi wewindi ngakwesokunxele"</string>
<string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Shintsha usayizi wewindi ngakwesokudla"</string>
<string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Khulisa noma buyisela usayizi wewindi"</string>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index f5f3f0f..a0c68ad 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -670,7 +670,4 @@
<dimen name="desktop_windowing_education_promo_height">352dp</dimen>
<!-- The corner radius of the desktop windowing education promo. -->
<dimen name="desktop_windowing_education_promo_corner_radius">28dp</dimen>
-
- <!-- The corner radius of freeform tasks in desktop windowing. -->
- <dimen name="desktop_windowing_freeform_rounded_corner_radius">16dp</dimen>
</resources>
diff --git a/libs/WindowManager/Shell/shared/res/values/dimen.xml b/libs/WindowManager/Shell/shared/res/values/dimen.xml
index 11a6f32..23c9caf 100644
--- a/libs/WindowManager/Shell/shared/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/shared/res/values/dimen.xml
@@ -46,4 +46,7 @@
<dimen name="drop_target_expanded_view_height">578</dimen>
<dimen name="drop_target_expanded_view_padding_bottom">108</dimen>
<dimen name="drop_target_expanded_view_padding_horizontal">24</dimen>
+
+ <!-- The corner radius of freeform tasks in desktop windowing. -->
+ <dimen name="desktop_windowing_freeform_rounded_corner_radius">16dp</dimen>
</resources>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/Interpolators.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/Interpolators.java
index e92c1eb..43dd9b7 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/Interpolators.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/Interpolators.java
@@ -74,6 +74,12 @@
0.05f, 0.7f, 0.1f, 1f);
/**
+ * The standard accelerating interpolator that should be used on every regular movement of
+ * content that is disappearing e.g. when moving off screen.
+ */
+ public static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(0.3f, 0f, 1f, 1f);
+
+ /**
* The standard decelerating interpolator that should be used on every regular movement of
* content that is appearing e.g. when coming from off screen.
*/
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/MinimizeAnimator.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/MinimizeAnimator.kt
index 0586e26..4ecace0 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/MinimizeAnimator.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/MinimizeAnimator.kt
@@ -19,52 +19,76 @@
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ValueAnimator
-import android.util.DisplayMetrics
+import android.content.Context
+import android.os.Handler
+import android.view.Choreographer
import android.view.SurfaceControl.Transaction
-import android.view.animation.LinearInterpolator
-import android.view.animation.PathInterpolator
import android.window.TransitionInfo.Change
+import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW
+import com.android.internal.jank.InteractionJankMonitor
/** Creates minimization animation */
object MinimizeAnimator {
private const val MINIMIZE_ANIM_ALPHA_DURATION_MS = 100L
- private val STANDARD_ACCELERATE = PathInterpolator(0.3f, 0f, 1f, 1f)
-
private val minimizeBoundsAnimationDef =
WindowAnimator.BoundsAnimationParams(
durationMs = 200,
endOffsetYDp = 12f,
endScale = 0.97f,
- interpolator = STANDARD_ACCELERATE,
+ interpolator = Interpolators.STANDARD_ACCELERATE,
)
+ /**
+ * Creates a minimize animator for given task [Change].
+ *
+ * @param onAnimFinish finish-callback for the animation, note that this is called on the same
+ * thread as the animation itself.
+ * @param animationHandler the Handler that the animation is running on.
+ */
@JvmStatic
fun create(
- displayMetrics: DisplayMetrics,
+ context: Context,
change: Change,
transaction: Transaction,
onAnimFinish: (Animator) -> Unit,
+ interactionJankMonitor: InteractionJankMonitor,
+ animationHandler: Handler,
): Animator {
val boundsAnimator = WindowAnimator.createBoundsAnimator(
- displayMetrics,
+ context.resources.displayMetrics,
minimizeBoundsAnimationDef,
change,
transaction,
)
val alphaAnimator = ValueAnimator.ofFloat(1f, 0f).apply {
duration = MINIMIZE_ANIM_ALPHA_DURATION_MS
- interpolator = LinearInterpolator()
+ interpolator = Interpolators.LINEAR
addUpdateListener { animation ->
- transaction.setAlpha(change.leash, animation.animatedValue as Float).apply()
+ transaction
+ .setAlpha(change.leash, animation.animatedValue as Float)
+ .setFrameTimeline(Choreographer.getInstance().vsyncId)
+ .apply()
}
}
val listener = object : Animator.AnimatorListener {
- override fun onAnimationEnd(animator: Animator) = onAnimFinish(animator)
- override fun onAnimationCancel(animator: Animator) = Unit
+ override fun onAnimationStart(animator: Animator) {
+ interactionJankMonitor.begin(
+ change.leash,
+ context,
+ animationHandler,
+ CUJ_DESKTOP_MODE_MINIMIZE_WINDOW,
+ )
+ }
+ override fun onAnimationCancel(animator: Animator) {
+ interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
+ }
override fun onAnimationRepeat(animator: Animator) = Unit
- override fun onAnimationStart(animator: Animator) = Unit
+ override fun onAnimationEnd(animator: Animator) {
+ interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
+ onAnimFinish(animator)
+ }
}
return AnimatorSet().apply {
playTogether(boundsAnimator, alphaAnimator)
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
index 14338a4..0e4a6b9 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
@@ -16,12 +16,14 @@
package com.android.wm.shell.shared.desktopmode
+import android.Manifest.permission.SYSTEM_ALERT_WINDOW
import android.app.TaskInfo
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED
import android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION
import android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS
+import android.content.pm.PackageManager
import android.window.DesktopModeFlags
import com.android.internal.R
@@ -32,8 +34,10 @@
class DesktopModeCompatPolicy(private val context: Context) {
private val systemUiPackage: String = context.resources.getString(R.string.config_systemUi)
+ private val pkgManager: PackageManager
+ get() = context.getPackageManager()
private val defaultHomePackage: String?
- get() = context.getPackageManager().getHomeActivities(ArrayList())?.packageName
+ get() = pkgManager.getHomeActivities(ArrayList())?.packageName
/**
* If the top activity should be exempt from desktop windowing and forced back to fullscreen.
@@ -47,11 +51,12 @@
fun isTopActivityExemptFromDesktopWindowing(packageName: String?,
numActivities: Int, isTopActivityNoDisplay: Boolean, isActivityStackTransparent: Boolean) =
- DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue
- && ((isSystemUiTask(packageName)
- || isPartOfDefaultHomePackageOrNoHomeAvailable(packageName)
- || isTransparentTask(isActivityStackTransparent, numActivities))
- && !isTopActivityNoDisplay)
+ DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue &&
+ ((isSystemUiTask(packageName) ||
+ isPartOfDefaultHomePackageOrNoHomeAvailable(packageName) ||
+ (isTransparentTask(isActivityStackTransparent, numActivities) &&
+ hasFullscreenTransparentPermission(packageName))) &&
+ !isTopActivityNoDisplay)
/**
* Whether the caption insets should be excluded from configuration for system to handle.
@@ -83,6 +88,26 @@
private fun isSystemUiTask(packageName: String?) = packageName == systemUiPackage
+ // Checks if the app for the given package has the SYSTEM_ALERT_WINDOW permission.
+ private fun hasFullscreenTransparentPermission(packageName: String?): Boolean {
+ if (DesktopModeFlags.ENABLE_MODALS_FULLSCREEN_WITH_PERMISSIONS.isTrue) {
+ if (packageName == null) {
+ return false
+ }
+ return try {
+ val packageInfo = pkgManager.getPackageInfo(
+ packageName,
+ PackageManager.GET_PERMISSIONS
+ )
+ packageInfo?.requestedPermissions?.contains(SYSTEM_ALERT_WINDOW) == true
+ } catch (e: PackageManager.NameNotFoundException) {
+ false // Package not found
+ }
+ }
+ // If the flag is disabled we make this condition neutral.
+ return true
+ }
+
/**
* Returns true if the tasks base activity is part of the default home package, or there is
* currently no default home package available.
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 f269b38..78f5154 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
@@ -364,7 +364,7 @@
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull List<ActivityEmbeddingAnimationAdapter> adapters) {
for (ActivityEmbeddingAnimationAdapter adapter : adapters) {
- final int backgroundColor = getTransitionBackgroundColorIfSet(info, adapter.mChange,
+ final int backgroundColor = getTransitionBackgroundColorIfSet(adapter.mChange,
adapter.mAnimation, 0 /* defaultColor */);
if (backgroundColor != 0) {
// We only need to show one color.
@@ -436,8 +436,8 @@
final TransitionInfo.AnimationOptions options = boundsAnimationChange
.getAnimationOptions();
if (options != null) {
- final Animation overrideAnimation = mAnimationSpec.loadCustomAnimationFromOptions(
- options, TRANSIT_CHANGE);
+ final Animation overrideAnimation =
+ mAnimationSpec.loadCustomAnimation(options, TRANSIT_CHANGE);
if (overrideAnimation != null) {
overrideShowBackdrop = overrideAnimation.getShowBackdrop();
}
@@ -447,7 +447,7 @@
// There are two animations in the array. The first one is for the start leash
// (snapshot), and the second one is for the end leash (TaskFragment).
final Animation[] animations =
- mAnimationSpec.createChangeBoundsChangeAnimations(info, change, parentBounds);
+ mAnimationSpec.createChangeBoundsChangeAnimations(change, parentBounds);
// Jump cut if either animation has zero for duration.
for (Animation animation : animations) {
if (shouldUseJumpCutForAnimation(animation)) {
@@ -500,12 +500,10 @@
// window without bounds change.
animation = ActivityEmbeddingAnimationSpec.createNoopAnimation(change);
} else if (TransitionUtil.isClosingType(change.getMode())) {
- animation =
- mAnimationSpec.createChangeBoundsCloseAnimation(info, change, parentBounds);
+ animation = mAnimationSpec.createChangeBoundsCloseAnimation(change, parentBounds);
shouldShowBackgroundColor = false;
} else {
- animation =
- mAnimationSpec.createChangeBoundsOpenAnimation(info, change, parentBounds);
+ animation = mAnimationSpec.createChangeBoundsOpenAnimation(change, parentBounds);
shouldShowBackgroundColor = false;
}
if (shouldUseJumpCutForAnimation(animation)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index 77799e9..2b9eda4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -42,7 +42,6 @@
import android.window.TransitionInfo;
import com.android.internal.policy.TransitionAnimation;
-import com.android.window.flags.Flags;
import com.android.wm.shell.shared.TransitionUtil;
/** Animation spec for ActivityEmbedding transition. */
@@ -94,9 +93,10 @@
/** Animation for window that is opening in a change transition. */
@NonNull
- Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo info,
- @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) {
- final Animation customAnimation = loadCustomAnimation(info, change, TRANSIT_CHANGE);
+ Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo.Change change,
+ @NonNull Rect parentBounds) {
+ final Animation customAnimation =
+ loadCustomAnimation(change.getAnimationOptions(), TRANSIT_CHANGE);
if (customAnimation != null) {
return customAnimation;
}
@@ -126,9 +126,10 @@
/** Animation for window that is closing in a change transition. */
@NonNull
- Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo info,
- @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) {
- final Animation customAnimation = loadCustomAnimation(info, change, TRANSIT_CHANGE);
+ Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo.Change change,
+ @NonNull Rect parentBounds) {
+ final Animation customAnimation =
+ loadCustomAnimation(change.getAnimationOptions(), TRANSIT_CHANGE);
if (customAnimation != null) {
return customAnimation;
}
@@ -162,12 +163,13 @@
* the second one is for the end leash.
*/
@NonNull
- Animation[] createChangeBoundsChangeAnimations(@NonNull TransitionInfo info,
- @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) {
+ Animation[] createChangeBoundsChangeAnimations(@NonNull TransitionInfo.Change change,
+ @NonNull Rect parentBounds) {
// TODO(b/293658614): Support more complicated animations that may need more than a noop
// animation as the start leash.
final Animation noopAnimation = createNoopAnimation(change);
- final Animation customAnimation = loadCustomAnimation(info, change, TRANSIT_CHANGE);
+ final Animation customAnimation =
+ loadCustomAnimation(change.getAnimationOptions(), TRANSIT_CHANGE);
if (customAnimation != null) {
return new Animation[]{noopAnimation, customAnimation};
}
@@ -221,7 +223,8 @@
Animation loadOpenAnimation(@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
- final Animation customAnimation = loadCustomAnimation(info, change, change.getMode());
+ final Animation customAnimation =
+ loadCustomAnimation(change.getAnimationOptions(), change.getMode());
final Animation animation;
if (customAnimation != null) {
animation = customAnimation;
@@ -248,7 +251,8 @@
Animation loadCloseAnimation(@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
- final Animation customAnimation = loadCustomAnimation(info, change, change.getMode());
+ final Animation customAnimation =
+ loadCustomAnimation(change.getAnimationOptions(), change.getMode());
final Animation animation;
if (customAnimation != null) {
animation = customAnimation;
@@ -280,20 +284,8 @@
}
@Nullable
- private Animation loadCustomAnimation(@NonNull TransitionInfo info,
- @NonNull TransitionInfo.Change change, @WindowManager.TransitionType int mode) {
- final TransitionInfo.AnimationOptions options;
- if (Flags.moveAnimationOptionsToChange()) {
- options = change.getAnimationOptions();
- } else {
- options = info.getAnimationOptions();
- }
- return loadCustomAnimationFromOptions(options, mode);
- }
-
- @Nullable
- Animation loadCustomAnimationFromOptions(@Nullable TransitionInfo.AnimationOptions options,
- @WindowManager.TransitionType int mode) {
+ Animation loadCustomAnimation(@Nullable TransitionInfo.AnimationOptions options,
+ @WindowManager.TransitionType int mode) {
if (options == null || options.getType() != ANIM_CUSTOM) {
return null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
index 55ed5fa..3a95333 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
@@ -40,7 +40,6 @@
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.window.flags.Flags;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
@@ -123,9 +122,6 @@
}
private boolean shouldAnimateAnimationOptions(@NonNull TransitionInfo info) {
- if (!Flags.moveAnimationOptionsToChange()) {
- return shouldAnimateAnimationOptions(info.getAnimationOptions());
- }
for (TransitionInfo.Change change : info.getChanges()) {
if (!shouldAnimateAnimationOptions(change.getAnimationOptions())) {
// If any of override animation is not supported, don't animate the transition.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
index 5bd8d86..0f1bf5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
@@ -15,6 +15,8 @@
*/
package com.android.wm.shell.bubbles;
+import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
+
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.Context;
@@ -35,7 +37,6 @@
import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.launcher3.icons.DotRenderer;
-import com.android.launcher3.icons.IconNormalizer;
import com.android.wm.shell.R;
import com.android.wm.shell.shared.animation.Interpolators;
@@ -132,7 +133,7 @@
private void getOutline(Outline outline) {
final int bubbleSize = mPositioner.getBubbleSize();
- final int normalizedSize = IconNormalizer.getNormalizedCircleSize(bubbleSize);
+ final int normalizedSize = Math.round(ICON_VISIBLE_AREA_FACTOR * bubbleSize);
final int inset = (bubbleSize - normalizedSize) / 2;
outline.setOval(inset, inset, inset + normalizedSize, inset + normalizedSize);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index d948928..313d151 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -364,7 +364,7 @@
@ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) {
return new Bubble(intent,
user,
- /* key= */ getAppBubbleKeyForApp(ComponentUtils.getPackageName(intent), user),
+ /* key= */ getAppBubbleKeyForApp(intent.getIntent().getPackage(), user),
mainExecutor, bgExecutor);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 58b46d2..305fcdd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -595,7 +595,10 @@
* <p>If bubble bar is supported, bubble views will be updated to switch to bar mode.
*/
public void registerBubbleStateListener(Bubbles.BubbleStateListener listener) {
- if (Flags.enableBubbleBar() && mBubblePositioner.isLargeScreen() && listener != null) {
+ final boolean bubbleBarAllowed = Flags.enableBubbleBar()
+ && (mBubblePositioner.isLargeScreen() || Flags.enableBubbleBarOnPhones())
+ && listener != null;
+ if (bubbleBarAllowed) {
// Only set the listener if we can show the bubble bar.
mBubbleStateListener = listener;
setUpBubbleViewsForMode();
@@ -772,7 +775,7 @@
/** Whether bubbles would be shown with the bubble bar UI. */
public boolean isShowingAsBubbleBar() {
return Flags.enableBubbleBar()
- && mBubblePositioner.isLargeScreen()
+ && (mBubblePositioner.isLargeScreen() || Flags.enableBubbleBarOnPhones())
&& mBubbleStateListener != null;
}
@@ -909,7 +912,7 @@
// TODO(b/393172431) : Utilise DragZoneFactory once it is ready
final int bubbleBarDropZoneSideSize = getContext().getResources().getDimensionPixelSize(
R.dimen.bubble_bar_drop_zone_side_size);
- int top = t - bubbleBarDropZoneSideSize;
+ int top = b - bubbleBarDropZoneSideSize;
result.put(BubbleBarLocation.LEFT,
new Rect(l, top, l + bubbleBarDropZoneSideSize, b));
result.put(BubbleBarLocation.RIGHT,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 3f607a9..2c2451c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -197,6 +197,8 @@
*/
private final FrameLayout mExpandedViewContainer = new FrameLayout(getContext());
+ private TaskView.Listener mCurrentTaskViewListener;
+
private final TaskView.Listener mTaskViewListener = new TaskView.Listener() {
private boolean mInitialized = false;
private boolean mDestroyed = false;
@@ -235,18 +237,24 @@
Context context =
mContext.createContextAsUser(
mBubble.getUser(), Context.CONTEXT_RESTRICTED);
+ Intent fillInIntent = new Intent();
+ fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
PendingIntent pi = PendingIntent.getActivity(
context,
/* requestCode= */ 0,
- mBubble.getIntent().addFlags(FLAG_ACTIVITY_MULTIPLE_TASK),
- PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
+ mBubble.getIntent(),
+ // Needs to be mutable for the fillInIntent
+ PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
/* options= */ null);
- mTaskView.startActivity(pi, /* fillInIntent= */ null, options,
- launchBounds);
+ mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
} else if (!mIsOverflow && isShortcutBubble) {
ProtoLog.v(WM_SHELL_BUBBLES, "startingShortcutBubble=%s", getBubbleKey());
- options.setLaunchedFromBubble(true);
- options.setApplyActivityFlagsForBubbles(true);
+ if (mBubble.isChat()) {
+ options.setLaunchedFromBubble(true);
+ options.setApplyActivityFlagsForBubbles(true);
+ } else {
+ options.setApplyMultipleTaskFlagForShortcut(true);
+ }
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
options, launchBounds);
} else {
@@ -453,7 +461,34 @@
mTaskView = bubbleTaskView.getTaskView();
// reset the insets that might left after TaskView is shown in BubbleBarExpandedView
mTaskView.setCaptionInsets(null);
- bubbleTaskView.setDelegateListener(mTaskViewListener);
+ if (Flags.enableBubbleTaskViewListener()) {
+ mCurrentTaskViewListener = new BubbleTaskViewListener(mContext, bubbleTaskView,
+ /* viewParent= */ this, expandedViewManager,
+ new BubbleTaskViewListener.Callback() {
+ @Override
+ public void onTaskCreated() {
+ setContentVisibility(true);
+ }
+
+ @Override
+ public void onContentVisibilityChanged(boolean visible) {
+ setContentVisibility(visible);
+ }
+
+ @Override
+ public void onBackPressed() {
+ mStackView.onBackPressed();
+ }
+
+ @Override
+ public void onTaskRemovalStarted() {
+ // nothing to do / handled in listener.
+ }
+ });
+ } else {
+ mCurrentTaskViewListener = mTaskViewListener;
+ bubbleTaskView.setDelegateListener(mCurrentTaskViewListener);
+ }
// set a fixed width so it is not recalculated as part of a rotation. the width will be
// updated manually after the rotation.
@@ -464,9 +499,12 @@
}
mExpandedViewContainer.addView(mTaskView, lp);
bringChildToFront(mTaskView);
- if (bubbleTaskView.isCreated()) {
- mTaskViewListener.onTaskCreated(
- bubbleTaskView.getTaskId(), bubbleTaskView.getComponentName());
+
+ if (!Flags.enableBubbleTaskViewListener()) {
+ if (bubbleTaskView.isCreated()) {
+ mCurrentTaskViewListener.onTaskCreated(
+ bubbleTaskView.getTaskId(), bubbleTaskView.getComponentName());
+ }
}
}
}
@@ -897,7 +935,12 @@
Log.w(TAG, "Stack is null for bubble: " + bubble);
return;
}
- boolean isNew = mBubble == null || didBackingContentChange(bubble);
+ boolean isNew;
+ if (mCurrentTaskViewListener instanceof BubbleTaskViewListener) {
+ isNew = ((BubbleTaskViewListener) mCurrentTaskViewListener).setBubble(bubble);
+ } else {
+ isNew = mBubble == null || didBackingContentChange(bubble);
+ }
boolean isUpdate = bubble != null && mBubble != null
&& bubble.getKey().equals(mBubble.getKey());
ProtoLog.d(WM_SHELL_BUBBLES, "BubbleExpandedView - update bubble=%s; isNew=%b; isUpdate=%b",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 5273a7c..33f1b94 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.bubbles;
+import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES;
import android.content.Context;
@@ -31,7 +32,7 @@
import androidx.annotation.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
-import com.android.launcher3.icons.IconNormalizer;
+import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider;
@@ -556,8 +557,7 @@
public float getPointerPosition(float bubblePosition) {
// TODO: I don't understand why it works but it does - why normalized in portrait
// & not in landscape? Am I missing ~2dp in the portrait expandedViewY calculation?
- final float normalizedSize = IconNormalizer.getNormalizedCircleSize(
- getBubbleSize());
+ final float normalizedSize = Math.round(ICON_VISIBLE_AREA_FACTOR * getBubbleSize());
return showBubblesVertically()
? bubblePosition + (getBubbleSize() / 2f)
: bubblePosition + (normalizedSize / 2f) - mPointerWidth;
@@ -906,7 +906,7 @@
if (isOverflow) {
return mOverflowHeight;
} else {
- return getBubbleBarExpandedViewHeightForLandscape();
+ return getBubbleBarExpandedViewHeight();
}
}
@@ -927,18 +927,23 @@
* | bottom inset ↕ | ↓
* |----------------------| --- mScreenRect.bottom
*/
- private int getBubbleBarExpandedViewHeightForLandscape() {
+ private int getBubbleBarExpandedViewHeight() {
int heightOfBubbleBarContainer =
mScreenRect.height() - getExpandedViewBottomForBubbleBar();
- // getting landscape height from screen rect
- int expandedViewHeight = Math.min(mScreenRect.width(), mScreenRect.height());
+ int expandedViewHeight;
+ if (Flags.enableBubbleBarOnPhones() && !mDeviceConfig.isLargeScreen()) {
+ // we're on a phone, use the max / height
+ expandedViewHeight = Math.max(mScreenRect.width(), mScreenRect.height());
+ } else {
+ // getting landscape height from screen rect
+ expandedViewHeight = Math.min(mScreenRect.width(), mScreenRect.height());
+ }
expandedViewHeight -= heightOfBubbleBarContainer; /* removing bubble container height */
expandedViewHeight -= mInsets.top; /* removing top inset */
expandedViewHeight -= mExpandedViewPadding; /* removing spacing */
return expandedViewHeight;
}
-
/** The bottom position of the expanded view when showing above the bubble bar. */
public int getExpandedViewBottomForBubbleBar() {
return mBubbleBarTopOnScreen - mExpandedViewPadding;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java
index a38debb..63d7134 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java
@@ -129,27 +129,28 @@
Context context =
mContext.createContextAsUser(
mBubble.getUser(), Context.CONTEXT_RESTRICTED);
- Intent fillInIntent = null;
+ Intent fillInIntent = new Intent();
+ fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
// First try get pending intent from the bubble
PendingIntent pi = mBubble.getPendingIntent();
if (pi == null) {
- // If null - create new one
+ // If null - create new one based on the bubble intent
pi = PendingIntent.getActivity(
context,
/* requestCode= */ 0,
- mBubble.getIntent()
- .addFlags(FLAG_ACTIVITY_MULTIPLE_TASK),
- PendingIntent.FLAG_IMMUTABLE
- | PendingIntent.FLAG_UPDATE_CURRENT,
+ mBubble.getIntent(),
+ // Needs to be mutable for the fillInIntent
+ PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
/* options= */ null);
- } else {
- fillInIntent = new Intent(pi.getIntent());
- fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
}
mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
} else if (isShortcutBubble) {
- options.setLaunchedFromBubble(true);
- options.setApplyActivityFlagsForBubbles(true);
+ if (mBubble.isChat()) {
+ options.setLaunchedFromBubble(true);
+ options.setApplyActivityFlagsForBubbles(true);
+ } else {
+ options.setApplyMultipleTaskFlagForShortcut(true);
+ }
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
options, launchBounds);
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
index a676f41..338ffe7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
@@ -21,6 +21,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.View.INVISIBLE;
import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE;
@@ -325,7 +326,7 @@
for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change chg = info.getChanges().get(i);
if (chg.getTaskInfo() == null) continue;
- if (chg.getMode() != TRANSIT_CHANGE) continue;
+ if (chg.getMode() != TRANSIT_CHANGE && chg.getMode() != TRANSIT_TO_FRONT) continue;
if (!mTaskInfo.token.equals(chg.getTaskInfo().token)) continue;
mStartBounds.set(chg.getStartAbsBounds());
// Converting a task into taskview, so treat as "new"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
index e3b0872..29837dc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
@@ -135,6 +135,7 @@
/** Shows the expanded view drop target at the requested {@link BubbleBarLocation location} */
public void showBubbleBarExtendedViewDropTarget(@NonNull BubbleBarLocation bubbleBarLocation) {
+ setVisibility(VISIBLE);
mBubbleExpandedViewPinController.showDropTarget(bubbleBarLocation);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 8377a35..df82091 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -227,7 +227,13 @@
/** Hides the IME for Bubbles when the device is locked. */
public void hideImeForBubblesWhenLocked(int displayId) {
PerDisplay pd = mImePerDisplay.get(displayId);
- pd.setImeInputTargetRequestedVisibility(false, pd.getImeSourceControl().getImeStatsToken());
+ InsetsSourceControl imeSourceControl = pd.getImeSourceControl();
+ if (imeSourceControl != null) {
+ ImeTracker.Token imeStatsToken = imeSourceControl.getImeStatsToken();
+ if (imeStatsToken != null) {
+ pd.setImeInputTargetRequestedVisibility(false, imeStatsToken);
+ }
+ }
}
/** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */
@@ -324,8 +330,10 @@
}
applyVisibilityToLeash(imeSourceControl);
}
- if (!mImeShowing) {
- removeImeSurface(mDisplayId);
+ if (!android.view.inputmethod.Flags.refactorInsetsController()) {
+ if (!mImeShowing) {
+ removeImeSurface(mDisplayId);
+ }
}
}
} else {
@@ -663,7 +671,9 @@
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
t.hide(animatingLeash);
- removeImeSurface(mDisplayId);
+ if (!android.view.inputmethod.Flags.refactorInsetsController()) {
+ removeImeSurface(mDisplayId);
+ }
if (android.view.inputmethod.Flags.refactorInsetsController()) {
setVisibleDirectly(false /* visible */, statsToken);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorController.kt
new file mode 100644
index 0000000..7a5bc13
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorController.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.common
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.graphics.RectF
+import android.view.SurfaceControl
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer
+import com.android.wm.shell.shared.annotations.ShellDesktopThread
+
+/**
+ * Controller to manage the indicators that show users the current position of the dragged window on
+ * the new display when performing drag move across displays.
+ */
+class MultiDisplayDragMoveIndicatorController(
+ private val displayController: DisplayController,
+ private val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
+ private val indicatorSurfaceFactory: MultiDisplayDragMoveIndicatorSurface.Factory,
+ @ShellDesktopThread private val desktopExecutor: ShellExecutor,
+) {
+ @ShellDesktopThread
+ private val dragIndicators =
+ mutableMapOf<Int, MutableMap<Int, MultiDisplayDragMoveIndicatorSurface>>()
+
+ /**
+ * Called during drag move, which started at [startDisplayId]. Updates the position and
+ * visibility of the drag move indicators for the [taskInfo] based on [boundsDp] on the
+ * destination displays ([displayIds]) as the dragged window moves. [transactionSupplier]
+ * provides a [SurfaceControl.Transaction] for applying changes to the indicator surfaces.
+ *
+ * It is executed on the [desktopExecutor] to prevent blocking the main thread and avoid jank,
+ * as creating and manipulating surfaces can be expensive.
+ */
+ fun onDragMove(
+ boundsDp: RectF,
+ startDisplayId: Int,
+ taskInfo: RunningTaskInfo,
+ displayIds: Set<Int>,
+ transactionSupplier: () -> SurfaceControl.Transaction,
+ ) {
+ desktopExecutor.execute {
+ for (displayId in displayIds) {
+ if (displayId == startDisplayId) {
+ // No need to render indicators on the original display where the drag started.
+ continue
+ }
+ val displayLayout = displayController.getDisplayLayout(displayId) ?: continue
+ val shouldBeVisible =
+ RectF.intersects(RectF(boundsDp), displayLayout.globalBoundsDp())
+ if (
+ dragIndicators[taskInfo.taskId]?.containsKey(displayId) != true &&
+ !shouldBeVisible
+ ) {
+ // Skip this display if:
+ // - It doesn't have an existing indicator that needs to be updated, AND
+ // - The latest dragged window bounds don't intersect with this display.
+ continue
+ }
+
+ val boundsPx =
+ MultiDisplayDragMoveBoundsCalculator.convertGlobalDpToLocalPxForRect(
+ boundsDp,
+ displayLayout,
+ )
+
+ // Get or create the inner map for the current task.
+ val dragIndicatorsForTask =
+ dragIndicators.getOrPut(taskInfo.taskId) { mutableMapOf() }
+ dragIndicatorsForTask[displayId]?.also { existingIndicator ->
+ val transaction = transactionSupplier()
+ existingIndicator.relayout(boundsPx, transaction, shouldBeVisible)
+ transaction.apply()
+ } ?: run {
+ val newIndicator =
+ indicatorSurfaceFactory.create(
+ taskInfo,
+ displayController.getDisplay(displayId),
+ )
+ newIndicator.show(
+ transactionSupplier(),
+ taskInfo,
+ rootTaskDisplayAreaOrganizer,
+ displayId,
+ boundsPx,
+ )
+ dragIndicatorsForTask[displayId] = newIndicator
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the drag ends. Disposes of the drag move indicator surfaces associated with the
+ * given [taskId]. [transactionSupplier] provides a [SurfaceControl.Transaction] for applying
+ * changes to the indicator surfaces.
+ *
+ * It is executed on the [desktopExecutor] to ensure that any pending `onDragMove` operations
+ * have completed before disposing of the surfaces.
+ */
+ fun onDragEnd(taskId: Int, transactionSupplier: () -> SurfaceControl.Transaction) {
+ desktopExecutor.execute {
+ dragIndicators.remove(taskId)?.values?.takeIf { it.isNotEmpty() }?.let { indicators ->
+ val transaction = transactionSupplier()
+ indicators.forEach { indicator ->
+ indicator.disposeSurface(transaction)
+ }
+ transaction.apply()
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorSurface.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorSurface.kt
new file mode 100644
index 0000000..d05d3b0
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorSurface.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.common
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.content.Context
+import android.graphics.Color
+import android.graphics.Rect
+import android.os.Trace
+import android.view.Display
+import android.view.SurfaceControl
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.ui.graphics.toArgb
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer
+import com.android.wm.shell.windowdecor.common.DecorThemeUtil
+import com.android.wm.shell.windowdecor.common.Theme
+
+/**
+ * Represents the indicator surface that visualizes the current position of a dragged window during
+ * a multi-display drag operation.
+ *
+ * This class manages the creation, display, and manipulation of the [SurfaceControl]s that act as a
+ * visual indicator, providing feedback to the user about the dragged window's location.
+ */
+class MultiDisplayDragMoveIndicatorSurface(
+ context: Context,
+ taskInfo: RunningTaskInfo,
+ display: Display,
+ surfaceControlBuilderFactory: Factory.SurfaceControlBuilderFactory,
+) {
+ private var isVisible = false
+
+ // A container surface to host the veil background
+ private var veilSurface: SurfaceControl? = null
+
+ private val decorThemeUtil = DecorThemeUtil(context)
+ private val lightColors = dynamicLightColorScheme(context)
+ private val darkColors = dynamicDarkColorScheme(context)
+
+ init {
+ Trace.beginSection("DragIndicatorSurface#init")
+
+ val displayId = display.displayId
+ veilSurface =
+ surfaceControlBuilderFactory
+ .create("Drag indicator veil of Task=${taskInfo.taskId} Display=$displayId")
+ .setColorLayer()
+ .setCallsite("DragIndicatorSurface#init")
+ .setHidden(true)
+ .build()
+
+ // TODO: b/383069173 - Add icon for the surface.
+
+ Trace.endSection()
+ }
+
+ /**
+ * Disposes the indicator surface using the provided [transaction].
+ */
+ fun disposeSurface(transaction: SurfaceControl.Transaction) {
+ veilSurface?.let { veil -> transaction.remove(veil) }
+ veilSurface = null
+ }
+
+ /**
+ * Shows the indicator surface at [bounds] on the specified display ([displayId]),
+ * visualizing the drag of the [taskInfo]. The indicator surface is shown using [transaction],
+ * and the [rootTaskDisplayAreaOrganizer] is used to reparent the surfaces.
+ */
+ fun show(
+ transaction: SurfaceControl.Transaction,
+ taskInfo: RunningTaskInfo,
+ rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
+ displayId: Int,
+ bounds: Rect,
+ ) {
+ val backgroundColor =
+ when (decorThemeUtil.getAppTheme(taskInfo)) {
+ Theme.LIGHT -> lightColors.surfaceContainer
+ Theme.DARK -> darkColors.surfaceContainer
+ }
+ val veil = veilSurface ?: return
+ isVisible = true
+
+ rootTaskDisplayAreaOrganizer.reparentToDisplayArea(displayId, veil, transaction)
+ relayout(bounds, transaction, shouldBeVisible = true)
+ transaction.show(veil).setColor(veil, Color.valueOf(backgroundColor.toArgb()).components)
+ transaction.apply()
+ }
+
+ /**
+ * Repositions and resizes the indicator surface based on [bounds] using [transaction]. The
+ * [shouldBeVisible] flag indicates whether the indicator is within the display after relayout.
+ */
+ fun relayout(bounds: Rect, transaction: SurfaceControl.Transaction, shouldBeVisible: Boolean) {
+ if (!isVisible && !shouldBeVisible) {
+ // No need to relayout if the surface is already invisible and should not be visible.
+ return
+ }
+ isVisible = shouldBeVisible
+ val veil = veilSurface ?: return
+ transaction.setCrop(veil, bounds)
+ }
+
+ /**
+ * Factory for creating [MultiDisplayDragMoveIndicatorSurface] instances with the [context].
+ */
+ class Factory(private val context: Context) {
+ private val surfaceControlBuilderFactory: SurfaceControlBuilderFactory =
+ object : SurfaceControlBuilderFactory {}
+
+ /**
+ * Creates a new [MultiDisplayDragMoveIndicatorSurface] instance to visualize the drag
+ * operation of the [taskInfo] on the given [display].
+ */
+ fun create(
+ taskInfo: RunningTaskInfo,
+ display: Display,
+ ) = MultiDisplayDragMoveIndicatorSurface(
+ context,
+ taskInfo,
+ display,
+ surfaceControlBuilderFactory,
+ )
+
+ /**
+ * Interface for creating [SurfaceControl.Builder] instances.
+ *
+ * This provides an abstraction over [SurfaceControl.Builder] creation for testing purposes.
+ */
+ interface SurfaceControlBuilderFactory {
+ fun create(name: String): SurfaceControl.Builder {
+ return SurfaceControl.Builder().setName(name)
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java
index 8e026f0..04e8d8d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java
@@ -24,6 +24,7 @@
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.DisplayMetrics;
+import android.util.Rational;
import android.util.Size;
import android.view.Gravity;
@@ -41,9 +42,6 @@
private static final String TAG = PipBoundsAlgorithm.class.getSimpleName();
private static final float INVALID_SNAP_FRACTION = -1f;
- // The same value (with the same name) is used in Launcher.
- private static final float PIP_ASPECT_RATIO_MISMATCH_THRESHOLD = 0.01f;
-
@NonNull private final PipBoundsState mPipBoundsState;
@NonNull protected final PipDisplayLayoutState mPipDisplayLayoutState;
@NonNull protected final SizeSpecSource mSizeSpecSource;
@@ -223,9 +221,8 @@
+ " than destination(%s)", sourceRectHint, destinationBounds);
return false;
}
- final float reportedRatio = destinationBounds.width() / (float) destinationBounds.height();
- final float inferredRatio = sourceRectHint.width() / (float) sourceRectHint.height();
- if (Math.abs(reportedRatio - inferredRatio) > PIP_ASPECT_RATIO_MISMATCH_THRESHOLD) {
+ if (!PictureInPictureParams.isSameAspectRatio(sourceRectHint,
+ new Rational(destinationBounds.width(), destinationBounds.height()))) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"isSourceRectHintValidForEnterPip=false, hint(%s) does not match"
+ " destination(%s) aspect ratio", sourceRectHint, destinationBounds);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java
index 381f0b0..3211307 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java
@@ -56,6 +56,7 @@
/** The function that will be run when this zone is tapped. */
private final Runnable mOnClickRunnable;
private SurfaceControlViewHost mViewHost;
+ private SurfaceControl mLeash;
/**
* @param isTopLeft Whether the desired touch zone will be on the top/left or the bottom/right
@@ -96,6 +97,7 @@
.setCallsite("OffscreenTouchZone::init");
builder.setParent(stageRoot);
SurfaceControl leash = builder.build();
+ mLeash = leash;
// Create a ViewHost that will hold our view.
WindowlessWindowManager wwm = new WindowlessWindowManager(config, leash, null);
@@ -117,10 +119,14 @@
}
/** Releases the touch zone when it's no longer needed. */
- void release() {
+ void release(SurfaceControl.Transaction t) {
if (mViewHost != null) {
mViewHost.release();
}
+ if (mLeash != null) {
+ t.remove(mLeash);
+ mLeash = null;
+ }
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 708e26c..720e8e5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -461,7 +461,14 @@
return;
}
- mOffscreenTouchZones.forEach(OffscreenTouchZone::release);
+ // TODO (b/349828130): It would be good to reuse a Transaction from StageCoordinator's
+ // mTransactionPool here, but passing it through SplitLayout and specifically
+ // SplitLayout.release() is complicated because that function is purposely called with a
+ // null value sometimes. When that function is refactored, we should also pass the
+ // Transaction in here.
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ mOffscreenTouchZones.forEach(touchZone -> touchZone.release(t));
+ t.apply();
mOffscreenTouchZones.clear();
}
@@ -975,8 +982,16 @@
final boolean shouldVeil =
insets.left != 0 || insets.top != 0 || insets.right != 0 || insets.bottom != 0;
+ // Find the "left/top"-most position of the app surface -- usually 0, but sometimes negative
+ // if the left/top app is offscreen.
+ int leftTop = 0;
+ if (Flags.enableFlexibleTwoAppSplit()) {
+ leftTop = mIsLeftRightSplit ? getTopLeftBounds().left : getTopLeftBounds().top;
+ }
+
final int dividerPos = mDividerSnapAlgorithm.calculateNonDismissingSnapTarget(
- mIsLeftRightSplit ? getBottomRightBounds().width() : getBottomRightBounds().height()
+ leftTop + (mIsLeftRightSplit
+ ? getBottomRightBounds().width() : getBottomRightBounds().height())
).position;
final Rect endBounds1 = new Rect();
final Rect endBounds2 = new Rect();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java
index ee3e39e..e9dc613 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java
@@ -162,22 +162,31 @@
}
}
+ /** Provide a Shell animation-thread Handler. */
+ @WMSingleton
+ @Provides
+ @ShellAnimationThread
+ public static Handler provideShellAnimationHandler() {
+ HandlerThread animThread = new HandlerThread("wmshell.anim", THREAD_PRIORITY_DISPLAY);
+ animThread.start();
+ if (Build.IS_DEBUGGABLE) {
+ animThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
+ animThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
+ MSGQ_SLOW_DELIVERY_THRESHOLD_MS);
+ }
+ return Handler.createAsync(animThread.getLooper());
+ }
+
/**
* Provide a Shell animation-thread Executor.
*/
@WMSingleton
@Provides
@ShellAnimationThread
- public static ShellExecutor provideShellAnimationExecutor() {
- HandlerThread shellAnimationThread = new HandlerThread("wmshell.anim",
- THREAD_PRIORITY_DISPLAY);
- shellAnimationThread.start();
- if (Build.IS_DEBUGGABLE) {
- shellAnimationThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
- shellAnimationThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
- MSGQ_SLOW_DELIVERY_THRESHOLD_MS);
- }
- return new HandlerExecutor(Handler.createAsync(shellAnimationThread.getLooper()));
+ public static ShellExecutor provideShellAnimationExecutor(
+ @ShellAnimationThread Handler animHandler
+ ) {
+ return new HandlerExecutor(animHandler);
}
/**
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 2fd8c27..5d5e4d3 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
@@ -68,6 +68,8 @@
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.LaunchAdjacentController;
+import com.android.wm.shell.common.MultiDisplayDragMoveIndicatorController;
+import com.android.wm.shell.common.MultiDisplayDragMoveIndicatorSurface;
import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -82,6 +84,7 @@
import com.android.wm.shell.desktopmode.DefaultDragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler;
import com.android.wm.shell.desktopmode.DesktopDisplayEventHandler;
+import com.android.wm.shell.desktopmode.DesktopDisplayModeController;
import com.android.wm.shell.desktopmode.DesktopImmersiveController;
import com.android.wm.shell.desktopmode.DesktopMinimizationTransitionHandler;
import com.android.wm.shell.desktopmode.DesktopMixedTransitionHandler;
@@ -428,9 +431,10 @@
Transitions transitions,
DisplayController displayController,
@ShellMainThread ShellExecutor mainExecutor,
- @ShellAnimationThread ShellExecutor animExecutor) {
+ @ShellAnimationThread ShellExecutor animExecutor,
+ @ShellAnimationThread Handler animHandler) {
return new FreeformTaskTransitionHandler(
- transitions, displayController, mainExecutor, animExecutor);
+ transitions, displayController, mainExecutor, animExecutor, animHandler);
}
@WMSingleton
@@ -989,7 +993,8 @@
WindowDecorTaskResourceLoader taskResourceLoader,
RecentsTransitionHandler recentsTransitionHandler,
DesktopModeCompatPolicy desktopModeCompatPolicy,
- DesktopTilingDecorViewModel desktopTilingDecorViewModel
+ DesktopTilingDecorViewModel desktopTilingDecorViewModel,
+ MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController
) {
if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) {
return Optional.empty();
@@ -1006,7 +1011,30 @@
windowDecorCaptionHandleRepository, activityOrientationChangeHandler,
focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger,
taskResourceLoader, recentsTransitionHandler, desktopModeCompatPolicy,
- desktopTilingDecorViewModel));
+ desktopTilingDecorViewModel,
+ multiDisplayDragMoveIndicatorController));
+ }
+
+ @WMSingleton
+ @Provides
+ static MultiDisplayDragMoveIndicatorController
+ providesMultiDisplayDragMoveIndicatorController(
+ DisplayController displayController,
+ RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+ MultiDisplayDragMoveIndicatorSurface.Factory
+ multiDisplayDragMoveIndicatorSurfaceFactory,
+ @ShellDesktopThread ShellExecutor desktopExecutor
+ ) {
+ return new MultiDisplayDragMoveIndicatorController(
+ displayController, rootTaskDisplayAreaOrganizer,
+ multiDisplayDragMoveIndicatorSurfaceFactory, desktopExecutor);
+ }
+
+ @WMSingleton
+ @Provides
+ static MultiDisplayDragMoveIndicatorSurface.Factory
+ providesMultiDisplayDragMoveIndicatorSurfaceFactory(Context context) {
+ return new MultiDisplayDragMoveIndicatorSurface.Factory(context);
}
@WMSingleton
@@ -1074,8 +1102,9 @@
Context context,
@ShellMainThread ShellExecutor mainExecutor,
@ShellAnimationThread ShellExecutor animExecutor,
- @ShellMainThread Handler handler) {
- return new CloseDesktopTaskTransitionHandler(context, mainExecutor, animExecutor, handler);
+ @ShellAnimationThread Handler animHandler) {
+ return new CloseDesktopTaskTransitionHandler(context, mainExecutor, animExecutor,
+ animHandler);
}
@WMSingleton
@@ -1083,9 +1112,10 @@
static DesktopMinimizationTransitionHandler provideDesktopMinimizationTransitionHandler(
@ShellMainThread ShellExecutor mainExecutor,
@ShellAnimationThread ShellExecutor animExecutor,
- DisplayController displayController) {
+ DisplayController displayController,
+ @ShellAnimationThread Handler mainHandler) {
return new DesktopMinimizationTransitionHandler(mainExecutor, animExecutor,
- displayController);
+ displayController, mainHandler);
}
@WMSingleton
@@ -1230,13 +1260,10 @@
static Optional<DesktopDisplayEventHandler> provideDesktopDisplayEventHandler(
Context context,
ShellInit shellInit,
- Transitions transitions,
DisplayController displayController,
- RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- IWindowManager windowManager,
Optional<DesktopUserRepositories> desktopUserRepositories,
Optional<DesktopTasksController> desktopTasksController,
- ShellTaskOrganizer shellTaskOrganizer
+ Optional<DesktopDisplayModeController> desktopDisplayModeController
) {
if (!DesktopModeStatus.canEnterDesktopMode(context)) {
return Optional.empty();
@@ -1245,13 +1272,10 @@
new DesktopDisplayEventHandler(
context,
shellInit,
- transitions,
displayController,
- rootTaskDisplayAreaOrganizer,
- windowManager,
desktopUserRepositories.get(),
desktopTasksController.get(),
- shellTaskOrganizer));
+ desktopDisplayModeController.get()));
}
@WMSingleton
@@ -1381,6 +1405,29 @@
return new DesktopModeUiEventLogger(uiEventLogger, packageManager);
}
+ @WMSingleton
+ @Provides
+ static Optional<DesktopDisplayModeController> provideDesktopDisplayModeController(
+ Context context,
+ Transitions transitions,
+ RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+ IWindowManager windowManager,
+ ShellTaskOrganizer shellTaskOrganizer,
+ DesktopWallpaperActivityTokenProvider desktopWallpaperActivityTokenProvider
+ ) {
+ if (!DesktopModeStatus.canEnterDesktopMode(context)) {
+ return Optional.empty();
+ }
+ return Optional.of(
+ new DesktopDisplayModeController(
+ context,
+ transitions,
+ rootTaskDisplayAreaOrganizer,
+ windowManager,
+ shellTaskOrganizer,
+ desktopWallpaperActivityTokenProvider));
+ }
+
//
// App zoom out
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandler.kt
index 1ce093e..b22a46e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandler.kt
@@ -37,7 +37,6 @@
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_CLOSE_TASK
import com.android.internal.jank.InteractionJankMonitor
import com.android.wm.shell.common.ShellExecutor
-import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.transition.Transitions
import java.util.function.Supplier
@@ -49,7 +48,7 @@
private val mainExecutor: ShellExecutor,
private val animExecutor: ShellExecutor,
private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() },
- @ShellMainThread private val handler: Handler,
+ private val animHandler: Handler,
) : Transitions.TransitionHandler {
private val runningAnimations = mutableMapOf<IBinder, List<Animator>>()
@@ -95,7 +94,7 @@
interactionJankMonitor.begin(
lastChangeLeash,
context,
- handler,
+ animHandler,
CUJ_DESKTOP_MODE_CLOSE_TASK,
)
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt
index c38558d..946e795 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt
@@ -16,41 +16,25 @@
package com.android.wm.shell.desktopmode
-import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
-import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
-import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
-import android.app.WindowConfiguration.windowingModeToString
import android.content.Context
-import android.provider.Settings
-import android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
import android.view.Display.DEFAULT_DISPLAY
-import android.view.IWindowManager
-import android.view.WindowManager.TRANSIT_CHANGE
import android.window.DesktopExperienceFlags
-import android.window.WindowContainerTransaction
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
import com.android.wm.shell.common.DisplayController.OnDisplaysChangedListener
import com.android.wm.shell.desktopmode.multidesks.OnDeskRemovedListener
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.sysui.ShellInit
-import com.android.wm.shell.transition.Transitions
/** Handles display events in desktop mode */
class DesktopDisplayEventHandler(
private val context: Context,
shellInit: ShellInit,
- private val transitions: Transitions,
private val displayController: DisplayController,
- private val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
- private val windowManager: IWindowManager,
private val desktopUserRepositories: DesktopUserRepositories,
private val desktopTasksController: DesktopTasksController,
- private val shellTaskOrganizer: ShellTaskOrganizer,
+ private val desktopDisplayModeController: DesktopDisplayModeController,
) : OnDisplaysChangedListener, OnDeskRemovedListener {
private val desktopRepository: DesktopRepository
@@ -70,7 +54,7 @@
override fun onDisplayAdded(displayId: Int) {
if (displayId != DEFAULT_DISPLAY) {
- refreshDisplayWindowingMode()
+ desktopDisplayModeController.refreshDisplayWindowingMode()
}
if (!supportsDesks(displayId)) {
@@ -88,7 +72,7 @@
override fun onDisplayRemoved(displayId: Int) {
if (displayId != DEFAULT_DISPLAY) {
- refreshDisplayWindowingMode()
+ desktopDisplayModeController.refreshDisplayWindowingMode()
}
// TODO: b/362720497 - move desks in closing display to the remaining desk.
@@ -102,65 +86,6 @@
}
}
- private fun refreshDisplayWindowingMode() {
- if (!Flags.enableDisplayWindowingModeSwitching()) return
- // TODO: b/375319538 - Replace the check with a DisplayManager API once it's available.
- val isExtendedDisplayEnabled =
- 0 !=
- Settings.Global.getInt(
- context.contentResolver,
- DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
- 0,
- )
- if (!isExtendedDisplayEnabled) {
- // No action needed in mirror or projected mode.
- return
- }
-
- val hasNonDefaultDisplay =
- rootTaskDisplayAreaOrganizer.getDisplayIds().any { displayId ->
- displayId != DEFAULT_DISPLAY
- }
- val targetDisplayWindowingMode =
- if (hasNonDefaultDisplay) {
- WINDOWING_MODE_FREEFORM
- } else {
- // Use the default display windowing mode when no non-default display.
- windowManager.getWindowingMode(DEFAULT_DISPLAY)
- }
- val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)
- requireNotNull(tdaInfo) { "DisplayAreaInfo of DEFAULT_DISPLAY must be non-null." }
- val currentDisplayWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
- if (currentDisplayWindowingMode == targetDisplayWindowingMode) {
- // Already in the target mode.
- return
- }
-
- logV(
- "As an external display is connected, changing default display's windowing mode from" +
- " ${windowingModeToString(currentDisplayWindowingMode)}" +
- " to ${windowingModeToString(targetDisplayWindowingMode)}"
- )
-
- val wct = WindowContainerTransaction()
- wct.setWindowingMode(tdaInfo.token, targetDisplayWindowingMode)
- shellTaskOrganizer
- .getRunningTasks(DEFAULT_DISPLAY)
- .filter { it.activityType == ACTIVITY_TYPE_STANDARD }
- .forEach {
- // TODO: b/391965153 - Reconsider the logic under multi-desk window hierarchy
- when (it.windowingMode) {
- currentDisplayWindowingMode -> {
- wct.setWindowingMode(it.token, currentDisplayWindowingMode)
- }
- targetDisplayWindowingMode -> {
- wct.setWindowingMode(it.token, WINDOWING_MODE_UNDEFINED)
- }
- }
- }
- transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null)
- }
-
// TODO: b/362720497 - connected/projected display considerations.
private fun supportsDesks(displayId: Int): Boolean =
DesktopModeStatus.canEnterDesktopMode(context)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayModeController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayModeController.kt
new file mode 100644
index 0000000..c9a63ff
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayModeController.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
+import android.app.WindowConfiguration.windowingModeToString
+import android.content.Context
+import android.provider.Settings
+import android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
+import android.view.Display.DEFAULT_DISPLAY
+import android.view.IWindowManager
+import android.view.WindowManager.TRANSIT_CHANGE
+import android.window.WindowContainerTransaction
+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.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.transition.Transitions
+
+/** Controls the display windowing mode in desktop mode */
+class DesktopDisplayModeController(
+ private val context: Context,
+ private val transitions: Transitions,
+ private val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
+ private val windowManager: IWindowManager,
+ private val shellTaskOrganizer: ShellTaskOrganizer,
+ private val desktopWallpaperActivityTokenProvider: DesktopWallpaperActivityTokenProvider,
+) {
+
+ fun refreshDisplayWindowingMode() {
+ if (!Flags.enableDisplayWindowingModeSwitching()) return
+ // TODO: b/375319538 - Replace the check with a DisplayManager API once it's available.
+ val isExtendedDisplayEnabled =
+ 0 !=
+ Settings.Global.getInt(
+ context.contentResolver,
+ DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
+ 0,
+ )
+ if (!isExtendedDisplayEnabled) {
+ // No action needed in mirror or projected mode.
+ return
+ }
+
+ val hasNonDefaultDisplay =
+ rootTaskDisplayAreaOrganizer.getDisplayIds().any { displayId ->
+ displayId != DEFAULT_DISPLAY
+ }
+ val targetDisplayWindowingMode =
+ if (hasNonDefaultDisplay) {
+ WINDOWING_MODE_FREEFORM
+ } else {
+ // Use the default display windowing mode when no non-default display.
+ windowManager.getWindowingMode(DEFAULT_DISPLAY)
+ }
+ val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)
+ requireNotNull(tdaInfo) { "DisplayAreaInfo of DEFAULT_DISPLAY must be non-null." }
+ val currentDisplayWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
+ if (currentDisplayWindowingMode == targetDisplayWindowingMode) {
+ // Already in the target mode.
+ return
+ }
+
+ logV(
+ "As an external display is connected, changing default display's windowing mode from" +
+ " ${windowingModeToString(currentDisplayWindowingMode)}" +
+ " to ${windowingModeToString(targetDisplayWindowingMode)}"
+ )
+
+ val wct = WindowContainerTransaction()
+ wct.setWindowingMode(tdaInfo.token, targetDisplayWindowingMode)
+ shellTaskOrganizer
+ .getRunningTasks(DEFAULT_DISPLAY)
+ .filter { it.activityType == ACTIVITY_TYPE_STANDARD }
+ .forEach {
+ // TODO: b/391965153 - Reconsider the logic under multi-desk window hierarchy
+ when (it.windowingMode) {
+ currentDisplayWindowingMode -> {
+ wct.setWindowingMode(it.token, currentDisplayWindowingMode)
+ }
+ targetDisplayWindowingMode -> {
+ wct.setWindowingMode(it.token, WINDOWING_MODE_UNDEFINED)
+ }
+ }
+ }
+ // The override windowing mode of DesktopWallpaper can be UNDEFINED on fullscreen-display
+ // right after the first launch while its resolved windowing mode is FULLSCREEN. We here
+ // it has the FULLSCREEN override windowing mode.
+ desktopWallpaperActivityTokenProvider.getToken(DEFAULT_DISPLAY)?.let { token ->
+ wct.setWindowingMode(token, WINDOWING_MODE_FULLSCREEN)
+ }
+ transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null)
+ }
+
+ private fun logV(msg: String, vararg arguments: Any?) {
+ ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
+ companion object {
+ private const val TAG = "DesktopDisplayModeController"
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt
index 728638d..7074e8b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt
@@ -18,14 +18,17 @@
import android.animation.Animator
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.os.Handler
import android.os.IBinder
-import android.util.DisplayMetrics
import android.view.SurfaceControl.Transaction
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.animation.MinimizeAnimator.create
import com.android.wm.shell.transition.Transitions
@@ -41,6 +44,7 @@
private val mainExecutor: ShellExecutor,
private val animExecutor: ShellExecutor,
private val displayController: DisplayController,
+ private val animHandler: Handler,
) : Transitions.TransitionHandler {
/** Shouldn't handle anything */
@@ -90,10 +94,30 @@
val t = Transaction()
val sc = change.leash
finishTransaction.hide(sc)
- val displayMetrics: DisplayMetrics? =
- change.taskInfo?.let {
- displayController.getDisplayContext(it.displayId)?.getResources()?.displayMetrics
- }
- return displayMetrics?.let { create(it, change, t, onAnimFinish) }
+ val displayContext =
+ change.taskInfo?.let { displayController.getDisplayContext(it.displayId) }
+ if (displayContext == null) {
+ logW(
+ "displayContext is null for taskId=${change.taskInfo?.taskId}, " +
+ "displayId=${change.taskInfo?.displayId}"
+ )
+ return null
+ }
+ return create(
+ displayContext,
+ change,
+ t,
+ onAnimFinish,
+ InteractionJankMonitor.getInstance(),
+ animHandler,
+ )
+ }
+
+ private companion object {
+ private fun logW(msg: String, vararg arguments: Any?) {
+ ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
+ const val TAG = "DesktopMinimizationTransitionHandler"
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
index eba1be5..7c6cf4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
@@ -208,6 +208,7 @@
/** Adds the given desk under the given display. */
fun addDesk(displayId: Int, deskId: Int) {
+ logD("addDesk for displayId=%d and deskId=%d", displayId, deskId)
desktopData.createDesk(displayId, deskId)
}
@@ -224,6 +225,7 @@
/** Sets the given desk as the active one in the given display. */
fun setActiveDesk(displayId: Int, deskId: Int) {
+ logD("setActiveDesk for displayId=%d and deskId=%d", displayId, deskId)
desktopData.setActiveDesk(displayId = displayId, deskId = deskId)
}
@@ -246,6 +248,7 @@
* TODO: b/389960283 - add explicit [deskId] argument.
*/
fun addTask(displayId: Int, taskId: Int, isVisible: Boolean) {
+ logD("addTask for displayId=%d, taskId=%d, isVisible=%b", displayId, taskId, isVisible)
val activeDesk =
checkNotNull(desktopData.getDefaultDesk(displayId)) {
"Expected desk in display: $displayId"
@@ -254,6 +257,13 @@
}
fun addTaskToDesk(displayId: Int, deskId: Int, taskId: Int, isVisible: Boolean) {
+ logD(
+ "addTaskToDesk for displayId=%d, deskId=%d, taskId=%d, isVisible=%b",
+ displayId,
+ deskId,
+ taskId,
+ isVisible,
+ )
addOrMoveTaskToTopOfDesk(displayId = displayId, deskId = deskId, taskId = taskId)
addActiveTaskToDesk(displayId = displayId, deskId = deskId, taskId = taskId)
updateTaskInDesk(
@@ -265,6 +275,12 @@
}
private fun addActiveTaskToDesk(displayId: Int, deskId: Int, taskId: Int) {
+ logD(
+ "addActiveTaskToDesk for displayId=%d, deskId=%d, taskId=%d",
+ displayId,
+ deskId,
+ taskId,
+ )
val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" }
// Removes task if it is active on another desk excluding this desk.
@@ -279,6 +295,7 @@
/** Removes task from active task list of desks excluding the [excludedDeskId]. */
@VisibleForTesting
fun removeActiveTask(taskId: Int, excludedDeskId: Int? = null) {
+ logD("removeActiveTask for taskId=%d, excludedDeskId=%d", taskId, excludedDeskId)
val affectedDisplays = mutableSetOf<Int>()
desktopData
.desksSequence()
@@ -303,6 +320,7 @@
taskId: Int,
notifyListeners: Boolean = true,
): Boolean {
+ logD("removeActiveTaskFromDesk for deskId=%d, taskId=%d", deskId, taskId)
val desk = desktopData.getDesk(deskId) ?: return false
if (desk.activeTasks.remove(taskId)) {
logD("Removed active task=%d from deskId=%d", taskId, desk.deskId)
@@ -314,29 +332,22 @@
return false
}
- /**
- * Adds given task to the closing task list for [displayId]'s active desk.
- *
- * TODO: b/389960283 - add explicit [deskId] argument.
- */
- fun addClosingTask(displayId: Int, taskId: Int) {
- val activeDesk =
- desktopData.getActiveDesk(displayId)
- ?: error("Expected active desk in display: $displayId")
- if (activeDesk.closingTasks.add(taskId)) {
- logD(
- "Added closing task=%d displayId=%d deskId=%d",
- taskId,
- displayId,
- activeDesk.deskId,
- )
+ /** Adds given task to the closing task list of its desk. */
+ fun addClosingTask(displayId: Int, deskId: Int?, taskId: Int) {
+ val desk =
+ deskId?.let { desktopData.getDesk(it) }
+ ?: checkNotNull(desktopData.getActiveDesk(displayId)) {
+ "Expected active desk in display: $displayId"
+ }
+ if (desk.closingTasks.add(taskId)) {
+ logD("Added closing task=%d displayId=%d deskId=%d", taskId, displayId, desk.deskId)
} else {
// If the task hasn't been removed from closing list after it disappeared.
logW(
"Task with taskId=%d displayId=%d deskId=%d is already closing",
taskId,
displayId,
- activeDesk.deskId,
+ desk.deskId,
)
}
}
@@ -374,7 +385,8 @@
* Checks if a task is the only visible, non-closing, non-minimized task on the active desk of
* the given display, or any display's active desk if [displayId] is [INVALID_DISPLAY].
*
- * TODO: b/389960283 - add explicit [deskId] argument.
+ * TODO: b/389960283 - consider forcing callers to use [isOnlyVisibleNonClosingTaskInDesk] with
+ * an explicit desk id instead of using this function and defaulting to the active one.
*/
fun isOnlyVisibleNonClosingTask(taskId: Int, displayId: Int = INVALID_DISPLAY): Boolean {
val activeDesks =
@@ -384,14 +396,27 @@
desktopData.getAllActiveDesks()
}
return activeDesks.any { desk ->
- desk.visibleTasks
- .subtract(desk.closingTasks)
- .subtract(desk.minimizedTasks)
- .singleOrNull() == taskId
+ isOnlyVisibleNonClosingTaskInDesk(
+ taskId = taskId,
+ deskId = desk.deskId,
+ displayId = desk.displayId,
+ )
}
}
/**
+ * Checks if a task is the only visible, non-closing, non-minimized task on the given desk of
+ * the given display.
+ */
+ fun isOnlyVisibleNonClosingTaskInDesk(taskId: Int, deskId: Int, displayId: Int): Boolean {
+ val desk = desktopData.getDesk(deskId) ?: return false
+ return desk.visibleTasks
+ .subtract(desk.closingTasks)
+ .subtract(desk.minimizedTasks)
+ .singleOrNull() == taskId
+ }
+
+ /**
* Returns the active tasks in the given display's active desk.
*
* TODO: b/389960283 - migrate callers to [getActiveTaskIdsInDesk].
@@ -456,7 +481,7 @@
/** Removes task from visible tasks of all desks except [excludedDeskId]. */
private fun removeVisibleTask(taskId: Int, excludedDeskId: Int? = null) {
- desktopData.forAllDesks { displayId, desk ->
+ desktopData.forAllDesks { _, desk ->
if (desk.deskId != excludedDeskId) {
removeVisibleTaskFromDesk(deskId = desk.deskId, taskId = taskId)
}
@@ -668,6 +693,11 @@
* TODO: b/389960283 - add explicit [deskId] argument.
*/
fun setTopTransparentFullscreenTaskId(displayId: Int, taskId: Int) {
+ logD(
+ "Top transparent fullscreen task set for display: taskId=%d, displayId=%d",
+ taskId,
+ displayId,
+ )
desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId = taskId
}
@@ -685,6 +715,11 @@
* TODO: b/389960283 - add explicit [deskId] argument.
*/
fun clearTopTransparentFullscreenTaskId(displayId: Int) {
+ logD(
+ "Top transparent fullscreen task cleared for display: taskId=%d, displayId=%d",
+ desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId,
+ displayId,
+ )
desktopData.getActiveDesk(displayId)?.topTransparentFullscreenTaskId = null
}
@@ -718,6 +753,12 @@
* Unminimizes the task if it is minimized.
*/
private fun addOrMoveTaskToTopOfDesk(displayId: Int, deskId: Int, taskId: Int) {
+ logD(
+ "addOrMoveTaskToTopOfDesk displayId=%d, deskId=%d, taskId=%d",
+ displayId,
+ deskId,
+ taskId,
+ )
val desk = desktopData.getDesk(deskId) ?: error("Could not find desk: $deskId")
logD("addOrMoveTaskToTopOfDesk: display=%d deskId=%d taskId=%d", displayId, deskId, taskId)
desktopData.forAllDesks { _, desk1 -> desk1.freeformTasksInZOrder.remove(taskId) }
@@ -738,6 +779,7 @@
* desk id instead of using this function and defaulting to the active one.
*/
fun minimizeTask(displayId: Int, taskId: Int) {
+ logD("minimizeTask displayId=%d, taskId=%d", displayId, taskId)
if (displayId == INVALID_DISPLAY) {
// When a task vanishes it doesn't have a displayId. Find the display of the task and
// mark it as minimized.
@@ -756,7 +798,7 @@
/** Minimizes the task in its desk. */
@VisibleForTesting
fun minimizeTaskInDesk(displayId: Int, deskId: Int, taskId: Int) {
- logD("Minimize Task: displayId=%d deskId=%d, task=%d", displayId, deskId, taskId)
+ logD("MinimizeTaskInDesk: displayId=%d deskId=%d, task=%d", displayId, deskId, taskId)
desktopData.getDesk(deskId)?.minimizedTasks?.add(taskId)
?: logD("Minimize task: No active desk found for task: taskId=%d", taskId)
updateTaskInDesk(displayId, deskId, taskId, isVisible = false)
@@ -771,12 +813,12 @@
* TODO: b/389960283 - consider using [unminimizeTaskFromDesk] instead.
*/
fun unminimizeTask(displayId: Int, taskId: Int) {
- logD("Unminimize Task: display=%d, task=%d", displayId, taskId)
+ logD("UnminimizeTask: display=%d, task=%d", displayId, taskId)
desktopData.forAllDesks(displayId) { desk -> unminimizeTaskFromDesk(desk.deskId, taskId) }
}
private fun unminimizeTaskFromDesk(deskId: Int, taskId: Int) {
- logD("Unminimize Task: deskId=%d, taskId=%d", deskId, taskId)
+ logD("Unminimize Task from desk: deskId=%d, taskId=%d", deskId, taskId)
if (desktopData.getDesk(deskId)?.minimizedTasks?.remove(taskId) != true) {
logW("Unminimize Task: deskId=%d, taskId=%d, no task data", deskId, taskId)
}
@@ -847,6 +889,7 @@
/** Removes the given desk and returns the active tasks in that desk. */
fun removeDesk(deskId: Int): Set<Int> {
+ logD("removeDesk %d", deskId)
val desk =
desktopData.getDesk(deskId)
?: return emptySet<Int>().also {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
index e831d5e..6034299 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
@@ -19,13 +19,16 @@
import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.window.DesktopModeFlags
+import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.freeform.TaskChangeListener
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
/** Manages tasks handling specific to Android Desktop Mode. */
class DesktopTaskChangeListener(private val desktopUserRepositories: DesktopUserRepositories) :
TaskChangeListener {
override fun onTaskOpening(taskInfo: RunningTaskInfo) {
+ logD("onTaskOpening for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
val desktopRepository: DesktopRepository =
desktopUserRepositories.getProfile(taskInfo.userId)
if (!isFreeformTask(taskInfo) && desktopRepository.isActiveTask(taskInfo.taskId)) {
@@ -38,6 +41,7 @@
}
override fun onTaskChanging(taskInfo: RunningTaskInfo) {
+ logD("onTaskChanging for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
val desktopRepository: DesktopRepository =
desktopUserRepositories.getProfile(taskInfo.userId)
if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
@@ -67,9 +71,15 @@
// of race conditions and possible duplications with [onTaskChanging].
override fun onNonTransitionTaskChanging(taskInfo: RunningTaskInfo) {
// TODO: b/367268953 - Propagate usages from FreeformTaskListener to this method.
+ logD(
+ "onNonTransitionTaskChanging for taskId=%d, displayId=%d",
+ taskInfo.taskId,
+ taskInfo.displayId,
+ )
}
override fun onTaskMovingToFront(taskInfo: RunningTaskInfo) {
+ logD("onTaskMovingToFront for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
val desktopRepository: DesktopRepository =
desktopUserRepositories.getProfile(taskInfo.userId)
if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
@@ -80,10 +90,12 @@
}
override fun onTaskMovingToBack(taskInfo: RunningTaskInfo) {
+ logD("onTaskMovingToBack for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
// TODO: b/367268953 - Connect this with DesktopRepository.
}
override fun onTaskClosing(taskInfo: RunningTaskInfo) {
+ logD("onTaskClosing for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
val desktopRepository: DesktopRepository =
desktopUserRepositories.getProfile(taskInfo.userId)
if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
@@ -104,4 +116,12 @@
private fun isFreeformTask(taskInfo: RunningTaskInfo): Boolean =
taskInfo.windowingMode == WINDOWING_MODE_FREEFORM
+
+ private fun logD(msg: String, vararg arguments: Any?) {
+ ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
+ companion object {
+ private const val TAG = "DesktopTaskChangeListener"
+ }
}
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 f7fe694..ca870d2 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
@@ -73,6 +73,7 @@
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_SNAP_RESIZE
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.protolog.ProtoLog
+import com.android.internal.util.LatencyTracker
import com.android.window.flags.Flags
import com.android.wm.shell.Flags.enableFlexibleSplit
import com.android.wm.shell.R
@@ -116,6 +117,7 @@
import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.recents.RecentsTransitionStateListener.RecentsTransitionState
import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING
+import com.android.wm.shell.shared.R as SharedR
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.annotations.ExternalThread
import com.android.wm.shell.shared.annotations.ShellDesktopThread
@@ -748,9 +750,9 @@
desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(
DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS.toInt()
)
- transition?.let {
- taskIdToMinimize?.let { taskId ->
- addPendingMinimizeTransition(it, taskId, MinimizeReason.TASK_LIMIT)
+ if (transition != null) {
+ taskIdToMinimize?.let {
+ addPendingMinimizeTransition(transition, it, MinimizeReason.TASK_LIMIT)
}
exitResult.asExit()?.runOnTransitionStart?.invoke(transition)
if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
@@ -765,6 +767,9 @@
} else {
taskRepository.setActiveDesk(displayId = taskInfo.displayId, deskId = deskId)
}
+ } else {
+ LatencyTracker.getInstance(context)
+ .onActionCancel(LatencyTracker.ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG)
}
}
@@ -797,6 +802,9 @@
): ((IBinder) -> Unit) {
val taskId = taskInfo.taskId
val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId)
+ if (deskId == null && DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+ error("Did not find desk for task: $taskId")
+ }
snapEventHandler.removeTaskIfTiled(displayId, taskId)
val shouldExitDesktop =
willExitDesktop(
@@ -814,7 +822,7 @@
shouldEndUpAtHome = true,
)
- taskRepository.addClosingTask(displayId, taskId)
+ taskRepository.addClosingTask(displayId = displayId, deskId = deskId, taskId = taskId)
taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(
doesAnyTaskRequireTaskbarRounding(displayId, taskId)
)
@@ -866,6 +874,10 @@
private fun minimizeTaskInner(taskInfo: RunningTaskInfo, minimizeReason: MinimizeReason) {
val taskId = taskInfo.taskId
val deskId = taskRepository.getDeskIdForTask(taskInfo.taskId)
+ if (deskId == null && DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+ logW("minimizeTaskInner: desk not found for task: ${taskInfo.taskId}")
+ return
+ }
val displayId = taskInfo.displayId
val wct = WindowContainerTransaction()
@@ -886,10 +898,26 @@
taskInfo = taskInfo,
reason = DesktopImmersiveController.ExitReason.MINIMIZED,
)
-
- wct.reorder(taskInfo.token, false)
- val isLastTask = taskRepository.isOnlyVisibleNonClosingTask(taskId, displayId)
- val transition: IBinder =
+ if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+ desksOrganizer.minimizeTask(
+ wct = wct,
+ deskId = checkNotNull(deskId) { "Expected non-null deskId" },
+ task = taskInfo,
+ )
+ } else {
+ wct.reorder(taskInfo.token, /* onTop= */ false)
+ }
+ val isLastTask =
+ if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+ taskRepository.isOnlyVisibleNonClosingTaskInDesk(
+ taskId = taskId,
+ deskId = checkNotNull(deskId) { "Expected non-null deskId" },
+ displayId = displayId,
+ )
+ } else {
+ taskRepository.isOnlyVisibleNonClosingTask(taskId = taskId, displayId = displayId)
+ }
+ val transition =
freeformTaskTransitionStarter.startMinimizedModeTransition(wct, taskId, isLastTask)
desktopTasksLimiter.ifPresent {
it.addPendingMinimizeChange(
@@ -1051,7 +1079,8 @@
)
}
- private fun startLaunchTransition(
+ @VisibleForTesting
+ fun startLaunchTransition(
transitionType: Int,
wct: WindowContainerTransaction,
launchingTaskId: Int?,
@@ -1059,34 +1088,52 @@
displayId: Int = DEFAULT_DISPLAY,
unminimizeReason: UnminimizeReason = UnminimizeReason.UNKNOWN,
): IBinder {
+ // TODO: b/397619806 - Consolidate sharable logic with [handleFreeformTaskLaunch].
+ var launchTransaction = wct
val taskIdToMinimize =
addAndGetMinimizeChanges(
displayId,
- wct,
+ launchTransaction,
newTaskId = launchingTaskId,
launchingNewIntent = launchingTaskId == null,
)
val exitImmersiveResult =
desktopImmersiveController.exitImmersiveIfApplicable(
- wct = wct,
+ wct = launchTransaction,
displayId = displayId,
excludeTaskId = launchingTaskId,
reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH,
)
+ var deskIdToActivate: Int? = null
+ if (
+ DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue &&
+ !isDesktopModeShowing(displayId)
+ ) {
+ deskIdToActivate =
+ checkNotNull(
+ launchingTaskId?.let { taskRepository.getDeskIdForTask(it) }
+ ?: getDefaultDeskId(displayId)
+ )
+ val activateDeskWct = WindowContainerTransaction()
+ addDeskActivationChanges(deskIdToActivate, activateDeskWct)
+ // Desk activation must be handled before app launch-related transactions.
+ activateDeskWct.merge(launchTransaction, /* transfer= */ true)
+ launchTransaction = activateDeskWct
+ }
val t =
if (remoteTransition == null) {
desktopMixedTransitionHandler.startLaunchTransition(
transitionType = transitionType,
- wct = wct,
+ wct = launchTransaction,
taskId = launchingTaskId,
minimizingTaskId = taskIdToMinimize,
exitingImmersiveTask = exitImmersiveResult.asExit()?.exitingTask,
)
} else if (taskIdToMinimize == null) {
val remoteTransitionHandler = OneShotRemoteHandler(mainExecutor, remoteTransition)
- transitions.startTransition(transitionType, wct, remoteTransitionHandler).also {
- remoteTransitionHandler.setTransition(it)
- }
+ transitions
+ .startTransition(transitionType, launchTransaction, remoteTransitionHandler)
+ .also { remoteTransitionHandler.setTransition(it) }
} else {
val remoteTransitionHandler =
DesktopWindowLimitRemoteHandler(
@@ -1095,9 +1142,9 @@
remoteTransition,
taskIdToMinimize,
)
- transitions.startTransition(transitionType, wct, remoteTransitionHandler).also {
- remoteTransitionHandler.setTransition(it)
- }
+ transitions
+ .startTransition(transitionType, launchTransaction, remoteTransitionHandler)
+ .also { remoteTransitionHandler.setTransition(it) }
}
if (taskIdToMinimize != null) {
addPendingMinimizeTransition(t, taskIdToMinimize, MinimizeReason.TASK_LIMIT)
@@ -1105,6 +1152,24 @@
if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) {
addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason)
}
+ if (
+ DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue &&
+ deskIdToActivate != null
+ ) {
+ if (DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue) {
+ desksTransitionObserver.addPendingTransition(
+ DeskTransition.ActivateDesk(
+ token = t,
+ displayId = displayId,
+ deskId = deskIdToActivate,
+ )
+ )
+ }
+
+ desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(
+ FREEFORM_ANIMATION_DURATION
+ )
+ }
exitImmersiveResult.asExit()?.runOnTransitionStart?.invoke(t)
return t
}
@@ -1227,9 +1292,9 @@
// home.
if (Flags.enablePerDisplayDesktopWallpaperActivity()) {
performDesktopExitCleanupIfNeeded(
- task.taskId,
- task.displayId,
- wct,
+ taskId = task.taskId,
+ displayId = task.displayId,
+ wct = wct,
forceToFullscreen = false,
// TODO: b/371096166 - Temporary turing home relaunch off to prevent home stealing
// display focus. Remove shouldEndUpAtHome = false when home focus handling
@@ -1796,6 +1861,7 @@
private fun performDesktopExitCleanupIfNeeded(
taskId: Int,
+ deskId: Int? = null,
displayId: Int,
wct: WindowContainerTransaction,
forceToFullscreen: Boolean,
@@ -1809,13 +1875,14 @@
// |RunOnTransitStart| when the transition is started.
return performDesktopExitCleanUp(
wct = wct,
- deskId = null,
+ deskId = deskId,
displayId = displayId,
willExitDesktop = true,
shouldEndUpAtHome = shouldEndUpAtHome,
)
}
+ /** TODO: b/394268248 - update [deskId] to be non-null. */
private fun performDesktopExitCleanUp(
wct: WindowContainerTransaction,
deskId: Int?,
@@ -2011,7 +2078,9 @@
}
val cornerRadius =
context.resources
- .getDimensionPixelSize(R.dimen.desktop_windowing_freeform_rounded_corner_radius)
+ .getDimensionPixelSize(
+ SharedR.dimen.desktop_windowing_freeform_rounded_corner_radius
+ )
.toFloat()
info.changes
.filter { it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM }
@@ -2366,17 +2435,28 @@
): WindowContainerTransaction? {
logV("handleTaskClosing")
if (!isDesktopModeShowing(task.displayId)) return null
+ val deskId = taskRepository.getDeskIdForTask(task.taskId)
+ if (deskId == null && DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+ return null
+ }
val wct = WindowContainerTransaction()
- performDesktopExitCleanupIfNeeded(
- task.taskId,
- task.displayId,
- wct,
- forceToFullscreen = false,
- )
+ val deactivationRunnable =
+ performDesktopExitCleanupIfNeeded(
+ taskId = task.taskId,
+ deskId = deskId,
+ displayId = task.displayId,
+ wct = wct,
+ forceToFullscreen = false,
+ )
+ deactivationRunnable?.invoke(transition)
if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) {
- taskRepository.addClosingTask(task.displayId, task.taskId)
+ taskRepository.addClosingTask(
+ displayId = task.displayId,
+ deskId = deskId,
+ taskId = task.taskId,
+ )
snapEventHandler.removeTaskIfTiled(task.displayId, task.taskId)
}
@@ -2580,9 +2660,9 @@
wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi())
performDesktopExitCleanupIfNeeded(
- taskInfo.taskId,
- taskInfo.displayId,
- wct,
+ taskId = taskInfo.taskId,
+ displayId = taskInfo.displayId,
+ wct = wct,
forceToFullscreen = false,
shouldEndUpAtHome = false,
)
@@ -2661,10 +2741,9 @@
activateDesk(deskId, remoteTransition)
}
- /** Activates the given desk. */
- fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) {
+ /** Activates the given desk but without starting a transition. */
+ fun addDeskActivationChanges(deskId: Int, wct: WindowContainerTransaction) {
val displayId = taskRepository.getDisplayForDesk(deskId)
- val wct = WindowContainerTransaction()
if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
prepareForDeskActivation(displayId, wct)
desksOrganizer.activateDesk(wct, deskId)
@@ -2677,6 +2756,13 @@
} else {
bringDesktopAppsToFront(displayId, wct)
}
+ }
+
+ /** Activates the given desk. */
+ fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) {
+ val displayId = taskRepository.getDisplayForDesk(deskId)
+ val wct = WindowContainerTransaction()
+ addDeskActivationChanges(deskId, wct)
val transitionType = transitionType(remoteTransition)
val handler =
@@ -3084,6 +3170,8 @@
val indicatorType = indicator.updateIndicatorType(inputCoordinates)
when (indicatorType) {
IndicatorType.TO_DESKTOP_INDICATOR -> {
+ LatencyTracker.getInstance(context)
+ .onActionStart(LatencyTracker.ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG)
// Start a new jank interaction for the drag release to desktop window animation.
interactionJankMonitor.begin(
taskSurface,
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 81b136d..f9ab359 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
@@ -26,7 +26,6 @@
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
@@ -176,28 +175,13 @@
return taskChange.mode == TRANSIT_TO_BACK
}
- override fun onTransitionStarting(transition: IBinder) {
- val mActiveTaskDetails = activeTransitionTokensAndTasks[transition]
- val info = mActiveTaskDetails?.transitionInfo ?: return
- val minimizeChange = getMinimizeChange(info, mActiveTaskDetails.taskId) ?: return
- // Begin minimize window CUJ instrumentation.
- interactionJankMonitor.begin(
- minimizeChange.leash,
- context,
- handler,
- CUJ_DESKTOP_MODE_MINIMIZE_WINDOW,
- )
- }
-
private fun getMinimizeChange(info: TransitionInfo, taskId: Int): TransitionInfo.Change? =
info.changes.find { change ->
change.taskInfo?.taskId == taskId && change.mode == TRANSIT_TO_BACK
}
override fun onTransitionMerged(merged: IBinder, playing: IBinder) {
- if (activeTransitionTokensAndTasks.remove(merged) != null) {
- interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
- }
+ activeTransitionTokensAndTasks.remove(merged)
pendingTransitionTokensAndTasks.remove(merged)?.let { taskToTransfer ->
pendingTransitionTokensAndTasks[playing] = taskToTransfer
}
@@ -209,13 +193,6 @@
}
override fun onTransitionFinished(transition: IBinder, aborted: Boolean) {
- if (activeTransitionTokensAndTasks.remove(transition) != null) {
- if (aborted) {
- interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
- } else {
- interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
- }
- }
pendingTransitionTokensAndTasks.remove(transition)
activeUnminimizeTransitionTokensAndTasks.remove(transition)
pendingUnminimizeTransitionTokensAndTasks.remove(transition)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
index 3ada988..9a97ae8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -186,14 +186,16 @@
for (change in info.changes) {
val taskInfo = change.taskInfo
if (taskInfo == null || taskInfo.taskId == -1) continue
- if (change.mode != TRANSIT_CLOSE) continue
- if (minimizingTask == null) {
- minimizingTask = getMinimizingTaskForClosingTransition(taskInfo)
+ if (
+ TransitionUtil.isClosingMode(change.mode) &&
+ DesktopWallpaperActivity.isWallpaperTask(taskInfo)
+ ) {
+ hasWallpaperClosing = true
}
- if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) {
- hasWallpaperClosing = true
+ if (change.mode == TRANSIT_CLOSE && minimizingTask == null) {
+ minimizingTask = getMinimizingTaskForClosingTransition(taskInfo)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DisplayDeskState.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DisplayDeskState.aidl
index 59add47..5f45192 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DisplayDeskState.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DisplayDeskState.aidl
@@ -18,13 +18,11 @@
/**
* Defines the state of desks on a display whose ID is `displayId`, which is:
- * - `canCreateDesks`: whether it's possible to create new desks on this display.
* - `activeDeskId`: the currently active desk Id, or `-1` if none is active.
* - `deskId`: the list of desk Ids of the available desks on this display.
*/
parcelable DisplayDeskState {
int displayId;
- boolean canCreateDesk;
int activeDeskId;
int[] deskIds;
}
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 0929ae1..cb23180 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
@@ -35,6 +35,7 @@
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.internal.util.LatencyTracker
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.animation.FloatProperties
import com.android.wm.shell.bubbles.BubbleController
@@ -42,7 +43,7 @@
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
-import com.android.wm.shell.protolog.ShellProtoLogGroup
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.animation.PhysicsAnimator
import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
@@ -119,10 +120,7 @@
dragToDesktopAnimator: MoveToDesktopAnimator,
) {
if (inProgress) {
- ProtoLog.v(
- ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
- "DragToDesktop: Drag to desktop transition already in progress.",
- )
+ logV("Drag to desktop transition already in progress.")
return
}
@@ -536,12 +534,14 @@
state.cancelState == CancelState.CANCEL_SPLIT_LEFT ||
state.cancelState == CancelState.CANCEL_SPLIT_RIGHT
) {
+ logV("mergeAnimation: cancel through split")
clearState()
return
}
// In case of bubble animation, finish the initial desktop drag animation, but keep the
// current animation running and have bubbles take over
if (info.type == TRANSIT_CONVERT_TO_BUBBLE) {
+ logV("mergeAnimation: convert-to-bubble")
state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null)
clearState()
return
@@ -561,6 +561,7 @@
state.startTransitionFinishCb
?: error("Start transition expected to be waiting for merge but wasn't")
if (isEndTransition) {
+ logV("mergeAnimation: end-transition, target=$mergeTarget")
setupEndDragToDesktop(
info,
startTransaction = startT,
@@ -568,8 +569,15 @@
)
// Call finishCallback to merge animation before startTransitionFinishCb is called
finishCallback.onTransitionFinished(/* wct= */ null)
+ LatencyTracker.getInstance(context)
+ .onActionEnd(LatencyTracker.ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG)
animateEndDragToDesktop(startTransaction = startT, startTransitionFinishCb)
- } else if (isCancelTransition) {
+ return
+ }
+ if (isCancelTransition) {
+ logV("mergeAnimation: cancel-transition, target=$mergeTarget")
+ LatencyTracker.getInstance(context)
+ .onActionCancel(LatencyTracker.ACTION_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG)
info.changes.forEach { change ->
startT.show(change.leash)
startTransactionFinishT.show(change.leash)
@@ -578,7 +586,9 @@
finishCallback.onTransitionFinished(/* wct= */ null)
startTransitionFinishCb.onTransitionFinished(/* wct= */ null)
clearState()
+ return
}
+ logW("unhandled merge transition: transitionInfo=$info")
}
protected open fun setupEndDragToDesktop(
@@ -719,10 +729,7 @@
return
}
if (state.startTransitionToken == transition) {
- ProtoLog.v(
- ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
- "DragToDesktop: onTransitionConsumed() start transition aborted",
- )
+ logV("onTransitionConsumed() start transition aborted")
state.startAborted = true
// The start-transition (DRAG_HOLD) is aborted, cancel its jank interaction.
interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD)
@@ -945,7 +952,16 @@
CANCEL_BUBBLE_RIGHT,
}
+ private fun logV(msg: String, vararg arguments: Any?) {
+ ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
+ private fun logW(msg: String, vararg arguments: Any?) {
+ ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
companion object {
+ private const val TAG = "DragToDesktopTransitionHandler"
/** The duration of the animation to commit or cancel the drag-to-desktop gesture. */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
const val DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS = 336L
@@ -1047,10 +1063,7 @@
val state = requireTransitionState()
val homeLeash = state.homeChange?.leash
if (homeLeash == null) {
- ProtoLog.e(
- ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
- "DragToDesktop: home leash is null",
- )
+ logE("home leash is null")
} else {
// Hide home on finish to prevent flickering when wallpaper activity flag is enabled
finishTransaction.hide(homeLeash)
@@ -1091,6 +1104,12 @@
val startBoundsWithOffset =
Rect(startBounds).apply { offset(startPosition.x.toInt(), startPosition.y.toInt()) }
+ logV(
+ "animateEndDragToDesktop: startBounds=$startBounds, endBounds=$endBounds, " +
+ "startScale=$startScale, startPosition=$startPosition, " +
+ "startBoundsWithOffset=$startBoundsWithOffset"
+ )
+
dragToDesktopStateListener?.onCommitToDesktopAnimationStart()
// Accept the merge by applying the merging transaction (applied by #showResizeVeil)
// and finish callback. Show the veil and position the task at the first frame before
@@ -1172,7 +1191,16 @@
.start()
}
+ private fun logV(msg: String, vararg arguments: Any?) {
+ ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
+ private fun logE(msg: String, vararg arguments: Any?) {
+ ProtoLog.e(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
companion object {
+ private const val TAG = "SpringDragToDesktopTransitionHandler"
/** The freeform tasks initial scale when committing the drag-to-desktop gesture. */
private val FREEFORM_TASKS_INITIAL_SCALE =
propertyValue("freeform_tasks_initial_scale", scale = 100f, default = 0.9f)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl
index 7ed1581..cefbd89 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl
@@ -28,7 +28,7 @@
* Called once when the listener first gets connected to initialize it with the current state of
* desks in Shell.
*/
- void onListenerConnected(in DisplayDeskState[] displayDeskStates);
+ void onListenerConnected(in DisplayDeskState[] displayDeskStates, boolean canCreateDesks);
/** Desktop tasks visibility has changed. Visible if at least 1 task is visible. */
void onTasksVisibilityChanged(int displayId, int visibleTasksCount);
@@ -49,10 +49,10 @@
void onExitDesktopModeTransitionStarted(int transitionDuration);
/**
- * Called when the conditions that allow the creation of a new desk on the display whose ID is
- * `displayId` changes to `canCreateDesks`. It's also called when a new display is added.
+ * Called when the conditions that allow the creation of a new desk changes. This is a global
+ * state for the entire device.
*/
- void onCanCreateDesksChanged(int displayId, boolean canCreateDesks);
+ void onCanCreateDesksChanged(boolean canCreateDesks);
/** Called when a desk whose ID is `deskId` is added to the display whose ID is `displayId`. */
void onDeskAdded(int displayId, int deskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksOrganizer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksOrganizer.kt
index 0f2f371..fc359d7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksOrganizer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksOrganizer.kt
@@ -40,9 +40,19 @@
task: ActivityManager.RunningTaskInfo,
)
+ /** Minimizes the given task of the given deskId. */
+ fun minimizeTask(
+ wct: WindowContainerTransaction,
+ deskId: Int,
+ task: ActivityManager.RunningTaskInfo,
+ )
+
/** Whether the change is for the given desk id. */
fun isDeskChange(change: TransitionInfo.Change, deskId: Int): Boolean
+ /** Whether the change is for a known desk. */
+ fun isDeskChange(change: TransitionInfo.Change): Boolean
+
/**
* Returns the desk id in which the task in the given change is located at the end of a
* transition, if any.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizer.kt
index 339932c..f576258 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizer.kt
@@ -15,7 +15,9 @@
*/
package com.android.wm.shell.desktopmode.multidesks
+import android.annotation.SuppressLint
import android.app.ActivityManager.RunningTaskInfo
+import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
@@ -25,6 +27,7 @@
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.DesktopExperienceFlags
import android.window.TransitionInfo
+import android.window.WindowContainerToken
import android.window.WindowContainerTransaction
import androidx.core.util.forEach
import com.android.internal.annotations.VisibleForTesting
@@ -43,8 +46,12 @@
private val shellTaskOrganizer: ShellTaskOrganizer,
) : DesksOrganizer, ShellTaskOrganizer.TaskListener {
- private val deskCreateRequests = mutableListOf<CreateRequest>()
- @VisibleForTesting val roots = SparseArray<DeskRoot>()
+ private val createDeskRootRequests = mutableListOf<CreateDeskRequest>()
+ @VisibleForTesting val deskRootsByDeskId = SparseArray<DeskRoot>()
+ private val createDeskMinimizationRootRequests =
+ mutableListOf<CreateDeskMinimizationRootRequest>()
+ @VisibleForTesting
+ val deskMinimizationRootsByDeskId: MutableMap<Int, DeskMinimizationRoot> = mutableMapOf()
init {
if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
@@ -57,7 +64,7 @@
override fun createDesk(displayId: Int, callback: OnCreateCallback) {
logV("createDesk in display: %d", displayId)
- deskCreateRequests += CreateRequest(displayId, callback)
+ createDeskRootRequests += CreateDeskRequest(displayId, callback)
shellTaskOrganizer.createRootTask(
displayId,
WINDOWING_MODE_FREEFORM,
@@ -68,14 +75,14 @@
override fun removeDesk(wct: WindowContainerTransaction, deskId: Int) {
logV("removeDesk %d", deskId)
- val desk = checkNotNull(roots[deskId]) { "Root not found for desk: $deskId" }
- wct.removeRootTask(desk.taskInfo.token)
+ deskRootsByDeskId[deskId]?.let { root -> wct.removeRootTask(root.token) }
+ deskMinimizationRootsByDeskId[deskId]?.let { root -> wct.removeRootTask(root.token) }
}
override fun activateDesk(wct: WindowContainerTransaction, deskId: Int) {
logV("activateDesk %d", deskId)
- val root = checkNotNull(roots[deskId]) { "Root not found for desk: $deskId" }
- wct.reorder(root.taskInfo.token, /* onTop= */ true)
+ val root = checkNotNull(deskRootsByDeskId[deskId]) { "Root not found for desk: $deskId" }
+ wct.reorder(root.token, /* onTop= */ true)
wct.setLaunchRoot(
/* container= */ root.taskInfo.token,
/* windowingModes= */ intArrayOf(WINDOWING_MODE_FREEFORM, WINDOWING_MODE_UNDEFINED),
@@ -85,7 +92,7 @@
override fun deactivateDesk(wct: WindowContainerTransaction, deskId: Int) {
logV("deactivateDesk %d", deskId)
- val root = checkNotNull(roots[deskId]) { "Root not found for desk: $deskId" }
+ val root = checkNotNull(deskRootsByDeskId[deskId]) { "Root not found for desk: $deskId" }
wct.setLaunchRoot(
/* container= */ root.taskInfo.token,
/* windowingModes= */ null,
@@ -98,16 +105,58 @@
deskId: Int,
task: RunningTaskInfo,
) {
- val root = roots[deskId] ?: error("Root not found for desk: $deskId")
+ val root = deskRootsByDeskId[deskId] ?: error("Root not found for desk: $deskId")
wct.setWindowingMode(task.token, WINDOWING_MODE_UNDEFINED)
wct.reparent(task.token, root.taskInfo.token, /* onTop= */ true)
}
- override fun isDeskChange(change: TransitionInfo.Change, deskId: Int): Boolean =
- roots.contains(deskId) && change.taskInfo?.taskId == deskId
+ override fun minimizeTask(wct: WindowContainerTransaction, deskId: Int, task: RunningTaskInfo) {
+ val deskRoot =
+ checkNotNull(deskRootsByDeskId[deskId]) { "Root not found for desk: $deskId" }
+ val minimizationRoot =
+ checkNotNull(deskMinimizationRootsByDeskId[deskId]) {
+ "Minimization root not found for desk: $deskId"
+ }
+ val taskId = task.taskId
+ if (taskId in minimizationRoot.children) {
+ logV("Task #$taskId is already minimized in desk #$deskId")
+ return
+ }
+ if (taskId !in deskRoot.children) {
+ logE("Attempted to minimize task=${task.taskId} in desk=$deskId but it was not a child")
+ return
+ }
+ wct.reparent(task.token, minimizationRoot.token, /* onTop= */ true)
+ }
- override fun getDeskAtEnd(change: TransitionInfo.Change): Int? =
- change.taskInfo?.parentTaskId?.takeIf { it in roots }
+ override fun isDeskChange(change: TransitionInfo.Change, deskId: Int): Boolean =
+ (isDeskRootChange(change) && change.taskId == deskId) ||
+ (getDeskMinimizationRootInChange(change)?.deskId == deskId)
+
+ override fun isDeskChange(change: TransitionInfo.Change): Boolean =
+ isDeskRootChange(change) || getDeskMinimizationRootInChange(change) != null
+
+ private fun isDeskRootChange(change: TransitionInfo.Change): Boolean =
+ change.taskId in deskRootsByDeskId
+
+ private fun getDeskMinimizationRootInChange(
+ change: TransitionInfo.Change
+ ): DeskMinimizationRoot? =
+ deskMinimizationRootsByDeskId.values.find { it.rootId == change.taskId }
+
+ private val TransitionInfo.Change.taskId: Int
+ get() = taskInfo?.taskId ?: INVALID_TASK_ID
+
+ override fun getDeskAtEnd(change: TransitionInfo.Change): Int? {
+ val parentTaskId = change.taskInfo?.parentTaskId ?: return null
+ if (parentTaskId in deskRootsByDeskId) {
+ return parentTaskId
+ }
+ val deskMinimizationRoot =
+ deskMinimizationRootsByDeskId.values.find { root -> root.rootId == parentTaskId }
+ ?: return null
+ return deskMinimizationRoot.deskId
+ }
override fun isDeskActiveAtEnd(change: TransitionInfo.Change, deskId: Int): Boolean =
change.taskInfo?.taskId == deskId &&
@@ -115,51 +164,176 @@
change.mode == TRANSIT_TO_FRONT
override fun onTaskAppeared(taskInfo: RunningTaskInfo, leash: SurfaceControl) {
- if (taskInfo.parentTaskId in roots) {
+ // Check whether this task is appearing inside a desk.
+ if (taskInfo.parentTaskId in deskRootsByDeskId) {
val deskId = taskInfo.parentTaskId
val taskId = taskInfo.taskId
logV("Task #$taskId appeared in desk #$deskId")
addChildToDesk(taskId = taskId, deskId = deskId)
return
}
- val deskId = taskInfo.taskId
- check(deskId !in roots) { "A root already exists for desk: $deskId" }
- val request =
- checkNotNull(deskCreateRequests.firstOrNull { it.displayId == taskInfo.displayId }) {
- "Task ${taskInfo.taskId} appeared without pending create request"
- }
- logV("Desk #$deskId appeared")
- roots[deskId] = DeskRoot(deskId, taskInfo, leash)
- deskCreateRequests.remove(request)
- request.onCreateCallback.onCreated(deskId)
+ // Check whether this task is appearing in a minimization root.
+ val minimizationRoot =
+ deskMinimizationRootsByDeskId.values.singleOrNull { it.rootId == taskInfo.parentTaskId }
+ if (minimizationRoot != null) {
+ val deskId = minimizationRoot.deskId
+ val taskId = taskInfo.taskId
+ logV("Task #$taskId was minimized in desk #$deskId ")
+ addChildToMinimizationRoot(taskId = taskId, deskId = deskId)
+ return
+ }
+ // The appearing task is a root (either a desk or a minimization root), it should not exist
+ // already.
+ check(taskInfo.taskId !in deskRootsByDeskId) {
+ "A root already exists for desk: ${taskInfo.taskId}"
+ }
+ check(deskMinimizationRootsByDeskId.values.none { it.rootId == taskInfo.taskId }) {
+ "A minimization root already exists with rootId: ${taskInfo.taskId}"
+ }
+
+ val appearingInDisplayId = taskInfo.displayId
+ // Check if there's any pending desk creation requests under this display.
+ val deskRequest =
+ createDeskRootRequests.firstOrNull { it.displayId == appearingInDisplayId }
+ if (deskRequest != null) {
+ // Appearing root matches desk request.
+ val deskId = taskInfo.taskId
+ logV("Desk #$deskId appeared")
+ deskRootsByDeskId[deskId] = DeskRoot(deskId, taskInfo, leash)
+ createDeskRootRequests.remove(deskRequest)
+ deskRequest.onCreateCallback.onCreated(deskId)
+ createDeskMinimizationRoot(displayId = appearingInDisplayId, deskId = deskId)
+ return
+ }
+ // Check if there's any pending minimization container creation requests under this display.
+ val deskMinimizationRootRequest =
+ createDeskMinimizationRootRequests.first { it.displayId == appearingInDisplayId }
+ val deskId = deskMinimizationRootRequest.deskId
+ logV("Minimization container for desk #$deskId appeared with id=${taskInfo.taskId}")
+ val deskMinimizationRoot = DeskMinimizationRoot(deskId, taskInfo, leash)
+ deskMinimizationRootsByDeskId[deskId] = deskMinimizationRoot
+ createDeskMinimizationRootRequests.remove(deskMinimizationRootRequest)
+ hideMinimizationRoot(deskMinimizationRoot)
}
override fun onTaskInfoChanged(taskInfo: RunningTaskInfo) {
- if (roots.contains(taskInfo.taskId)) {
+ if (deskRootsByDeskId.contains(taskInfo.taskId)) {
val deskId = taskInfo.taskId
- roots[deskId] = roots[deskId].copy(taskInfo = taskInfo)
+ deskRootsByDeskId[deskId] = deskRootsByDeskId[deskId].copy(taskInfo = taskInfo)
+ logV("Desk #$deskId's task info changed")
+ return
}
+ val minimizationRoot =
+ deskMinimizationRootsByDeskId.values.find { root -> root.rootId == taskInfo.taskId }
+ if (minimizationRoot != null) {
+ deskMinimizationRootsByDeskId.remove(minimizationRoot.deskId)
+ deskMinimizationRootsByDeskId[minimizationRoot.deskId] =
+ minimizationRoot.copy(taskInfo = taskInfo)
+ logV("Minimization root for desk#${minimizationRoot.deskId} task info changed")
+ return
+ }
+
+ val parentTaskId = taskInfo.parentTaskId
+ if (parentTaskId in deskRootsByDeskId) {
+ val deskId = taskInfo.parentTaskId
+ val taskId = taskInfo.taskId
+ logV("onTaskInfoChanged: Task #$taskId appeared in desk #$deskId")
+ addChildToDesk(taskId = taskId, deskId = deskId)
+ return
+ }
+ // Check whether this task is appearing in a minimization root.
+ val parentMinimizationRoot =
+ deskMinimizationRootsByDeskId.values.singleOrNull { it.rootId == parentTaskId }
+ if (parentMinimizationRoot != null) {
+ val deskId = parentMinimizationRoot.deskId
+ val taskId = taskInfo.taskId
+ logV("onTaskInfoChanged: Task #$taskId was minimized in desk #$deskId ")
+ addChildToMinimizationRoot(taskId = taskId, deskId = deskId)
+ return
+ }
+ logE("onTaskInfoChanged: unknown task: ${taskInfo.taskId}")
}
override fun onTaskVanished(taskInfo: RunningTaskInfo) {
- if (roots.contains(taskInfo.taskId)) {
+ if (deskRootsByDeskId.contains(taskInfo.taskId)) {
val deskId = taskInfo.taskId
- val deskRoot = roots[deskId]
+ val deskRoot = deskRootsByDeskId[deskId]
// Use the last saved taskInfo to obtain the displayId. Using the local one here will
// return -1 since the task is not unassociated with a display.
val displayId = deskRoot.taskInfo.displayId
logV("Desk #$deskId vanished from display #$displayId")
- roots.remove(deskId)
+ deskRootsByDeskId.remove(deskId)
return
}
+ val deskMinimizationRoot =
+ deskMinimizationRootsByDeskId.values.singleOrNull { it.rootId == taskInfo.taskId }
+ if (deskMinimizationRoot != null) {
+ logV("Minimization root for desk ${deskMinimizationRoot.deskId} vanished")
+ deskMinimizationRootsByDeskId.remove(deskMinimizationRoot.deskId)
+ return
+ }
+
+ // Check whether the vanishing task was a child of any desk.
// At this point, [parentTaskId] may be unset even if this is a task vanishing from a desk,
// so search through each root to remove this if it's a child.
- roots.forEach { deskId, deskRoot ->
+ deskRootsByDeskId.forEach { deskId, deskRoot ->
if (deskRoot.children.remove(taskInfo.taskId)) {
logV("Task #${taskInfo.taskId} vanished from desk #$deskId")
return
}
}
+ // Check whether the vanishing task was a child of the minimized root and remove it.
+ deskMinimizationRootsByDeskId.values.forEach { root ->
+ val taskId = taskInfo.taskId
+ if (root.children.remove(taskId)) {
+ logV("Task #$taskId vanished from minimization root of desk #${root.deskId}")
+ return
+ }
+ }
+ }
+
+ private fun createDeskMinimizationRoot(displayId: Int, deskId: Int) {
+ createDeskMinimizationRootRequests +=
+ CreateDeskMinimizationRootRequest(displayId = displayId, deskId = deskId)
+ shellTaskOrganizer.createRootTask(
+ displayId,
+ WINDOWING_MODE_FREEFORM,
+ /* listener = */ this,
+ /* removeWithTaskOrganizer = */ true,
+ )
+ }
+
+ @SuppressLint("MissingPermission")
+ private fun hideMinimizationRoot(root: DeskMinimizationRoot) {
+ shellTaskOrganizer.applyTransaction(
+ WindowContainerTransaction().apply { setHidden(root.token, /* hidden= */ true) }
+ )
+ }
+
+ private fun addChildToDesk(taskId: Int, deskId: Int) {
+ deskRootsByDeskId.forEach { _, deskRoot ->
+ if (deskRoot.deskId == deskId) {
+ deskRoot.children.add(taskId)
+ } else {
+ deskRoot.children.remove(taskId)
+ }
+ }
+ // A task cannot be in both a desk root and a minimization root at the same time, so make
+ // sure to remove them if needed.
+ deskMinimizationRootsByDeskId.values.forEach { root -> root.children.remove(taskId) }
+ }
+
+ private fun addChildToMinimizationRoot(taskId: Int, deskId: Int) {
+ deskMinimizationRootsByDeskId.forEach { _, minimizationRoot ->
+ if (minimizationRoot.deskId == deskId) {
+ minimizationRoot.children += taskId
+ } else {
+ minimizationRoot.children -= taskId
+ }
+ }
+ // A task cannot be in both a desk root and a minimization root at the same time, so make
+ // sure to remove them if needed.
+ deskRootsByDeskId.forEach { _, deskRoot -> deskRoot.children -= taskId }
}
@VisibleForTesting
@@ -168,34 +342,55 @@
val taskInfo: RunningTaskInfo,
val leash: SurfaceControl,
val children: MutableSet<Int> = mutableSetOf(),
+ ) {
+ val token: WindowContainerToken = taskInfo.token
+ }
+
+ @VisibleForTesting
+ data class DeskMinimizationRoot(
+ val deskId: Int,
+ val taskInfo: RunningTaskInfo,
+ val leash: SurfaceControl,
+ val children: MutableSet<Int> = mutableSetOf(),
+ ) {
+ val rootId: Int
+ get() = taskInfo.taskId
+
+ val token: WindowContainerToken = taskInfo.token
+ }
+
+ private data class CreateDeskRequest(
+ val displayId: Int,
+ val onCreateCallback: OnCreateCallback,
)
+ private data class CreateDeskMinimizationRootRequest(val displayId: Int, val deskId: Int)
+
+ private fun logV(msg: String, vararg arguments: Any?) {
+ ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
+ private fun logE(msg: String, vararg arguments: Any?) {
+ ProtoLog.e(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
+ }
+
override fun dump(pw: PrintWriter, prefix: String) {
val innerPrefix = "$prefix "
pw.println("$prefix$TAG")
pw.println("${innerPrefix}Desk Roots:")
- roots.forEach { deskId, root ->
+ deskRootsByDeskId.forEach { deskId, root ->
+ val minimizationRoot = deskMinimizationRootsByDeskId[deskId]
pw.println("$innerPrefix #$deskId visible=${root.taskInfo.isVisible}")
+ pw.println("$innerPrefix displayId=${root.taskInfo.displayId}")
pw.println("$innerPrefix children=${root.children}")
- }
- }
-
- private fun addChildToDesk(taskId: Int, deskId: Int) {
- roots.forEach { _, deskRoot ->
- if (deskRoot.deskId == deskId) {
- deskRoot.children.add(taskId)
- } else {
- deskRoot.children.remove(taskId)
+ pw.println("$innerPrefix minimization root:")
+ pw.println("$innerPrefix rootId=${minimizationRoot?.rootId}")
+ if (minimizationRoot != null) {
+ pw.println("$innerPrefix children=${minimizationRoot.children}")
}
}
}
- private data class CreateRequest(val displayId: Int, val onCreateCallback: OnCreateCallback)
-
- private fun logV(msg: String, vararg arguments: Any?) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
- }
-
companion object {
private const val TAG = "RootTaskDesksOrganizer"
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/README.md b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/README.md
index 3fad28a..a98ae55 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/README.md
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/README.md
@@ -9,6 +9,7 @@
4) [Threading model in the Shell](threading.md)
5) [Making changes in the Shell](changes.md)
6) [Extending the Shell for Products/OEMs](extending.md)
+6) [Shell transitions](transitions.md)
7) [Debugging in the Shell](debugging.md)
8) [Testing in the Shell](testing.md)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/transitions.md b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/transitions.md
new file mode 100644
index 0000000..dc23bb0
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/transitions.md
@@ -0,0 +1,118 @@
+# Shell transitions
+[Back to home](README.md)
+
+---
+
+## General
+
+General guides for using Shell Transitions can be found here:
+- [Shell transitions animation guide](http://go/shell-transit-anim)
+- [Hitchhiker's guide to transitions](http://go/transitions-book)
+
+## Transient-launch transitions
+<span style="color:orange">Use with care!</span>
+
+Transient-launch transitions are a way to handle non-atomic (ie. gestural) transitions by allowing
+WM Core to put participating activities into a transiently visible or hidden state for the duration
+of the animation and adding the ability to cancel the transition.
+
+For example, if you are launching an activity normally, WM Core will be updated
+at the start of the animation which includes pausing the previous activity and resuming the next
+activity (and subsequently the transition will reconcile that state via an animation).
+
+If you are transiently launching an activity though, WM Core will ensure that both the leaving
+activity and the incoming activity will be RESUMED for the duration of the transition duration. In
+addition, WM Core will track the position of the transient-launch activity in the window hierarchy
+prior to the launch, and allow Shell to restore it to that position if the transitions needs to be
+canceled.
+
+Starting a transient-launch transition can be done via the activity options (since the activity may
+not have been started yet):
+```kotlin
+val opts = ActivityOptions.makeBasic().setTransientLaunch()
+val wct = WindowContainerTransaction()
+wct.sendPendingIntent(pendingIntent, new Intent(), opts.toBundle())
+transitions.startTransition(TRANSIT_OPEN, wct, ...)
+```
+
+And restoring the transient order via a WCT:
+```kotlin
+val wct = WindowContainerTransaction()
+wct.restoreTransientOrder(transientLaunchContainerToken)
+transitions.startTransition(TRANSIT_RESTORE, wct, ...)
+```
+
+### <span style="color:orange">Considerations</span>
+
+Usage of transient-launch transitions should be done with consideration, there are a few gotchas
+that might result in subtle and hard-to-reproduce issues.
+
+#### Understanding the flow
+When starting a transient-launch transition, there are several possible outcomes:
+1) The transition finishes as normal: The user is committing the transition to the state requested
+ at the start of the transition. In such cases, you can simply finish the transition and the
+ states of the transiently shown/hidden activities will be updated to match the original state
+ that a non-transient transition would have (ie. closing activities will be stopped).
+
+2) The transition is interrupted: A change in the system results in the window hierarchy changing
+ in a way which may or may not affect the transient-launch activity. eg. We transiently-launch
+ home from app A, but then app B launches. In this case, WM attempts to create a new transition
+ reflecting the window hierarchy changes (ie. if B occludes Home in the above example, then the
+ transition will have Home TO_BACK, and B TO_FRONT).
+
+ At this point, the transition handler can choose to merge the incoming transition or not (to
+ queue it after this current transition). Take note of the next section for concerns re. bookend
+ transitions.
+
+3) The transition is canceled: The user is canceling the transition to the previous state. In such
+ cases, you need to store the `WindowContainerToken` for the task associated with the
+ transient-launch activity, and restore the transient order via the `WindowContainerTransaction`
+ API above. In some cases, if anything has been reordered since (ie. due to other merged
+ transitions), then you may also want to use `WindowContainerTransaction#reorder()` to place all
+ the relevant containers to their original order (provided via the change-order in the initial
+ launch transition).
+
+#### Finishing the transient-launch transition
+
+When restoring the transient order in the 3rd flow above, it is recommended to do it in a new
+transition and <span style="color:orange">**not**</span> via the WindowContainerTransaction in
+`TransitionFinishCallback#onTransitionFinished()` provided when starting the transition.
+
+Changes to the window hierarchy via the finish transaction are not applied in sync with other
+transitions that are collecting and aplying, and are also not observable in Shell in any way.
+Starting a new transition instead ensures both. (The finish transaction can still be used if there
+are non-transition affecting properties (ie. container properties) that need to be updated as a part
+of finishing the transient-launch transition).
+
+So the general idea is when restoring is:
+
+1) Start transient-launch transition START_T
+2) ...
+3) All done, start bookend transition END_T
+4) Handler receives END_T, merges it and then finishes START_T
+
+In practice it's not quite that simple, due to the ordering of transitions and extra care must be
+taken when using a new transition to prevent deadlocking when merging transitions.
+
+When a new transition arrives while a transient-launch transition is playing, the handler can
+choose to handle/merge the transition into the ongoing one, or skip merging to queue it up to be
+played after. In the above flow, we can see how this might result in a deadlock:
+
+Queueing END during merge:
+1) Start transient-launch transition START_T
+2) ...
+3) Incoming transition OTHER_T, choose to cancel START_T -> start bookend transition END_T, but don't merge OTHER_T
+3) Waiting for END_T... <span style="color:red">Deadlock!</span>
+
+Interrupt while pending END:
+1) Start transient-launch transition START_T
+2) ...
+3) All done, start bookend transition END_T
+3) Incoming transition OTHER_T occurs before END_T, but don't merge OTHER_T
+3) Waiting for END_T... <span style="color:red">Deadlock!</span>
+
+This means that when using transient-launch transitions with a bookend transition
+<span style="color:orange">requires</span> you to handle any incoming transitions if the bookend is
+ever queued (or already posted) after it. You can do so by preempting the bookend transition
+(finishing the transient-launch transition), or handling the merge of the new transition (so it
+doesn't queue).
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index b60fb5e..16e411e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -25,10 +25,12 @@
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
+import android.content.Context;
import android.graphics.Rect;
+import android.os.Handler;
import android.os.IBinder;
import android.util.ArrayMap;
-import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
@@ -38,6 +40,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.jank.InteractionJankMonitor;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.shared.animation.MinimizeAnimator;
@@ -52,11 +55,13 @@
*/
public class FreeformTaskTransitionHandler
implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
+ private static final String TAG = "FreeformTaskTransitionHandler";
private static final int CLOSE_ANIM_DURATION = 400;
private final Transitions mTransitions;
private final DisplayController mDisplayController;
private final ShellExecutor mMainExecutor;
private final ShellExecutor mAnimExecutor;
+ private final Handler mAnimHandler;
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
@@ -66,11 +71,13 @@
Transitions transitions,
DisplayController displayController,
ShellExecutor mainExecutor,
- ShellExecutor animExecutor) {
+ ShellExecutor animExecutor,
+ Handler animHandler) {
mTransitions = transitions;
mDisplayController = displayController;
mMainExecutor = mainExecutor;
mAnimExecutor = animExecutor;
+ mAnimHandler = animHandler;
}
@Override
@@ -123,13 +130,11 @@
@NonNull Transitions.TransitionFinishCallback finishCallback) {
boolean transitionHandled = false;
final ArrayList<Animator> animations = new ArrayList<>();
- final Runnable onAnimFinish = () -> {
+ final Runnable onAnimFinish = () -> mMainExecutor.execute(() -> {
if (!animations.isEmpty()) return;
- mMainExecutor.execute(() -> {
- mAnimations.remove(transition);
- finishCallback.onTransitionFinished(null /* wct */);
- });
- };
+ mAnimations.remove(transition);
+ finishCallback.onTransitionFinished(null /* wct */);
+ });
for (TransitionInfo.Change change : info.getChanges()) {
if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
continue;
@@ -234,18 +239,25 @@
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
SurfaceControl sc = change.getLeash();
finishT.hide(sc);
- final DisplayMetrics displayMetrics =
- mDisplayController
- .getDisplayContext(taskInfo.displayId).getResources().getDisplayMetrics();
+ final Context displayContext =
+ mDisplayController.getDisplayContext(taskInfo.displayId);
+ if (displayContext == null) {
+ Log.w(TAG, "No displayContext for displayId=" + taskInfo.displayId);
+ return false;
+ }
final Animator animator = MinimizeAnimator.create(
- displayMetrics,
+ displayContext,
change,
t,
(anim) -> {
- animations.remove(anim);
- onAnimFinish.run();
+ mMainExecutor.execute(() -> {
+ animations.remove(anim);
+ onAnimFinish.run();
+ });
return null;
- });
+ },
+ InteractionJankMonitor.getInstance(),
+ mAnimHandler);
animations.add(animator);
return true;
}
@@ -277,8 +289,10 @@
new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- animations.remove(animator);
- onAnimFinish.run();
+ mMainExecutor.execute(() -> {
+ animations.remove(animator);
+ onAnimFinish.run();
+ });
}
});
animations.add(animator);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java
index 118ad9c..fa14bc9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java
@@ -30,6 +30,7 @@
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import android.view.accessibility.IWindowSurfaceInfoCallback;
import android.window.ScreenCapture;
import androidx.annotation.BinderThread;
@@ -373,6 +374,13 @@
}
@Override
+ public void getWindowSurfaceInfo(IWindowSurfaceInfoCallback callback) {
+ // AbstractAccessibilityServiceConnection uses the standard
+ // IAccessibilityInteractionConnection for takeScreenshotOfWindow for Pip windows,
+ // so do nothing here.
+ }
+
+ @Override
public void clearAccessibilityFocus() throws RemoteException {
// Do nothing
}
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 99c9302..1ce24f7 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
@@ -404,6 +404,10 @@
mPipBoundsState.setBoundsStateForEntry(componentName, activityInfo, pictureInPictureParams,
mPipBoundsAlgorithm);
+
+ // Update the size spec in case aspect ratio is invariant, but display has changed
+ // since the last PiP session, or this is the first PiP session altogether.
+ mPipBoundsState.updateMinMaxSize(mPipBoundsState.getAspectRatio());
return mPipBoundsAlgorithm.getEntryDestinationBounds();
}
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 035c93d..97b3e5a 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
@@ -738,6 +738,13 @@
}
}
+ if (!mPipTransitionState.isInSwipePipToHomeTransition()) {
+ // Update the size spec in case aspect ratio is invariant, but display has changed
+ // since the last PiP session, or this is the first PiP session altogether.
+ // Skip the update if in swipe PiP to home, as this has already been done.
+ mPipBoundsState.updateMinMaxSize(mPipBoundsState.getAspectRatio());
+ }
+
// calculate the entry bounds and notify core to move task to pinned with final bounds
final Rect entryBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
mPipBoundsState.setBounds(entryBounds);
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 847a038..3e03e00 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
@@ -47,6 +47,7 @@
import android.app.ActivityTaskManager;
import android.app.IApplicationThread;
import android.app.PendingIntent;
+import android.app.WindowConfiguration;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
@@ -75,11 +76,11 @@
import com.android.internal.os.IResultReceiver;
import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.Flags;
-import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.shared.R;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.HomeTransitionObserver;
@@ -320,7 +321,7 @@
"RecentsTransitionHandler.mergeAnimation: no controller found");
return;
}
- controller.merge(info, startT, finishT, mergeTarget, finishCallback);
+ controller.merge(info, startT, finishT, finishCallback);
}
@Override
@@ -408,7 +409,8 @@
// next called.
private Pair<int[], TaskSnapshot[]> mPendingPauseSnapshotsForCancel;
- // Used to track a pending finish transition
+ // Used to track a pending finish transition, this is only non-null if
+ // enableRecentsBookendTransition() is enabled
private IBinder mPendingFinishTransition;
private IResultReceiver mPendingRunnerFinishCb;
@@ -917,7 +919,7 @@
*/
@SuppressLint("NewApi")
void merge(TransitionInfo info, SurfaceControl.Transaction startT,
- SurfaceControl.Transaction finishT, IBinder mergeTarget,
+ SurfaceControl.Transaction finishT,
Transitions.TransitionFinishCallback finishCallback) {
if (mFinishCB == null) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
@@ -927,16 +929,25 @@
return;
}
- if (Flags.enableRecentsBookendTransition()
- && info.getType() == TRANSIT_END_RECENTS_TRANSITION
- && mergeTarget == mTransition) {
- // This is a pending finish, so merge the end transition to trigger completing the
- // cleanup of the recents transition
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- "[%d] RecentsController.merge: TRANSIT_END_RECENTS_TRANSITION",
- mInstanceId);
- finishCallback.onTransitionFinished(null /* wct */);
- return;
+ if (Flags.enableRecentsBookendTransition()) {
+ if (info.getType() == TRANSIT_END_RECENTS_TRANSITION) {
+ // This is a pending finish, so merge the end transition to trigger completing
+ // the cleanup of the recents transition
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.merge: TRANSIT_END_RECENTS_TRANSITION",
+ mInstanceId);
+ consumeMerge(info, startT, finishT, finishCallback);
+ return;
+ } else if (mPendingFinishTransition != null) {
+ // This transition is interrupting a pending finish that was already sent, so
+ // pre-empt the pending finish transition since the state has already changed
+ // in the core
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.merge: Awaiting TRANSIT_END_RECENTS_TRANSITION",
+ mInstanceId);
+ onFinishInner(null /* wct */);
+ return;
+ }
}
if (info.getType() == TRANSIT_SLEEP) {
@@ -1210,16 +1221,12 @@
}
return;
}
+
// At this point, we are accepting the merge.
- startT.apply();
- // Since we're accepting the merge, update the finish transaction so that changes via
- // that transaction will be applied on top of those of the merged transitions
- mFinishTransaction = finishT;
+ consumeMerge(info, startT, finishT, finishCallback);
+
+ // Notify Launcher of the new opening tasks if necessary
boolean passTransitionInfo = ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX.isTrue();
- if (!passTransitionInfo) {
- // not using the incoming anim-only surfaces
- info.releaseAnimSurfaces();
- }
if (appearedTargets != null) {
try {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
@@ -1229,6 +1236,27 @@
Slog.e(TAG, "Error sending appeared tasks to recents animation", e);
}
}
+ }
+
+ /**
+ * Consumes the merge of the other given transition.
+ */
+ private void consumeMerge(TransitionInfo info, SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT,
+ Transitions.TransitionFinishCallback finishCallback) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.merge: consuming merge",
+ mInstanceId);
+
+ startT.apply();
+ // Since we're accepting the merge, update the finish transaction so that changes via
+ // that transaction will be applied on top of those of the merged transitions
+ mFinishTransaction = finishT;
+ boolean passTransitionInfo = ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX.isTrue();
+ if (!passTransitionInfo) {
+ // not using the incoming anim-only surfaces
+ info.releaseAnimSurfaces();
+ }
finishCallback.onTransitionFinished(null /* wct */);
}
@@ -1346,9 +1374,16 @@
final SurfaceControl.Transaction t = mFinishTransaction;
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ // The following code must set this if it is changing anything in core that might affect
+ // transitions as a part of finishing the recents transition
+ boolean requiresBookendTransition = false;
+
if (mKeyguardLocked && mRecentsTask != null) {
if (toHome) wct.reorder(mRecentsTask, true /* toTop */);
else wct.restoreTransientOrder(mRecentsTask);
+ // We are manipulating the window hierarchy, which should only be done with the
+ // bookend transition
+ requiresBookendTransition = true;
}
if (returningToApp) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " returning to app");
@@ -1365,6 +1400,9 @@
if (!mKeyguardLocked && mRecentsTask != null) {
wct.restoreTransientOrder(mRecentsTask);
}
+ // We are manipulating the window hierarchy, which should only be done with the
+ // bookend transition
+ requiresBookendTransition = true;
} else if (toHome && mOpeningSeparateHome && mPausingTasks != null) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " 3p launching home");
// Special situation where 3p launcher was changed during recents (this happens
@@ -1384,6 +1422,9 @@
if (!mKeyguardLocked && mRecentsTask != null) {
wct.restoreTransientOrder(mRecentsTask);
}
+ // We are manipulating the window hierarchy, which should only be done with the
+ // bookend transition
+ requiresBookendTransition = true;
} else {
if (mPausingSeparateHome) {
if (mOpeningTasks.isEmpty()) {
@@ -1484,13 +1525,21 @@
if (Flags.enableRecentsBookendTransition()) {
if (!wct.isEmpty()) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- "[%d] RecentsController.finishInner: "
- + "Queuing TRANSIT_END_RECENTS_TRANSITION", mInstanceId);
- mPendingRunnerFinishCb = runnerFinishCb;
- mPendingFinishTransition = mTransitions.startTransition(
- TRANSIT_END_RECENTS_TRANSITION, wct,
- new PendingFinishTransitionHandler());
+ if (requiresBookendTransition) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.finishInner: "
+ + "Queuing TRANSIT_END_RECENTS_TRANSITION", mInstanceId);
+ mPendingRunnerFinishCb = runnerFinishCb;
+ mPendingFinishTransition = mTransitions.startTransition(
+ TRANSIT_END_RECENTS_TRANSITION, wct,
+ new PendingFinishTransitionHandler());
+ } else {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.finishInner: Non-transition affecting wct",
+ mInstanceId);
+ mPendingRunnerFinishCb = runnerFinishCb;
+ onFinishInner(wct);
+ }
} else {
// If there's no work to do, just go ahead and clean up
mPendingRunnerFinishCb = runnerFinishCb;
@@ -1631,6 +1680,9 @@
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] PendingFinishTransitionHandler.startAnimation: "
+ + "Started pending finish transition", mInstanceId);
return false;
}
@@ -1644,10 +1696,15 @@
@Override
public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
@Nullable SurfaceControl.Transaction finishTransaction) {
+ if (mPendingFinishTransition == null) {
+ // The cleanup was pre-empted by an earlier transition, nothing there is nothing
+ // to do here
+ return;
+ }
// Once we have merged (or not if the WCT didn't result in any changes), then we can
// run the pending finish logic
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- "[%d] RecentsController.onTransitionConsumed: "
+ "[%d] PendingFinishTransitionHandler.onTransitionConsumed: "
+ "Consumed pending finish transition", mInstanceId);
onFinishInner(null /* wct */);
}
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 73b42d6..77a7c54 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
@@ -1317,6 +1317,10 @@
WindowContainerTransaction noFocus = new WindowContainerTransaction();
noFocus.setFocusable(mRootTaskInfo.token, false);
mSyncQueue.queue(noFocus);
+ // Remove touch layers, since offscreen apps coming onscreen will not need their touch
+ // layers anymore. populateTouchZones() is called in the end callback to inflate new touch
+ // layers in the appropriate places.
+ mSplitLayout.removeTouchZones();
mSplitLayout.playSwapAnimation(t, topLeftStage, bottomRightStage,
insets -> {
@@ -1337,6 +1341,7 @@
mSyncQueue.runInSync(st -> {
mSplitLayout.updateStateWithCurrentPosition();
updateSurfaceBounds(mSplitLayout, st, false /* applyResizingOffset */);
+ mSplitLayout.populateTouchZones();
// updateSurfaceBounds(), above, officially puts the two apps in their new
// stages. Starting on the next frame, all calculations are made using the
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 c5994f8..e132c5e 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
@@ -681,7 +681,8 @@
// C. The background of the adaptive icon is grayscale, and the foreground of the
// adaptive icon forms a certain contrast with the theme color.
// D. Didn't specify icon background color.
- if (!iconColor.mIsBgComplex && mTmpAttrs.mIconBgColor == Color.TRANSPARENT
+ if (iconForeground != null
+ && !iconColor.mIsBgComplex && mTmpAttrs.mIconBgColor == Color.TRANSPARENT
&& (isRgbSimilarInHsv(mThemeColor, iconColor.mBgColor)
|| (iconColor.mIsBgGrayscale
&& !isRgbSimilarInHsv(mThemeColor, iconColor.mFgColor)))) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
index cc962ac..caed194 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
@@ -368,8 +368,12 @@
mStartingWindowRecordManager.addRecord(taskId, tView);
}
- private void removeWindowInner(@NonNull View decorView, boolean hideView) {
+ private void removeWindowInner(@NonNull View decorView, StartingWindowRemovalInfo info,
+ boolean hideView) {
requestTopUi(false);
+ if (info.windowAnimationLeash != null && info.windowAnimationLeash.isValid()) {
+ info.windowAnimationLeash.release();
+ }
if (decorView.getParent() == null) {
Slog.w(TAG, "This root view has no parent, never been added to a ViewRootImpl?");
return;
@@ -452,22 +456,22 @@
if (mSplashView == null) {
// shouldn't happen, the app window may be drawn earlier than starting window?
Slog.e(TAG, "Found empty splash screen, remove!");
- removeWindowInner(mRootView, false);
+ removeWindowInner(mRootView, info, false);
return true;
}
if (immediately
|| mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
- removeWindowInner(mRootView, false);
+ removeWindowInner(mRootView, info, false);
} else {
if (info.playRevealAnimation) {
mSplashscreenContentDrawer.applyExitAnimation(mSplashView,
info.windowAnimationLeash, info.mainFrame,
- () -> removeWindowInner(mRootView, true),
+ () -> removeWindowInner(mRootView, info, true),
mCreateTime, info.roundedCornerRadius);
} else {
// the SplashScreenView has been copied to client, hide the view to skip
// default exit animation
- removeWindowInner(mRootView, true);
+ removeWindowInner(mRootView, info, true);
}
}
return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 743bd05..347dcff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -40,7 +40,6 @@
import android.window.WindowContainerTransaction;
import com.android.internal.protolog.ProtoLog;
-import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.activityembedding.ActivityEmbeddingController;
import com.android.wm.shell.common.ComponentUtils;
@@ -439,9 +438,6 @@
for (int i = 0; i < info.getRootCount(); ++i) {
out.addRoot(info.getRoot(i));
}
- if (!Flags.moveAnimationOptionsToChange()) {
- out.setAnimationOptions(info.getAnimationOptions());
- }
return out;
}
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 01428e6..e9c6ade 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
@@ -539,7 +539,7 @@
cornerRadius = 0;
}
- backgroundColorForTransition = getTransitionBackgroundColorIfSet(info, change, a,
+ backgroundColorForTransition = getTransitionBackgroundColorIfSet(change, a,
backgroundColorForTransition);
if (!isTask && a.getExtensionEdges() != 0x0) {
@@ -606,12 +606,7 @@
mTransactionPool, mMainExecutor, animRelOffset, cornerRadius,
clipRect);
- final TransitionInfo.AnimationOptions options;
- if (Flags.moveAnimationOptionsToChange()) {
- options = change.getAnimationOptions();
- } else {
- options = info.getAnimationOptions();
- }
+ final TransitionInfo.AnimationOptions options = change.getAnimationOptions();
if (options != null) {
attachThumbnail(animations, onAnimFinish, change, options, cornerRadius);
}
@@ -834,12 +829,7 @@
final boolean isOpeningType = TransitionUtil.isOpeningType(type);
final boolean enter = TransitionUtil.isOpeningType(changeMode);
final boolean isTask = change.getTaskInfo() != null;
- final TransitionInfo.AnimationOptions options;
- if (Flags.moveAnimationOptionsToChange()) {
- options = change.getAnimationOptions();
- } else {
- options = info.getAnimationOptions();
- }
+ final TransitionInfo.AnimationOptions options = change.getAnimationOptions();
final int overrideType = options != null ? options.getType() : ANIM_NONE;
final int userId = options != null ? options.getUserId() : UserHandle.USER_CURRENT;
final Rect endBounds = TransitionUtil.isClosingType(changeMode)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
index 1917996..938885c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -21,6 +21,7 @@
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE;
import static com.android.wm.shell.transition.Transitions.TransitionObserver;
import android.annotation.NonNull;
@@ -35,6 +36,7 @@
import com.android.wm.shell.common.SingleInstanceRemoteListener;
import com.android.wm.shell.shared.IHomeTransitionListener;
import com.android.wm.shell.shared.TransitionUtil;
+import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
/**
* The {@link TransitionObserver} that observes for transitions involving the home
@@ -48,6 +50,8 @@
private @NonNull final Context mContext;
private @NonNull final ShellExecutor mMainExecutor;
+ private Boolean mPendingHomeVisibilityUpdate;
+
public HomeTransitionObserver(@NonNull Context context,
@NonNull ShellExecutor mainExecutor) {
mContext = context;
@@ -59,28 +63,78 @@
@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction) {
+ if (BubbleAnythingFlagHelper.enableBubbleToFullscreen()) {
+ handleTransitionReadyWithBubbleAnything(info);
+ } else {
+ handleTransitionReady(info);
+ }
+ }
+
+ private void handleTransitionReady(@NonNull TransitionInfo info) {
for (TransitionInfo.Change change : info.getChanges()) {
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
- || taskInfo == null
+ if (taskInfo == null
+ || info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
+ || taskInfo.displayId != DEFAULT_DISPLAY
+ || taskInfo.taskId == -1
+ || !taskInfo.isRunning) {
+ continue;
+ }
+ Boolean homeVisibilityUpdate = getHomeVisibilityUpdate(info, change, taskInfo);
+ if (homeVisibilityUpdate != null) {
+ notifyHomeVisibilityChanged(homeVisibilityUpdate);
+ }
+ }
+ }
+
+ private void handleTransitionReadyWithBubbleAnything(@NonNull TransitionInfo info) {
+ Boolean homeVisibilityUpdate = null;
+ for (TransitionInfo.Change change : info.getChanges()) {
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (taskInfo == null
|| taskInfo.displayId != DEFAULT_DISPLAY
|| taskInfo.taskId == -1
|| !taskInfo.isRunning) {
continue;
}
- final int mode = change.getMode();
- final boolean isBackGesture = change.hasFlags(FLAG_BACK_GESTURE_ANIMATED);
- if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
- final boolean gestureToHomeTransition = isBackGesture
- && TransitionUtil.isClosingType(info.getType());
- if (gestureToHomeTransition || TransitionUtil.isClosingMode(mode)
- || (!isBackGesture && TransitionUtil.isOpeningMode(mode))) {
- notifyHomeVisibilityChanged(gestureToHomeTransition
- || TransitionUtil.isOpeningType(mode));
- }
+ Boolean update = getHomeVisibilityUpdate(info, change, taskInfo);
+ if (update != null) {
+ homeVisibilityUpdate = update;
}
}
+
+ if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP) {
+ // Do not apply at the start of desktop drag as that updates launcher UI visibility.
+ // Store the value and apply with a next transition if needed.
+ mPendingHomeVisibilityUpdate = homeVisibilityUpdate;
+ return;
+ }
+
+ if (info.getType() == TRANSIT_CONVERT_TO_BUBBLE && homeVisibilityUpdate == null) {
+ // We are converting to bubble and we did not get a change to home visibility in this
+ // transition. Apply the value from start of drag.
+ homeVisibilityUpdate = mPendingHomeVisibilityUpdate;
+ }
+ if (homeVisibilityUpdate != null) {
+ mPendingHomeVisibilityUpdate = null;
+ notifyHomeVisibilityChanged(homeVisibilityUpdate);
+ }
+ }
+
+ private Boolean getHomeVisibilityUpdate(TransitionInfo info,
+ TransitionInfo.Change change, ActivityManager.RunningTaskInfo taskInfo) {
+ final int mode = change.getMode();
+ final boolean isBackGesture = change.hasFlags(FLAG_BACK_GESTURE_ANIMATED);
+ if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
+ final boolean gestureToHomeTransition = isBackGesture
+ && TransitionUtil.isClosingType(info.getType());
+ if (gestureToHomeTransition || TransitionUtil.isClosingMode(mode)
+ || (!isBackGesture && TransitionUtil.isOpeningMode(mode))) {
+ return gestureToHomeTransition || TransitionUtil.isOpeningType(mode);
+ }
+ }
+ return null;
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
index 4feb475..7984bce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
@@ -58,7 +58,6 @@
import com.android.internal.R;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.protolog.ProtoLog;
-import com.android.window.flags.Flags;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.TransitionUtil;
@@ -78,12 +77,7 @@
final boolean isFreeform = isTask && change.getTaskInfo().isFreeform();
final boolean isCoveredByOpaqueFullscreenChange =
isCoveredByOpaqueFullscreenChange(info, change);
- final TransitionInfo.AnimationOptions options;
- if (Flags.moveAnimationOptionsToChange()) {
- options = change.getAnimationOptions();
- } else {
- options = info.getAnimationOptions();
- }
+ final TransitionInfo.AnimationOptions options = change.getAnimationOptions();
final int overrideType = options != null ? options.getType() : ANIM_NONE;
int animAttr = 0;
boolean translucent = false;
@@ -279,16 +273,10 @@
* the given transition animation.
*/
@ColorInt
- public static int getTransitionBackgroundColorIfSet(@NonNull TransitionInfo info,
- @NonNull TransitionInfo.Change change, @NonNull Animation a,
- @ColorInt int defaultColor) {
+ public static int getTransitionBackgroundColorIfSet(@NonNull TransitionInfo.Change change,
+ @NonNull Animation a, @ColorInt int defaultColor) {
if (!a.getShowBackdrop()) {
return defaultColor;
- }
- if (!Flags.moveAnimationOptionsToChange() && info.getAnimationOptions() != null
- && info.getAnimationOptions().getBackgroundColor() != 0) {
- // If available use the background color provided through AnimationOptions
- return info.getAnimationOptions().getBackgroundColor();
} else if (a.getBackdropColor() != 0) {
// Otherwise fallback on the background color provided through the animation
// definition.
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 5a6ea21..cf139a0 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
@@ -103,6 +103,7 @@
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.MultiDisplayDragMoveIndicatorController;
import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -258,6 +259,7 @@
private final RecentsTransitionHandler mRecentsTransitionHandler;
private final DesktopModeCompatPolicy mDesktopModeCompatPolicy;
private final DesktopTilingDecorViewModel mDesktopTilingDecorViewModel;
+ private final MultiDisplayDragMoveIndicatorController mMultiDisplayDragMoveIndicatorController;
public DesktopModeWindowDecorViewModel(
Context context,
@@ -296,7 +298,8 @@
WindowDecorTaskResourceLoader taskResourceLoader,
RecentsTransitionHandler recentsTransitionHandler,
DesktopModeCompatPolicy desktopModeCompatPolicy,
- DesktopTilingDecorViewModel desktopTilingDecorViewModel) {
+ DesktopTilingDecorViewModel desktopTilingDecorViewModel,
+ MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController) {
this(
context,
shellExecutor,
@@ -340,7 +343,8 @@
taskResourceLoader,
recentsTransitionHandler,
desktopModeCompatPolicy,
- desktopTilingDecorViewModel);
+ desktopTilingDecorViewModel,
+ multiDisplayDragMoveIndicatorController);
}
@VisibleForTesting
@@ -387,7 +391,8 @@
WindowDecorTaskResourceLoader taskResourceLoader,
RecentsTransitionHandler recentsTransitionHandler,
DesktopModeCompatPolicy desktopModeCompatPolicy,
- DesktopTilingDecorViewModel desktopTilingDecorViewModel) {
+ DesktopTilingDecorViewModel desktopTilingDecorViewModel,
+ MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController) {
mContext = context;
mMainExecutor = shellExecutor;
mMainHandler = mainHandler;
@@ -460,6 +465,7 @@
mDesktopModeCompatPolicy = desktopModeCompatPolicy;
mDesktopTilingDecorViewModel = desktopTilingDecorViewModel;
mDesktopTasksController.setSnapEventHandler(this);
+ mMultiDisplayDragMoveIndicatorController = multiDisplayDragMoveIndicatorController;
shellInit.addInitCallback(this::onInit, this);
}
@@ -1759,7 +1765,8 @@
mTransitions,
mInteractionJankMonitor,
mTransactionFactory,
- mMainHandler);
+ mMainHandler,
+ mMultiDisplayDragMoveIndicatorController);
windowDecoration.setTaskDragResizer(taskPositioner);
final DesktopModeTouchEventListener touchEventListener =
@@ -2056,7 +2063,8 @@
Transitions transitions,
InteractionJankMonitor interactionJankMonitor,
Supplier<SurfaceControl.Transaction> transactionFactory,
- Handler handler) {
+ Handler handler,
+ MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController) {
final TaskPositioner taskPositioner = DesktopModeStatus.isVeiledResizeEnabled()
// TODO(b/383632995): Update when the flag is launched.
? (Flags.enableConnectedDisplaysWindowDrag()
@@ -2067,7 +2075,8 @@
dragEventListener,
transitions,
interactionJankMonitor,
- handler)
+ handler,
+ multiDisplayDragMoveIndicatorController)
: new VeiledResizeTaskPositioner(
taskOrganizer,
windowDecoration,
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 dca376f..6165dbf 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
@@ -1069,7 +1069,8 @@
private static int getCornerRadius(@NonNull Context context, int layoutResId) {
if (layoutResId == R.layout.desktop_mode_app_header) {
return loadDimensionPixelSize(context.getResources(),
- R.dimen.desktop_windowing_freeform_rounded_corner_radius);
+ com.android.wm.shell.shared.R.dimen
+ .desktop_windowing_freeform_rounded_corner_radius);
}
return INVALID_CORNER_RADIUS;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
index bb20292..c6cb62d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
@@ -17,6 +17,7 @@
import android.graphics.PointF
import android.graphics.Rect
+import android.hardware.display.DisplayTopology
import android.os.Handler
import android.os.IBinder
import android.os.Looper
@@ -32,10 +33,10 @@
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.MultiDisplayDragMoveBoundsCalculator
+import com.android.wm.shell.common.MultiDisplayDragMoveIndicatorController
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.transition.Transitions
import java.util.concurrent.TimeUnit
-import java.util.function.Supplier
/**
* A task positioner that also takes into account resizing a
@@ -49,11 +50,12 @@
private val desktopWindowDecoration: DesktopModeWindowDecoration,
private val displayController: DisplayController,
dragEventListener: DragPositioningCallbackUtility.DragEventListener,
- private val transactionSupplier: Supplier<SurfaceControl.Transaction>,
+ private val transactionSupplier: () -> SurfaceControl.Transaction,
private val transitions: Transitions,
private val interactionJankMonitor: InteractionJankMonitor,
@ShellMainThread private val handler: Handler,
-) : TaskPositioner, Transitions.TransitionHandler {
+ private val multiDisplayDragMoveIndicatorController: MultiDisplayDragMoveIndicatorController,
+) : TaskPositioner, Transitions.TransitionHandler, DisplayController.OnDisplaysChangedListener {
private val dragEventListeners =
mutableListOf<DragPositioningCallbackUtility.DragEventListener>()
private val stableBounds = Rect()
@@ -71,6 +73,7 @@
private var isResizingOrAnimatingResize = false
@Surface.Rotation private var rotation = 0
private var startDisplayId = 0
+ private val displayIds = mutableSetOf<Int>()
constructor(
taskOrganizer: ShellTaskOrganizer,
@@ -80,19 +83,22 @@
transitions: Transitions,
interactionJankMonitor: InteractionJankMonitor,
@ShellMainThread handler: Handler,
+ multiDisplayDragMoveIndicatorController: MultiDisplayDragMoveIndicatorController,
) : this(
taskOrganizer,
windowDecoration,
displayController,
dragEventListener,
- Supplier<SurfaceControl.Transaction> { SurfaceControl.Transaction() },
+ { SurfaceControl.Transaction() },
transitions,
interactionJankMonitor,
handler,
+ multiDisplayDragMoveIndicatorController,
)
init {
dragEventListeners.add(dragEventListener)
+ displayController.addDisplayWindowListener(this)
}
override fun onDragPositioningStart(ctrlType: Int, displayId: Int, x: Float, y: Float): Rect {
@@ -164,7 +170,7 @@
createLongTimeoutJankConfigBuilder(Cuj.CUJ_DESKTOP_MODE_DRAG_WINDOW)
)
- val t = transactionSupplier.get()
+ val t = transactionSupplier()
val startDisplayLayout = displayController.getDisplayLayout(startDisplayId)
val currentDisplayLayout = displayController.getDisplayLayout(displayId)
@@ -196,7 +202,13 @@
)
)
- // TODO(b/383069173): Render drag indicator(s)
+ multiDisplayDragMoveIndicatorController.onDragMove(
+ boundsDp,
+ startDisplayId,
+ desktopWindowDecoration.mTaskInfo,
+ displayIds,
+ transactionSupplier,
+ )
t.setPosition(
desktopWindowDecoration.leash,
@@ -267,7 +279,10 @@
)
)
- // TODO(b/383069173): Clear drag indicator(s)
+ multiDisplayDragMoveIndicatorController.onDragEnd(
+ desktopWindowDecoration.mTaskInfo.taskId,
+ transactionSupplier,
+ )
}
interactionJankMonitor.end(Cuj.CUJ_DESKTOP_MODE_DRAG_WINDOW)
@@ -348,6 +363,14 @@
dragEventListeners.remove(dragEventListener)
}
+ override fun onTopologyChanged(topology: DisplayTopology) {
+ // TODO: b/383069173 - Cancel window drag when topology changes happen during drag.
+
+ displayIds.clear()
+ val displayBounds = topology.getAbsoluteBounds()
+ displayIds.addAll(List(displayBounds.size()) { displayBounds.keyAt(it) })
+ }
+
companion object {
// Timeout used for resize and drag CUJs, this is longer than the default timeout to avoid
// timing out in the middle of a resize or drag action.
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 88cc94c..7af6b8e 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
@@ -90,6 +90,7 @@
private var viewHost: SurfaceControlViewHost? = null
private var display: Display? = null
private var veilAnimator: ValueAnimator? = null
+ private var iconAnimator: ValueAnimator? = null
private var loadAppInfoJob: Job? = null
/**
@@ -241,7 +242,7 @@
}
})
}
- val iconAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
+ iconAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
duration = RESIZE_ALPHA_DURATION
addUpdateListener {
iconAnimT.setAlpha(icon, animatedValue as Float)
@@ -265,7 +266,7 @@
.hide(background)
.apply()
veilAnimator?.start()
- iconAnimator.start()
+ iconAnimator?.start()
} else {
// Show the veil immediately.
t.apply()
@@ -414,6 +415,10 @@
private fun cancelAnimation() {
veilAnimator?.removeAllUpdateListeners()
veilAnimator?.cancel()
+ veilAnimator = null
+ iconAnimator?.removeAllUpdateListeners()
+ iconAnimator?.cancel()
+ iconAnimator = null
}
/**
@@ -421,7 +426,6 @@
*/
fun dispose() {
cancelAnimation()
- veilAnimator = null
isVisible = false
loadAppInfoJob?.cancel()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
index 2115f70..af2840e 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
@@ -45,6 +45,7 @@
tapl.setExpectedRotation(rotation.value)
ChangeDisplayOrientationRule.setRotation(rotation)
tapl.enableTransientTaskbar(false)
+ testApp.exit(wmHelper)
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
index 94dc774..d4d8d93 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
@@ -39,7 +39,6 @@
import android.annotation.NonNull;
import android.graphics.Point;
import android.graphics.Rect;
-import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -77,7 +76,6 @@
doNothing().when(mController).onAnimationFinished(any());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testStartAnimation() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
@@ -103,7 +101,6 @@
verify(mController).onAnimationFinished(mTransition);
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testChangesBehindStartingWindow() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
@@ -118,7 +115,6 @@
assertEquals(0, animator.getDuration());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testTransitionTypeDragResize() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TASK_FRAGMENT_DRAG_RESIZE, 0)
@@ -133,25 +129,6 @@
assertEquals(0, animator.getDuration());
}
- @DisableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
- @Test
- public void testInvalidCustomAnimation_disableAnimationOptionsPerChange() {
- final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
- .addChange(createChange(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY, TRANSIT_OPEN))
- .build();
- info.setAnimationOptions(TransitionInfo.AnimationOptions
- .makeCustomAnimOptions("packageName", 0 /* enterResId */, 0 /* exitResId */,
- 0 /* backgroundColor */, false /* overrideTaskTransition */));
- final Animator animator = mAnimRunner.createAnimator(
- info, mStartTransaction, mFinishTransaction,
- () -> mFinishCallback.onTransitionFinished(null /* wct */),
- new ArrayList<>());
-
- // An invalid custom animation is equivalent to jump-cut.
- assertEquals(0, animator.getDuration());
- }
-
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testInvalidCustomAnimation_enableAnimationOptionsPerChange() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
@@ -169,36 +146,6 @@
assertEquals(0, animator.getDuration());
}
- @DisableFlags(Flags.FLAG_ACTIVITY_EMBEDDING_OVERLAY_PRESENTATION_FLAG)
- @Test
- public void testCalculateParentBounds_flagDisabled() {
- final Rect parentBounds = new Rect(0, 0, 2000, 2000);
- final Rect primaryBounds = new Rect();
- final Rect secondaryBounds = new Rect();
- parentBounds.splitVertically(primaryBounds, secondaryBounds);
-
- final TransitionInfo.Change change = createChange(0 /* flags */);
- change.setStartAbsBounds(secondaryBounds);
-
- final TransitionInfo.Change boundsAnimationChange = createChange(0 /* flags */);
- boundsAnimationChange.setStartAbsBounds(primaryBounds);
- boundsAnimationChange.setEndAbsBounds(primaryBounds);
- final Rect actualParentBounds = new Rect();
-
- calculateParentBounds(change, boundsAnimationChange, actualParentBounds);
-
- assertEquals(parentBounds, actualParentBounds);
-
- actualParentBounds.setEmpty();
-
- boundsAnimationChange.setStartAbsBounds(secondaryBounds);
- boundsAnimationChange.setEndAbsBounds(primaryBounds);
-
- calculateParentBounds(boundsAnimationChange, boundsAnimationChange, actualParentBounds);
-
- assertEquals(parentBounds, actualParentBounds);
- }
-
// TODO(b/243518738): Rewrite with TestParameter
@EnableFlags(Flags.FLAG_ACTIVITY_EMBEDDING_OVERLAY_PRESENTATION_FLAG)
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java
index 9f29ef7..53a13d0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java
@@ -32,8 +32,6 @@
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.Rect;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -41,7 +39,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.window.flags.Flags;
import com.android.wm.shell.transition.TransitionInfoBuilder;
import org.junit.Before;
@@ -69,13 +66,11 @@
any());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testInstantiate() {
verify(mShellInit).addInitCallback(any(), any());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOnInit() {
mController.onInit();
@@ -83,7 +78,6 @@
verify(mTransitions).addHandler(mController);
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testSetAnimScaleSetting() {
mController.setAnimScaleSetting(1.0f);
@@ -92,7 +86,6 @@
verify(mAnimSpec).setAnimScaleSetting(1.0f);
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testStartAnimation_containsNonActivityEmbeddingChange() {
final TransitionInfo.Change nonEmbeddedOpen = createChange(0 /* flags */);
@@ -129,7 +122,6 @@
assertFalse(info2.getChanges().contains(nonEmbeddedClose));
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testStartAnimation_containsOnlyFillTaskActivityEmbeddingChange() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
@@ -146,7 +138,6 @@
verifyNoMoreInteractions(mFinishCallback);
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testStartAnimation_containsActivityEmbeddingSplitChange() {
// Change that occupies only part of the Task.
@@ -164,7 +155,6 @@
verifyNoMoreInteractions(mFinishTransaction);
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testStartAnimation_containsChangeEnterActivityEmbeddingSplit() {
// Change that is entering ActivityEmbedding split.
@@ -181,7 +171,6 @@
verifyNoMoreInteractions(mFinishTransaction);
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testStartAnimation_containsChangeExitActivityEmbeddingSplit() {
// Change that is exiting ActivityEmbedding split.
@@ -198,27 +187,6 @@
verifyNoMoreInteractions(mFinishTransaction);
}
- @DisableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
- @Test
- public void testShouldAnimate_containsAnimationOptions_disableAnimOptionsPerChange() {
- final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0)
- .addChange(createEmbeddedChange(EMBEDDED_RIGHT_BOUNDS, TASK_BOUNDS, TASK_BOUNDS))
- .build();
-
- info.setAnimationOptions(TransitionInfo.AnimationOptions
- .makeCustomAnimOptions("packageName", 0 /* enterResId */, 0 /* exitResId */,
- 0 /* backgroundColor */, false /* overrideTaskTransition */));
- assertTrue(mController.shouldAnimate(info));
-
- info.setAnimationOptions(TransitionInfo.AnimationOptions
- .makeSceneTransitionAnimOptions());
- assertFalse(mController.shouldAnimate(info));
-
- info.setAnimationOptions(TransitionInfo.AnimationOptions.makeCrossProfileAnimOptions());
- assertFalse(mController.shouldAnimate(info));
- }
-
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testShouldAnimate_containsAnimationOptions_enableAnimOptionsPerChange() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0)
@@ -239,7 +207,6 @@
assertFalse(mController.shouldAnimate(info));
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@UiThreadTest
@Test
public void testMergeAnimation() {
@@ -278,7 +245,6 @@
verify(mFinishCallback).onTransitionFinished(any());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOnAnimationFinished() {
// Should not call finish when there is no transition.
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorControllerTest.kt
new file mode 100644
index 0000000..abd2388
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiDisplayDragMoveIndicatorControllerTest.kt
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.common
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.content.res.Configuration
+import android.graphics.Rect
+import android.graphics.RectF
+import android.testing.TestableResources
+import android.view.Display
+import android.view.SurfaceControl
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestShellExecutor
+import java.util.function.Supplier
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.times
+import org.mockito.kotlin.whenever
+
+/**
+ * Tests for [MultiDisplayDragMoveIndicatorController].
+ *
+ * Build/Install/Run: atest WMShellUnitTests:MultiDisplayDragMoveIndicatorControllerTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MultiDisplayDragMoveIndicatorControllerTest : ShellTestCase() {
+ private val displayController = mock<DisplayController>()
+ private val rootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>()
+ private val indicatorSurfaceFactory = mock<MultiDisplayDragMoveIndicatorSurface.Factory>()
+ private val indicatorSurface0 = mock<MultiDisplayDragMoveIndicatorSurface>()
+ private val indicatorSurface1 = mock<MultiDisplayDragMoveIndicatorSurface>()
+ private val transaction = mock<SurfaceControl.Transaction>()
+ private val transactionSupplier = mock<Supplier<SurfaceControl.Transaction>>()
+ private val taskInfo = mock<RunningTaskInfo>()
+ private val display0 = mock<Display>()
+ private val display1 = mock<Display>()
+
+ private lateinit var resources: TestableResources
+ private val executor = TestShellExecutor()
+
+ private lateinit var controller: MultiDisplayDragMoveIndicatorController
+
+ @Before
+ fun setUp() {
+ resources = mContext.getOrCreateTestableResources()
+ val resourceConfiguration = Configuration()
+ resourceConfiguration.uiMode = 0
+ resources.overrideConfiguration(resourceConfiguration)
+
+ controller =
+ MultiDisplayDragMoveIndicatorController(
+ displayController,
+ rootTaskDisplayAreaOrganizer,
+ indicatorSurfaceFactory,
+ executor,
+ )
+
+ val spyDisplayLayout0 =
+ MultiDisplayTestUtil.createSpyDisplayLayout(
+ MultiDisplayTestUtil.DISPLAY_GLOBAL_BOUNDS_0,
+ MultiDisplayTestUtil.DISPLAY_DPI_0,
+ resources.resources,
+ )
+ val spyDisplayLayout1 =
+ MultiDisplayTestUtil.createSpyDisplayLayout(
+ MultiDisplayTestUtil.DISPLAY_GLOBAL_BOUNDS_1,
+ MultiDisplayTestUtil.DISPLAY_DPI_1,
+ resources.resources,
+ )
+
+ taskInfo.taskId = TASK_ID
+ whenever(displayController.getDisplayLayout(0)).thenReturn(spyDisplayLayout0)
+ whenever(displayController.getDisplayLayout(1)).thenReturn(spyDisplayLayout1)
+ whenever(displayController.getDisplay(0)).thenReturn(display0)
+ whenever(displayController.getDisplay(1)).thenReturn(display1)
+ whenever(indicatorSurfaceFactory.create(taskInfo, display0)).thenReturn(indicatorSurface0)
+ whenever(indicatorSurfaceFactory.create(taskInfo, display1)).thenReturn(indicatorSurface1)
+ whenever(transactionSupplier.get()).thenReturn(transaction)
+ }
+
+ @Test
+ fun onDrag_boundsNotIntersectWithDisplay_noIndicator() {
+ controller.onDragMove(
+ RectF(2000f, 2000f, 2100f, 2200f), // not intersect with any display
+ startDisplayId = 0,
+ taskInfo,
+ displayIds = setOf(0, 1),
+ ) { transaction }
+ executor.flushAll()
+
+ verify(indicatorSurfaceFactory, never()).create(any(), any())
+ }
+
+ @Test
+ fun onDrag_boundsIntersectWithStartDisplay_noIndicator() {
+ controller.onDragMove(
+ RectF(100f, 100f, 200f, 200f), // intersect with display 0
+ startDisplayId = 0,
+ taskInfo,
+ displayIds = setOf(0, 1),
+ ) { transaction }
+ executor.flushAll()
+
+ verify(indicatorSurfaceFactory, never()).create(any(), any())
+ }
+
+ @Test
+ fun onDrag_boundsIntersectWithNonStartDisplay_showAndDisposeIndicator() {
+ controller.onDragMove(
+ RectF(100f, -100f, 200f, 200f), // intersect with display 0 and 1
+ startDisplayId = 0,
+ taskInfo,
+ displayIds = setOf(0, 1),
+ ) { transaction }
+ executor.flushAll()
+
+ verify(indicatorSurfaceFactory, times(1)).create(taskInfo, display1)
+ verify(indicatorSurface1, times(1))
+ .show(transaction, taskInfo, rootTaskDisplayAreaOrganizer, 1, Rect(0, 1800, 200, 2400))
+
+ controller.onDragMove(
+ RectF(2000f, 2000f, 2100f, 2200f), // not intersect with display 1
+ startDisplayId = 0,
+ taskInfo,
+ displayIds = setOf(0, 1)
+ ) { transaction }
+ while (executor.callbacks.isNotEmpty()) {
+ executor.flushAll()
+ }
+
+ verify(indicatorSurface1, times(1))
+ .relayout(any(), eq(transaction), shouldBeVisible = eq(false))
+
+ controller.onDragEnd(TASK_ID, { transaction })
+ while (executor.callbacks.isNotEmpty()) {
+ executor.flushAll()
+ }
+
+ verify(indicatorSurface1, times(1)).disposeSurface(transaction)
+ }
+
+ companion object {
+ private const val TASK_ID = 10
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt
index 0d5741f..8ad54f5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt
@@ -16,51 +16,28 @@
package com.android.wm.shell.desktopmode
-import android.app.ActivityManager.RunningTaskInfo
-import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
-import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
-import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
-import android.content.ContentResolver
-import android.os.Binder
import android.platform.test.annotations.EnableFlags
-import android.provider.Settings
-import android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
import android.testing.AndroidTestingRunner
import android.view.Display.DEFAULT_DISPLAY
-import android.view.IWindowManager
-import android.view.WindowManager.TRANSIT_CHANGE
-import android.window.DisplayAreaInfo
-import android.window.WindowContainerTransaction
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.ExtendedMockito.never
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.window.flags.Flags
-import com.android.wm.shell.MockToken
-import com.android.wm.shell.RootTaskDisplayAreaOrganizer
-import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
-import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayController.OnDisplaysChangedListener
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.sysui.ShellInit
-import com.android.wm.shell.transition.Transitions
-import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.isNull
import org.mockito.Mock
-import org.mockito.Mockito.anyInt
import org.mockito.Mockito.spy
-import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
-import org.mockito.kotlin.eq
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
@@ -73,27 +50,18 @@
@RunWith(AndroidTestingRunner::class)
class DesktopDisplayEventHandlerTest : ShellTestCase() {
@Mock lateinit var testExecutor: ShellExecutor
- @Mock lateinit var transitions: Transitions
@Mock lateinit var displayController: DisplayController
- @Mock lateinit var rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer
- @Mock private lateinit var mockWindowManager: IWindowManager
@Mock private lateinit var mockDesktopUserRepositories: DesktopUserRepositories
@Mock private lateinit var mockDesktopRepository: DesktopRepository
@Mock private lateinit var mockDesktopTasksController: DesktopTasksController
- @Mock private lateinit var shellTaskOrganizer: ShellTaskOrganizer
+ @Mock private lateinit var desktopDisplayModeController: DesktopDisplayModeController
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var shellInit: ShellInit
private lateinit var handler: DesktopDisplayEventHandler
private val onDisplaysChangedListenerCaptor = argumentCaptor<OnDisplaysChangedListener>()
- private val runningTasks = mutableListOf<RunningTaskInfo>()
private val externalDisplayId = 100
- private val freeformTask =
- TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FREEFORM).build()
- private val fullscreenTask =
- TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FULLSCREEN).build()
- private val defaultTDA = DisplayAreaInfo(MockToken().token(), DEFAULT_DISPLAY, 0)
@Before
fun setUp() {
@@ -105,24 +73,15 @@
shellInit = spy(ShellInit(testExecutor))
whenever(mockDesktopUserRepositories.current).thenReturn(mockDesktopRepository)
- whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() }
- whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
- .thenReturn(defaultTDA)
handler =
DesktopDisplayEventHandler(
context,
shellInit,
- transitions,
displayController,
- rootTaskDisplayAreaOrganizer,
- mockWindowManager,
mockDesktopUserRepositories,
mockDesktopTasksController,
- shellTaskOrganizer,
+ desktopDisplayModeController,
)
- whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks }
- runningTasks.add(freeformTask)
- runningTasks.add(fullscreenTask)
shellInit.init()
verify(displayController)
.addDisplayWindowListener(onDisplaysChangedListenerCaptor.capture())
@@ -133,65 +92,6 @@
mockitoSession.finishMocking()
}
- private fun testDisplayWindowingModeSwitch(
- defaultWindowingMode: Int,
- extendedDisplayEnabled: Boolean,
- expectTransition: Boolean,
- ) {
- defaultTDA.configuration.windowConfiguration.windowingMode = defaultWindowingMode
- whenever(mockWindowManager.getWindowingMode(anyInt())).thenAnswer { defaultWindowingMode }
- val settingsSession =
- ExtendedDisplaySettingsSession(
- context.contentResolver,
- if (extendedDisplayEnabled) 1 else 0,
- )
-
- settingsSession.use {
- connectExternalDisplay()
- defaultTDA.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
- disconnectExternalDisplay()
-
- if (expectTransition) {
- val arg = argumentCaptor<WindowContainerTransaction>()
- verify(transitions, times(2))
- .startTransition(eq(TRANSIT_CHANGE), arg.capture(), isNull())
- assertThat(arg.firstValue.changes[defaultTDA.token.asBinder()]?.windowingMode)
- .isEqualTo(WINDOWING_MODE_FREEFORM)
- assertThat(arg.secondValue.changes[defaultTDA.token.asBinder()]?.windowingMode)
- .isEqualTo(defaultWindowingMode)
- } else {
- verify(transitions, never()).startTransition(eq(TRANSIT_CHANGE), any(), isNull())
- }
- }
- }
-
- @Test
- fun displayWindowingModeSwitchOnDisplayConnected_extendedDisplayDisabled() {
- testDisplayWindowingModeSwitch(
- defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
- extendedDisplayEnabled = false,
- expectTransition = false,
- )
- }
-
- @Test
- fun displayWindowingModeSwitchOnDisplayConnected_fullscreenDisplay() {
- testDisplayWindowingModeSwitch(
- defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
- extendedDisplayEnabled = true,
- expectTransition = true,
- )
- }
-
- @Test
- fun displayWindowingModeSwitchOnDisplayConnected_freeformDisplay() {
- testDisplayWindowingModeSwitch(
- defaultWindowingMode = WINDOWING_MODE_FREEFORM,
- extendedDisplayEnabled = true,
- expectTransition = false,
- )
- }
-
@Test
fun testDisplayAdded_supportsDesks_createsDesk() {
whenever(DesktopModeStatus.canEnterDesktopMode(context)).thenReturn(true)
@@ -231,70 +131,14 @@
}
@Test
- fun displayWindowingModeSwitch_existingTasksOnConnected() {
- defaultTDA.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
- whenever(mockWindowManager.getWindowingMode(anyInt())).thenAnswer {
- WINDOWING_MODE_FULLSCREEN
- }
-
- ExtendedDisplaySettingsSession(context.contentResolver, 1).use {
- connectExternalDisplay()
-
- val arg = argumentCaptor<WindowContainerTransaction>()
- verify(transitions, times(1))
- .startTransition(eq(TRANSIT_CHANGE), arg.capture(), isNull())
- assertThat(arg.firstValue.changes[freeformTask.token.asBinder()]?.windowingMode)
- .isEqualTo(WINDOWING_MODE_UNDEFINED)
- assertThat(arg.firstValue.changes[fullscreenTask.token.asBinder()]?.windowingMode)
- .isEqualTo(WINDOWING_MODE_FULLSCREEN)
- }
+ fun testConnectExternalDisplay() {
+ onDisplaysChangedListenerCaptor.lastValue.onDisplayAdded(externalDisplayId)
+ verify(desktopDisplayModeController).refreshDisplayWindowingMode()
}
@Test
- fun displayWindowingModeSwitch_existingTasksOnDisconnected() {
- defaultTDA.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
- whenever(mockWindowManager.getWindowingMode(anyInt())).thenAnswer {
- WINDOWING_MODE_FULLSCREEN
- }
-
- ExtendedDisplaySettingsSession(context.contentResolver, 1).use {
- disconnectExternalDisplay()
-
- val arg = argumentCaptor<WindowContainerTransaction>()
- verify(transitions, times(1))
- .startTransition(eq(TRANSIT_CHANGE), arg.capture(), isNull())
- assertThat(arg.firstValue.changes[freeformTask.token.asBinder()]?.windowingMode)
- .isEqualTo(WINDOWING_MODE_FREEFORM)
- assertThat(arg.firstValue.changes[fullscreenTask.token.asBinder()]?.windowingMode)
- .isEqualTo(WINDOWING_MODE_UNDEFINED)
- }
- }
-
- private fun connectExternalDisplay() {
- whenever(rootTaskDisplayAreaOrganizer.getDisplayIds())
- .thenReturn(intArrayOf(DEFAULT_DISPLAY, externalDisplayId))
- onDisplaysChangedListenerCaptor.lastValue.onDisplayAdded(externalDisplayId)
- }
-
- private fun disconnectExternalDisplay() {
- whenever(rootTaskDisplayAreaOrganizer.getDisplayIds())
- .thenReturn(intArrayOf(DEFAULT_DISPLAY))
+ fun testDisconnectExternalDisplay() {
onDisplaysChangedListenerCaptor.lastValue.onDisplayRemoved(externalDisplayId)
- }
-
- private class ExtendedDisplaySettingsSession(
- private val contentResolver: ContentResolver,
- private val overrideValue: Int,
- ) : AutoCloseable {
- private val settingName = DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
- private val initialValue = Settings.Global.getInt(contentResolver, settingName, 0)
-
- init {
- Settings.Global.putInt(contentResolver, settingName, overrideValue)
- }
-
- override fun close() {
- Settings.Global.putInt(contentResolver, settingName, initialValue)
- }
+ verify(desktopDisplayModeController).refreshDisplayWindowingMode()
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
new file mode 100644
index 0000000..0ff7230
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
+import android.content.ContentResolver
+import android.os.Binder
+import android.provider.Settings
+import android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
+import android.testing.AndroidTestingRunner
+import android.view.Display.DEFAULT_DISPLAY
+import android.view.IWindowManager
+import android.view.WindowManager.TRANSIT_CHANGE
+import android.window.DisplayAreaInfo
+import android.window.WindowContainerTransaction
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.never
+import com.android.wm.shell.MockToken
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer
+import com.android.wm.shell.ShellTaskOrganizer
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestRunningTaskInfoBuilder
+import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
+import com.android.wm.shell.transition.Transitions
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.isNull
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+/**
+ * Test class for [DesktopDisplayModeController]
+ *
+ * Usage: atest WMShellUnitTests:DesktopDisplayModeControllerTest
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class DesktopDisplayModeControllerTest : ShellTestCase() {
+ private val transitions = mock<Transitions>()
+ private val rootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>()
+ private val mockWindowManager = mock<IWindowManager>()
+ private val shellTaskOrganizer = mock<ShellTaskOrganizer>()
+ private val desktopWallpaperActivityTokenProvider =
+ mock<DesktopWallpaperActivityTokenProvider>()
+
+ private lateinit var controller: DesktopDisplayModeController
+
+ private val runningTasks = mutableListOf<RunningTaskInfo>()
+ private val freeformTask =
+ TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FREEFORM).build()
+ private val fullscreenTask =
+ TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FULLSCREEN).build()
+ private val defaultTDA = DisplayAreaInfo(MockToken().token(), DEFAULT_DISPLAY, 0)
+ private val wallpaperToken = MockToken().token()
+
+ @Before
+ fun setUp() {
+ whenever(transitions.startTransition(anyInt(), any(), isNull())).thenReturn(Binder())
+ whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
+ .thenReturn(defaultTDA)
+ controller =
+ DesktopDisplayModeController(
+ context,
+ transitions,
+ rootTaskDisplayAreaOrganizer,
+ mockWindowManager,
+ shellTaskOrganizer,
+ desktopWallpaperActivityTokenProvider,
+ )
+ runningTasks.add(freeformTask)
+ runningTasks.add(fullscreenTask)
+ whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(ArrayList(runningTasks))
+ whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(wallpaperToken)
+ }
+
+ private fun testDisplayWindowingModeSwitch(
+ defaultWindowingMode: Int,
+ extendedDisplayEnabled: Boolean,
+ expectTransition: Boolean,
+ ) {
+ defaultTDA.configuration.windowConfiguration.windowingMode = defaultWindowingMode
+ whenever(mockWindowManager.getWindowingMode(anyInt())).thenReturn(defaultWindowingMode)
+ val settingsSession =
+ ExtendedDisplaySettingsSession(
+ context.contentResolver,
+ if (extendedDisplayEnabled) 1 else 0,
+ )
+
+ settingsSession.use {
+ connectExternalDisplay()
+ defaultTDA.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
+ disconnectExternalDisplay()
+
+ if (expectTransition) {
+ val arg = argumentCaptor<WindowContainerTransaction>()
+ verify(transitions, times(2))
+ .startTransition(eq(TRANSIT_CHANGE), arg.capture(), isNull())
+ assertThat(arg.firstValue.changes[defaultTDA.token.asBinder()]?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_FREEFORM)
+ assertThat(arg.firstValue.changes[wallpaperToken.asBinder()]?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+ assertThat(arg.secondValue.changes[defaultTDA.token.asBinder()]?.windowingMode)
+ .isEqualTo(defaultWindowingMode)
+ assertThat(arg.secondValue.changes[wallpaperToken.asBinder()]?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+ } else {
+ verify(transitions, never()).startTransition(eq(TRANSIT_CHANGE), any(), isNull())
+ }
+ }
+ }
+
+ @Test
+ fun displayWindowingModeSwitchOnDisplayConnected_extendedDisplayDisabled() {
+ testDisplayWindowingModeSwitch(
+ defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
+ extendedDisplayEnabled = false,
+ expectTransition = false,
+ )
+ }
+
+ @Test
+ fun displayWindowingModeSwitchOnDisplayConnected_fullscreenDisplay() {
+ testDisplayWindowingModeSwitch(
+ defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
+ extendedDisplayEnabled = true,
+ expectTransition = true,
+ )
+ }
+
+ @Test
+ fun displayWindowingModeSwitchOnDisplayConnected_freeformDisplay() {
+ testDisplayWindowingModeSwitch(
+ defaultWindowingMode = WINDOWING_MODE_FREEFORM,
+ extendedDisplayEnabled = true,
+ expectTransition = false,
+ )
+ }
+
+ @Test
+ fun displayWindowingModeSwitch_existingTasksOnConnected() {
+ defaultTDA.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
+ whenever(mockWindowManager.getWindowingMode(anyInt())).thenReturn(WINDOWING_MODE_FULLSCREEN)
+
+ ExtendedDisplaySettingsSession(context.contentResolver, 1).use {
+ connectExternalDisplay()
+
+ val arg = argumentCaptor<WindowContainerTransaction>()
+ verify(transitions, times(1))
+ .startTransition(eq(TRANSIT_CHANGE), arg.capture(), isNull())
+ assertThat(arg.firstValue.changes[freeformTask.token.asBinder()]?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_UNDEFINED)
+ assertThat(arg.firstValue.changes[fullscreenTask.token.asBinder()]?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+ }
+ }
+
+ @Test
+ fun displayWindowingModeSwitch_existingTasksOnDisconnected() {
+ defaultTDA.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
+ whenever(mockWindowManager.getWindowingMode(anyInt())).thenAnswer {
+ WINDOWING_MODE_FULLSCREEN
+ }
+
+ ExtendedDisplaySettingsSession(context.contentResolver, 1).use {
+ disconnectExternalDisplay()
+
+ val arg = argumentCaptor<WindowContainerTransaction>()
+ verify(transitions, times(1))
+ .startTransition(eq(TRANSIT_CHANGE), arg.capture(), isNull())
+ assertThat(arg.firstValue.changes[freeformTask.token.asBinder()]?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_FREEFORM)
+ assertThat(arg.firstValue.changes[fullscreenTask.token.asBinder()]?.windowingMode)
+ .isEqualTo(WINDOWING_MODE_UNDEFINED)
+ }
+ }
+
+ private fun connectExternalDisplay() {
+ whenever(rootTaskDisplayAreaOrganizer.getDisplayIds())
+ .thenReturn(intArrayOf(DEFAULT_DISPLAY, EXTERNAL_DISPLAY_ID))
+ controller.refreshDisplayWindowingMode()
+ }
+
+ private fun disconnectExternalDisplay() {
+ whenever(rootTaskDisplayAreaOrganizer.getDisplayIds())
+ .thenReturn(intArrayOf(DEFAULT_DISPLAY))
+ controller.refreshDisplayWindowingMode()
+ }
+
+ private class ExtendedDisplaySettingsSession(
+ private val contentResolver: ContentResolver,
+ private val overrideValue: Int,
+ ) : AutoCloseable {
+ private val settingName = DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
+ private val initialValue = Settings.Global.getInt(contentResolver, settingName, 0)
+
+ init {
+ Settings.Global.putInt(contentResolver, settingName, overrideValue)
+ }
+
+ override fun close() {
+ Settings.Global.putInt(contentResolver, settingName, initialValue)
+ }
+ }
+
+ private companion object {
+ const val EXTERNAL_DISPLAY_ID = 100
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt
index 4c3325d..0d1c5722 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt
@@ -21,6 +21,7 @@
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WindowingMode
+import android.os.Handler
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.SurfaceControl
@@ -56,7 +57,12 @@
@Before
fun setUp() {
handler =
- DesktopMinimizationTransitionHandler(testExecutor, testExecutor, displayController)
+ DesktopMinimizationTransitionHandler(
+ testExecutor,
+ testExecutor,
+ displayController,
+ mock<Handler>(),
+ )
whenever(displayController.getDisplayContext(any())).thenReturn(mContext)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
index ed9b97d..9bff287 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopRepositoryTest.kt
@@ -333,7 +333,7 @@
@Test
fun isOnlyVisibleNonClosingTask_singleVisibleClosingTask() {
repo.updateTask(DEFAULT_DISPLAY, taskId = 1, isVisible = true)
- repo.addClosingTask(DEFAULT_DISPLAY, 1)
+ repo.addClosingTask(displayId = DEFAULT_DISPLAY, deskId = 0, taskId = 1)
// A visible task that's closing
assertThat(repo.isVisibleTask(1)).isTrue()
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 fcd92ac..0b160c6 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
@@ -2477,8 +2477,7 @@
controller.moveTaskToFront(task.taskId, unminimizeReason = UnminimizeReason.UNKNOWN)
val wct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
- assertThat(wct.hierarchyOps).hasSize(1)
- wct.assertLaunchTaskAt(0, task.taskId, WINDOWING_MODE_FREEFORM)
+ wct.assertLaunchTask(task.taskId, WINDOWING_MODE_FREEFORM)
}
@Test
@@ -2827,7 +2826,7 @@
fun onDesktopWindowClose_singleActiveTask_isClosing() {
val task = setUpFreeformTask()
- taskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId)
+ taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, deskId = 0, taskId = task.taskId)
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
@@ -2864,7 +2863,11 @@
val task1 = setUpFreeformTask()
val task2 = setUpFreeformTask()
- taskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId)
+ taskRepository.addClosingTask(
+ displayId = DEFAULT_DISPLAY,
+ deskId = 0,
+ taskId = task2.taskId,
+ )
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task1)
@@ -2966,9 +2969,13 @@
val captor = argumentCaptor<WindowContainerTransaction>()
verify(freeformTaskTransitionStarter)
.startMinimizedModeTransition(captor.capture(), eq(task.taskId), eq(false))
- captor.firstValue.hierarchyOps.none { hop ->
- hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
- }
+ assertThat(
+ captor.firstValue.hierarchyOps.none { hop ->
+ hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK &&
+ hop.container == wallpaperToken.asBinder()
+ }
+ )
+ .isTrue()
}
@Test
@@ -3057,9 +3064,13 @@
val captor = argumentCaptor<WindowContainerTransaction>()
verify(freeformTaskTransitionStarter).startPipTransition(captor.capture())
- captor.firstValue.hierarchyOps.none { hop ->
- hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
- }
+ assertThat(
+ captor.firstValue.hierarchyOps.none { hop ->
+ hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK &&
+ hop.container == wallpaperToken.asBinder()
+ }
+ )
+ .isTrue()
}
@Test
@@ -3080,7 +3091,12 @@
val captor = argumentCaptor<WindowContainerTransaction>()
verify(freeformTaskTransitionStarter)
.startMinimizedModeTransition(captor.capture(), eq(task.taskId), eq(true))
- captor.firstValue.hierarchyOps.none { hop -> hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK }
+ assertThat(
+ captor.firstValue.hierarchyOps.none { hop ->
+ hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK
+ }
+ )
+ .isTrue()
}
@Test
@@ -3127,9 +3143,13 @@
val captor = argumentCaptor<WindowContainerTransaction>()
verify(freeformTaskTransitionStarter)
.startMinimizedModeTransition(captor.capture(), eq(task.taskId), eq(false))
- captor.firstValue.hierarchyOps.none { hop ->
- hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
- }
+ assertThat(
+ captor.firstValue.hierarchyOps.none { hop ->
+ hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK &&
+ hop.container == wallpaperToken.asBinder()
+ }
+ )
+ .isTrue()
}
@Test
@@ -3151,9 +3171,13 @@
val captor = argumentCaptor<WindowContainerTransaction>()
verify(freeformTaskTransitionStarter)
.startMinimizedModeTransition(captor.capture(), eq(task1.taskId), eq(false))
- captor.firstValue.hierarchyOps.none { hop ->
- hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
- }
+ assertThat(
+ captor.firstValue.hierarchyOps.none { hop ->
+ hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK &&
+ hop.container == wallpaperToken.asBinder()
+ }
+ )
+ .isTrue()
}
@Test
@@ -3225,6 +3249,30 @@
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ fun onDesktopWindowMinimize_minimizesTask() {
+ val task = setUpFreeformTask()
+ val transition = Binder()
+ val runOnTransit = RunOnStartTransitionCallback()
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
+ .thenReturn(transition)
+ whenever(mMockDesktopImmersiveController.exitImmersiveIfApplicable(any(), eq(task), any()))
+ .thenReturn(
+ ExitResult.Exit(exitingTask = task.taskId, runOnTransitionStart = runOnTransit)
+ )
+
+ controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
+
+ verify(desksOrganizer).minimizeTask(any(), /* deskId= */ eq(0), eq(task))
+ }
+
+ @Test
fun onDesktopWindowMinimize_triesToStopTiling() {
val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val transition = Binder()
@@ -3972,7 +4020,11 @@
val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
- taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.addClosingTask(
+ displayId = DEFAULT_DISPLAY,
+ deskId = 0,
+ taskId = task2.taskId,
+ )
val result =
controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
@@ -4083,6 +4135,36 @@
}
@Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
+ )
+ fun handleRequest_closeTransition_onlyDesktopTask_deactivatesDesk() {
+ val task = setUpFreeformTask()
+
+ controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE))
+
+ verify(desksOrganizer).deactivateDesk(any(), /* deskId= */ eq(0))
+ }
+
+ @Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
+ )
+ fun handleRequest_closeTransition_onlyDesktopTask_addsDeactivatesDeskTransition() {
+ val transition = Binder()
+ val task = setUpFreeformTask()
+
+ controller.handleRequest(transition, createTransition(task, type = TRANSIT_CLOSE))
+
+ verify(desksTransitionsObserver)
+ .addPendingTransition(DeskTransition.DeactivateDesk(token = transition, deskId = 0))
+ }
+
+ @Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
fun handleRequest_closeTransition_multipleTasks_noWallpaper_doesNotHandle() {
val task1 = setUpFreeformTask()
@@ -4115,7 +4197,11 @@
val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
- taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
+ taskRepository.addClosingTask(
+ displayId = DEFAULT_DISPLAY,
+ deskId = 0,
+ taskId = task2.taskId,
+ )
val result =
controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
@@ -6240,6 +6326,61 @@
assertThat(taskRepository.getNumberOfDesks(DEFAULT_DISPLAY)).isEqualTo(currentDeskCount + 1)
}
+ @Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ )
+ fun startLaunchTransition_desktopNotShowing_movesWallpaperToFront() {
+ val launchingTask = createFreeformTask()
+ val wct = WindowContainerTransaction()
+ wct.reorder(launchingTask.token, /* onTop= */ true)
+ whenever(
+ desktopMixedTransitionHandler.startLaunchTransition(
+ eq(TRANSIT_OPEN),
+ any(),
+ anyOrNull(),
+ anyOrNull(),
+ anyOrNull(),
+ )
+ )
+ .thenReturn(Binder())
+
+ controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null)
+
+ val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
+ val launchingTaskReorderIndex = latestWct.indexOfReorder(launchingTask, toTop = true)
+ val wallpaperReorderIndex = latestWct.indexOfReorder(wallpaperToken, toTop = true)
+ assertThat(launchingTaskReorderIndex).isNotEqualTo(-1)
+ assertThat(wallpaperReorderIndex).isNotEqualTo(-1)
+ assertThat(launchingTaskReorderIndex).isGreaterThan(wallpaperReorderIndex)
+ }
+
+ @Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ )
+ fun startLaunchTransition_desktopShowing_doesNotReorderWallpaper() {
+ val wct = WindowContainerTransaction()
+ whenever(
+ desktopMixedTransitionHandler.startLaunchTransition(
+ eq(TRANSIT_OPEN),
+ any(),
+ anyOrNull(),
+ anyOrNull(),
+ anyOrNull(),
+ )
+ )
+ .thenReturn(Binder())
+
+ setUpFreeformTask()
+ controller.startLaunchTransition(TRANSIT_OPEN, wct, launchingTaskId = null)
+
+ val latestWct = getLatestDesktopMixedTaskWct(type = TRANSIT_OPEN)
+ assertNull(latestWct.hierarchyOps.find { op -> op.container == wallpaperToken.asBinder() })
+ }
+
private class RunOnStartTransitionCallback : ((IBinder) -> Unit) {
var invocations = 0
private set
@@ -6626,11 +6767,18 @@
}
private fun WindowContainerTransaction.indexOfReorder(
+ token: WindowContainerToken,
+ toTop: Boolean? = null,
+): Int {
+ val hop = hierarchyOps.singleOrNull(ReorderPredicate(token, toTop)) ?: return -1
+ return hierarchyOps.indexOf(hop)
+}
+
+private fun WindowContainerTransaction.indexOfReorder(
task: RunningTaskInfo,
toTop: Boolean? = null,
): Int {
- val hop = hierarchyOps.singleOrNull(ReorderPredicate(task.token, toTop)) ?: return -1
- return hierarchyOps.indexOf(hop)
+ return indexOfReorder(task.token, toTop)
}
private class ReorderPredicate(val token: WindowContainerToken, val toTop: Boolean? = null) :
@@ -6750,6 +6898,17 @@
assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories)
}
+private fun WindowContainerTransaction.assertLaunchTask(taskId: Int, windowingMode: Int) {
+ val keyLaunchWindowingMode = "android.activity.windowingMode"
+
+ assertHop { hop ->
+ hop.type == HIERARCHY_OP_TYPE_LAUNCH_TASK &&
+ hop.launchOptions?.getInt(LAUNCH_KEY_TASK_ID) == taskId &&
+ hop.launchOptions?.getInt(keyLaunchWindowingMode, WINDOWING_MODE_UNDEFINED) ==
+ windowingMode
+ }
+}
+
private fun WindowContainerTransaction.assertLaunchTaskAt(
index: Int,
taskId: Int,
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 d33209d..62e3c54 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
@@ -37,7 +37,6 @@
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.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION
import com.android.wm.shell.ShellTaskOrganizer
@@ -72,8 +71,6 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.spy
import org.mockito.Mockito.`when`
-import org.mockito.kotlin.eq
-import org.mockito.kotlin.verify
import org.mockito.quality.Strictness
/**
@@ -521,85 +518,6 @@
}
@Test
- fun minimizeTransitionReadyAndFinished_logsJankInstrumentationBeginAndEnd() {
- desktopTaskRepo.addDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
- desktopTaskRepo.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
- (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() }
- val transition = Binder()
- val task = setUpFreeformTask()
- addPendingMinimizeChange(transition, taskId = task.taskId)
-
- callOnTransitionReady(
- transition,
- TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
- )
-
- desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition)
-
- verify(interactionJankMonitor)
- .begin(any(), eq(mContext), eq(handler), 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() {
- desktopTaskRepo.addDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
- desktopTaskRepo.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
- (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() }
- val transition = Binder()
- val task = setUpFreeformTask()
- addPendingMinimizeChange(transition, taskId = task.taskId)
-
- callOnTransitionReady(
- transition,
- TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
- )
-
- desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition)
-
- verify(interactionJankMonitor)
- .begin(any(), eq(mContext), eq(handler), 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() {
- desktopTaskRepo.addDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
- desktopTaskRepo.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
- (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() }
- val mergedTransition = Binder()
- val newTransition = Binder()
- val task = setUpFreeformTask()
- addPendingMinimizeChange(mergedTransition, taskId = task.taskId)
-
- callOnTransitionReady(
- mergedTransition,
- TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
- )
-
- desktopTasksLimiter.getTransitionObserver().onTransitionStarting(mergedTransition)
-
- verify(interactionJankMonitor)
- .begin(any(), eq(mContext), eq(handler), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
-
- desktopTasksLimiter
- .getTransitionObserver()
- .onTransitionMerged(mergedTransition, newTransition)
-
- verify(interactionJankMonitor).end(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW))
- }
-
- @Test
fun getMinimizingTask_noPendingTransition_returnsNull() {
val transition = Binder()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
index c29edec..dd577f4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
@@ -24,6 +24,7 @@
import android.content.Intent
import android.os.Binder
import android.os.IBinder
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.Display.DEFAULT_DISPLAY
import android.view.WindowManager
@@ -168,7 +169,8 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
- fun backNavigation_withCloseTransitionLastTask_taskMinimized() {
+ @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER)
+ fun backNavigation_withCloseTransitionLastTask_wallpaperActivityClosed_taskMinimized() {
val task = createTaskInfo(1)
val transition = mock<IBinder>()
whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1)
@@ -193,6 +195,35 @@
}
@Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ )
+ fun backNavigation_withCloseTransitionLastTask_wallpaperActivityReordered_taskMinimized() {
+ val task = createTaskInfo(1)
+ val transition = mock<IBinder>()
+ whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1)
+ whenever(taskRepository.isClosingTask(task.taskId)).thenReturn(false)
+ whenever(backAnimationController.latestTriggerBackTask).thenReturn(task.taskId)
+
+ transitionObserver.onTransitionReady(
+ transition = transition,
+ info = createBackNavigationTransition(task, TRANSIT_CLOSE, true, TRANSIT_TO_BACK),
+ startTransaction = mock(),
+ finishTransaction = mock(),
+ )
+
+ verify(taskRepository).minimizeTask(task.displayId, task.taskId)
+ val pendingTransition =
+ DesktopMixedTransitionHandler.PendingMixedTransition.Minimize(
+ transition,
+ task.taskId,
+ isLastTask = true,
+ )
+ verify(mixedHandler).addPendingMixedTransition(pendingTransition)
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
fun backNavigation_nullTaskInfo_taskNotMinimized() {
val task = createTaskInfo(1)
@@ -434,6 +465,7 @@
task: RunningTaskInfo?,
type: Int = TRANSIT_TO_BACK,
withWallpaper: Boolean = false,
+ wallpaperChangeMode: Int = TRANSIT_CLOSE,
): TransitionInfo {
return TransitionInfo(type, /* flags= */ 0).apply {
addChange(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizerTest.kt
index 8b10ca1..96b85ad 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/multidesks/RootTaskDesksOrganizerTest.kt
@@ -22,6 +22,7 @@
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
+import android.window.WindowContainerTransaction.Change
import android.window.WindowContainerTransaction.HierarchyOp
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT
import androidx.test.filters.SmallTest
@@ -29,15 +30,19 @@
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.TestShellExecutor
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
+import com.android.wm.shell.desktopmode.multidesks.RootTaskDesksOrganizer.DeskMinimizationRoot
import com.android.wm.shell.desktopmode.multidesks.RootTaskDesksOrganizer.DeskRoot
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellInit
import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertNotNull
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.argThat
import org.mockito.kotlin.mock
/**
@@ -75,6 +80,43 @@
}
@Test
+ fun testCreateDesk_createsMinimizationRoot() {
+ val callback = FakeOnCreateCallback()
+ organizer.createDesk(Display.DEFAULT_DISPLAY, callback)
+ val freeformRoot = createFreeformTask().apply { parentTaskId = -1 }
+ organizer.onTaskAppeared(freeformRoot, SurfaceControl())
+
+ val minimizationRootTask = createFreeformTask().apply { parentTaskId = -1 }
+ organizer.onTaskAppeared(minimizationRootTask, SurfaceControl())
+
+ val minimizationRoot = organizer.deskMinimizationRootsByDeskId[freeformRoot.taskId]
+ assertNotNull(minimizationRoot)
+ assertThat(minimizationRoot.deskId).isEqualTo(freeformRoot.taskId)
+ assertThat(minimizationRoot.rootId).isEqualTo(minimizationRootTask.taskId)
+ }
+
+ @Test
+ fun testCreateMinimizationRoot_marksHidden() {
+ organizer.createDesk(Display.DEFAULT_DISPLAY, FakeOnCreateCallback())
+ val freeformRoot = createFreeformTask().apply { parentTaskId = -1 }
+ organizer.onTaskAppeared(freeformRoot, SurfaceControl())
+
+ val minimizationRootTask = createFreeformTask().apply { parentTaskId = -1 }
+ organizer.onTaskAppeared(minimizationRootTask, SurfaceControl())
+
+ verify(mockShellTaskOrganizer)
+ .applyTransaction(
+ argThat { wct ->
+ wct.changes.any { change ->
+ change.key == minimizationRootTask.token.asBinder() &&
+ (change.value.changeMask and Change.CHANGE_HIDDEN != 0) &&
+ change.value.hidden
+ }
+ }
+ )
+ }
+
+ @Test
fun testOnTaskAppeared_withoutRequest_throws() {
val freeformRoot = createFreeformTask().apply { parentTaskId = -1 }
@@ -105,57 +147,122 @@
}
@Test
+ fun testOnTaskAppeared_duplicateMinimizedRoot_throws() {
+ organizer.createDesk(Display.DEFAULT_DISPLAY, FakeOnCreateCallback())
+ val freeformRoot = createFreeformTask().apply { parentTaskId = -1 }
+ val minimizationRootTask = createFreeformTask().apply { parentTaskId = -1 }
+ organizer.onTaskAppeared(freeformRoot, SurfaceControl())
+ organizer.onTaskAppeared(minimizationRootTask, SurfaceControl())
+
+ assertThrows(Exception::class.java) {
+ organizer.onTaskAppeared(minimizationRootTask, SurfaceControl())
+ }
+ }
+
+ @Test
fun testOnTaskVanished_removesRoot() {
val desk = createDesk()
- organizer.onTaskVanished(desk.taskInfo)
+ organizer.onTaskVanished(desk.deskRoot.taskInfo)
- assertThat(organizer.roots.contains(desk.deskId)).isFalse()
+ assertThat(organizer.deskRootsByDeskId.contains(desk.deskRoot.deskId)).isFalse()
+ }
+
+ @Test
+ fun testOnTaskVanished_removesMinimizedRoot() {
+ val desk = createDesk()
+
+ organizer.onTaskVanished(desk.deskRoot.taskInfo)
+ organizer.onTaskVanished(desk.minimizationRoot.taskInfo)
+
+ assertThat(organizer.deskMinimizationRootsByDeskId.contains(desk.deskRoot.deskId)).isFalse()
}
@Test
fun testDesktopWindowAppearsInDesk() {
val desk = createDesk()
- val child = createFreeformTask().apply { parentTaskId = desk.deskId }
+ val child = createFreeformTask().apply { parentTaskId = desk.deskRoot.deskId }
organizer.onTaskAppeared(child, SurfaceControl())
- assertThat(desk.children).contains(child.taskId)
+ assertThat(desk.deskRoot.children).contains(child.taskId)
+ }
+
+ @Test
+ fun testDesktopWindowAppearsInDeskMinimizationRoot() {
+ val desk = createDesk()
+ val child = createFreeformTask().apply { parentTaskId = desk.minimizationRoot.rootId }
+
+ organizer.onTaskAppeared(child, SurfaceControl())
+
+ assertThat(desk.minimizationRoot.children).contains(child.taskId)
+ }
+
+ @Test
+ fun testDesktopWindowMovesToMinimizationRoot() {
+ val desk = createDesk()
+ val child = createFreeformTask().apply { parentTaskId = desk.deskRoot.deskId }
+ organizer.onTaskAppeared(child, SurfaceControl())
+
+ child.parentTaskId = desk.minimizationRoot.rootId
+ organizer.onTaskInfoChanged(child)
+
+ assertThat(desk.deskRoot.children).doesNotContain(child.taskId)
+ assertThat(desk.minimizationRoot.children).contains(child.taskId)
}
@Test
fun testDesktopWindowDisappearsFromDesk() {
val desk = createDesk()
- val child = createFreeformTask().apply { parentTaskId = desk.deskId }
+ val child = createFreeformTask().apply { parentTaskId = desk.deskRoot.deskId }
organizer.onTaskAppeared(child, SurfaceControl())
organizer.onTaskVanished(child)
- assertThat(desk.children).doesNotContain(child.taskId)
+ assertThat(desk.deskRoot.children).doesNotContain(child.taskId)
}
@Test
- fun testRemoveDesk() {
+ fun testDesktopWindowDisappearsFromDeskMinimizationRoot() {
+ val desk = createDesk()
+ val child = createFreeformTask().apply { parentTaskId = desk.minimizationRoot.rootId }
+
+ organizer.onTaskAppeared(child, SurfaceControl())
+ organizer.onTaskVanished(child)
+
+ assertThat(desk.minimizationRoot.children).doesNotContain(child.taskId)
+ }
+
+ @Test
+ fun testRemoveDesk_removesDeskRoot() {
val desk = createDesk()
val wct = WindowContainerTransaction()
- organizer.removeDesk(wct, desk.deskId)
+ organizer.removeDesk(wct, desk.deskRoot.deskId)
assertThat(
wct.hierarchyOps.any { hop ->
hop.type == HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK &&
- hop.container == desk.taskInfo.token.asBinder()
+ hop.container == desk.deskRoot.token.asBinder()
}
)
.isTrue()
}
@Test
- fun testRemoveDesk_didNotExist_throws() {
- val freeformRoot = createFreeformTask().apply { parentTaskId = -1 }
+ fun testRemoveDesk_removesMinimizationRoot() {
+ val desk = createDesk()
val wct = WindowContainerTransaction()
- assertThrows(Exception::class.java) { organizer.removeDesk(wct, freeformRoot.taskId) }
+ organizer.removeDesk(wct, desk.deskRoot.deskId)
+
+ assertThat(
+ wct.hierarchyOps.any { hop ->
+ hop.type == HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK &&
+ hop.container == desk.minimizationRoot.token.asBinder()
+ }
+ )
+ .isTrue()
}
@Test
@@ -163,20 +270,20 @@
val desk = createDesk()
val wct = WindowContainerTransaction()
- organizer.activateDesk(wct, desk.deskId)
+ organizer.activateDesk(wct, desk.deskRoot.deskId)
assertThat(
wct.hierarchyOps.any { hop ->
hop.type == HierarchyOp.HIERARCHY_OP_TYPE_REORDER &&
hop.toTop &&
- hop.container == desk.taskInfo.token.asBinder()
+ hop.container == desk.deskRoot.taskInfo.token.asBinder()
}
)
.isTrue()
assertThat(
wct.hierarchyOps.any { hop ->
hop.type == HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT &&
- hop.container == desk.taskInfo.token.asBinder()
+ hop.container == desk.deskRoot.taskInfo.token.asBinder()
}
)
.isTrue()
@@ -196,14 +303,14 @@
val desktopTask = createFreeformTask().apply { parentTaskId = -1 }
val wct = WindowContainerTransaction()
- organizer.moveTaskToDesk(wct, desk.deskId, desktopTask)
+ organizer.moveTaskToDesk(wct, desk.deskRoot.deskId, desktopTask)
assertThat(
wct.hierarchyOps.any { hop ->
hop.isReparent &&
hop.toTop &&
hop.container == desktopTask.token.asBinder() &&
- hop.newParent == desk.taskInfo.token.asBinder()
+ hop.newParent == desk.deskRoot.taskInfo.token.asBinder()
}
)
.isTrue()
@@ -231,13 +338,26 @@
fun testGetDeskAtEnd() {
val desk = createDesk()
- val task = createFreeformTask().apply { parentTaskId = desk.deskId }
+ val task = createFreeformTask().apply { parentTaskId = desk.deskRoot.deskId }
val endDesk =
organizer.getDeskAtEnd(
TransitionInfo.Change(task.token, SurfaceControl()).apply { taskInfo = task }
)
- assertThat(endDesk).isEqualTo(desk.deskId)
+ assertThat(endDesk).isEqualTo(desk.deskRoot.deskId)
+ }
+
+ @Test
+ fun testGetDeskAtEnd_inMinimizationRoot() {
+ val desk = createDesk()
+
+ val task = createFreeformTask().apply { parentTaskId = desk.minimizationRoot.rootId }
+ val endDesk =
+ organizer.getDeskAtEnd(
+ TransitionInfo.Change(task.token, SurfaceControl()).apply { taskInfo = task }
+ )
+
+ assertThat(endDesk).isEqualTo(desk.deskRoot.deskId)
}
@Test
@@ -264,14 +384,14 @@
fun deactivateDesk_clearsLaunchRoot() {
val wct = WindowContainerTransaction()
val desk = createDesk()
- organizer.activateDesk(wct, desk.deskId)
+ organizer.activateDesk(wct, desk.deskRoot.deskId)
- organizer.deactivateDesk(wct, desk.deskId)
+ organizer.deactivateDesk(wct, desk.deskRoot.deskId)
assertThat(
wct.hierarchyOps.any { hop ->
hop.type == HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT &&
- hop.container == desk.taskInfo.token.asBinder() &&
+ hop.container == desk.deskRoot.taskInfo.token.asBinder() &&
hop.windowingModes == null &&
hop.activityTypes == null
}
@@ -280,25 +400,129 @@
}
@Test
- fun isDeskChange() {
+ fun isDeskChange_forDeskId() {
val desk = createDesk()
assertThat(
organizer.isDeskChange(
- TransitionInfo.Change(desk.taskInfo.token, desk.leash).apply {
- taskInfo = desk.taskInfo
+ TransitionInfo.Change(desk.deskRoot.taskInfo.token, desk.deskRoot.leash).apply {
+ taskInfo = desk.deskRoot.taskInfo
},
- desk.deskId,
+ desk.deskRoot.deskId,
)
)
.isTrue()
}
- private fun createDesk(): DeskRoot {
+ @Test
+ fun isDeskChange_forDeskId_inMinimizationRoot() {
+ val desk = createDesk()
+
+ assertThat(
+ organizer.isDeskChange(
+ change =
+ TransitionInfo.Change(
+ desk.minimizationRoot.token,
+ desk.minimizationRoot.leash,
+ )
+ .apply { taskInfo = desk.minimizationRoot.taskInfo },
+ deskId = desk.deskRoot.deskId,
+ )
+ )
+ .isTrue()
+ }
+
+ @Test
+ fun isDeskChange_anyDesk() {
+ val desk = createDesk()
+
+ assertThat(
+ organizer.isDeskChange(
+ change =
+ TransitionInfo.Change(desk.deskRoot.taskInfo.token, desk.deskRoot.leash)
+ .apply { taskInfo = desk.deskRoot.taskInfo }
+ )
+ )
+ .isTrue()
+ }
+
+ @Test
+ fun isDeskChange_anyDesk_inMinimizationRoot() {
+ val desk = createDesk()
+
+ assertThat(
+ organizer.isDeskChange(
+ change =
+ TransitionInfo.Change(
+ desk.minimizationRoot.taskInfo.token,
+ desk.minimizationRoot.leash,
+ )
+ .apply { taskInfo = desk.minimizationRoot.taskInfo }
+ )
+ )
+ .isTrue()
+ }
+
+ @Test
+ fun minimizeTask() {
+ val desk = createDesk()
+ val task = createFreeformTask().apply { parentTaskId = desk.deskRoot.deskId }
+ val wct = WindowContainerTransaction()
+ organizer.moveTaskToDesk(wct, desk.deskRoot.deskId, task)
+ organizer.onTaskAppeared(task, SurfaceControl())
+
+ organizer.minimizeTask(wct, deskId = desk.deskRoot.deskId, task)
+
+ assertThat(
+ wct.hierarchyOps.any { hop ->
+ hop.isReparent &&
+ hop.container == task.token.asBinder() &&
+ hop.newParent == desk.minimizationRoot.token.asBinder()
+ }
+ )
+ .isTrue()
+ }
+
+ @Test
+ fun minimizeTask_alreadyMinimized_noOp() {
+ val desk = createDesk()
+ val task = createFreeformTask().apply { parentTaskId = desk.minimizationRoot.rootId }
+ val wct = WindowContainerTransaction()
+ organizer.onTaskAppeared(task, SurfaceControl())
+
+ organizer.minimizeTask(wct, deskId = desk.deskRoot.deskId, task)
+
+ assertThat(wct.isEmpty).isTrue()
+ }
+
+ @Test
+ fun minimizeTask_inDifferentDesk_noOp() {
+ val desk = createDesk()
+ val otherDesk = createDesk()
+ val task = createFreeformTask().apply { parentTaskId = otherDesk.deskRoot.deskId }
+ val wct = WindowContainerTransaction()
+ organizer.onTaskAppeared(task, SurfaceControl())
+
+ organizer.minimizeTask(wct, deskId = desk.deskRoot.deskId, task)
+
+ assertThat(wct.isEmpty).isTrue()
+ }
+
+ private data class DeskRoots(
+ val deskRoot: DeskRoot,
+ val minimizationRoot: DeskMinimizationRoot,
+ )
+
+ private fun createDesk(): DeskRoots {
organizer.createDesk(Display.DEFAULT_DISPLAY, FakeOnCreateCallback())
val freeformRoot = createFreeformTask().apply { parentTaskId = -1 }
organizer.onTaskAppeared(freeformRoot, SurfaceControl())
- return organizer.roots[freeformRoot.taskId]
+ val minimizationRoot = createFreeformTask().apply { parentTaskId = -1 }
+ organizer.onTaskAppeared(minimizationRoot, SurfaceControl())
+ return DeskRoots(
+ organizer.deskRootsByDeskId[freeformRoot.taskId],
+ checkNotNull(organizer.deskMinimizationRootsByDeskId[freeformRoot.taskId]),
+ )
}
private class FakeOnCreateCallback : DesksOrganizer.OnCreateCallback {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
index fd5e567..93dd345 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
@@ -17,16 +17,20 @@
package com.android.wm.shell.recents;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_SLEEP;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX;
+import static com.android.wm.shell.Flags.FLAG_ENABLE_RECENTS_BOOKEND_TRANSITION;
import static com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_ANIMATING;
import static com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING;
import static com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_END_RECENTS_TRANSITION;
import static com.android.wm.shell.transition.Transitions.TRANSIT_START_RECENTS_TRANSITION;
import static com.google.common.truth.Truth.assertThat;
@@ -64,7 +68,6 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.internal.os.IResultReceiver;
-import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
@@ -73,6 +76,7 @@
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
+import com.android.wm.shell.shared.R;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
@@ -308,8 +312,7 @@
mRecentsTransitionHandler.findController(transition).merge(
mergeTransitionInfo,
new StubTransaction(),
- finishT,
- transition,
+ new StubTransaction(),
mock(Transitions.TransitionFinishCallback.class));
mMainExecutor.flushAll();
@@ -318,6 +321,69 @@
}
@Test
+ @EnableFlags(FLAG_ENABLE_RECENTS_BOOKEND_TRANSITION)
+ public void testMerge_consumeBookendTransition() throws Exception {
+ // Start and finish the transition
+ final IRecentsAnimationRunner animationRunner = mock(IRecentsAnimationRunner.class);
+ final IBinder transition = startRecentsTransition(/* synthetic= */ false, animationRunner);
+ mRecentsTransitionHandler.startAnimation(
+ transition, createTransitionInfo(), new StubTransaction(), new StubTransaction(),
+ mock(Transitions.TransitionFinishCallback.class));
+ mRecentsTransitionHandler.findController(transition).finish(/* toHome= */ false,
+ false /* sendUserLeaveHint */, mock(IResultReceiver.class));
+ mMainExecutor.flushAll();
+
+ // Merge the bookend transition
+ TransitionInfo mergeTransitionInfo =
+ new TransitionInfoBuilder(TRANSIT_END_RECENTS_TRANSITION)
+ .addChange(TRANSIT_OPEN, new TestRunningTaskInfoBuilder().build())
+ .build();
+ SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ Transitions.TransitionFinishCallback finishCallback
+ = mock(Transitions.TransitionFinishCallback.class);
+ mRecentsTransitionHandler.findController(transition).merge(
+ mergeTransitionInfo,
+ new StubTransaction(),
+ finishT,
+ finishCallback);
+ mMainExecutor.flushAll();
+
+ // Verify that we've merged
+ verify(finishCallback).onTransitionFinished(any());
+ }
+
+ @Test
+ @EnableFlags(FLAG_ENABLE_RECENTS_BOOKEND_TRANSITION)
+ public void testMerge_pendingBookendTransition_mergesTransition() throws Exception {
+ // Start and finish the transition
+ final IRecentsAnimationRunner animationRunner = mock(IRecentsAnimationRunner.class);
+ final IBinder transition = startRecentsTransition(/* synthetic= */ false, animationRunner);
+ mRecentsTransitionHandler.startAnimation(
+ transition, createTransitionInfo(), new StubTransaction(), new StubTransaction(),
+ mock(Transitions.TransitionFinishCallback.class));
+ mRecentsTransitionHandler.findController(transition).finish(/* toHome= */ false,
+ false /* sendUserLeaveHint */, mock(IResultReceiver.class));
+ mMainExecutor.flushAll();
+
+ // Merge a new transition while we have a pending finish
+ TransitionInfo mergeTransitionInfo = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN, new TestRunningTaskInfoBuilder().build())
+ .build();
+ SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ Transitions.TransitionFinishCallback finishCallback
+ = mock(Transitions.TransitionFinishCallback.class);
+ mRecentsTransitionHandler.findController(transition).merge(
+ mergeTransitionInfo,
+ new StubTransaction(),
+ finishT,
+ finishCallback);
+ mMainExecutor.flushAll();
+
+ // Verify that we've cleaned up the original transition
+ assertNull(mRecentsTransitionHandler.findController(transition));
+ }
+
+ @Test
@EnableFlags(FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX)
public void testMergeAndFinish_openingFreeformTasks_setsCornerRadius() {
ActivityManager.RunningTaskInfo freeformTask =
@@ -336,7 +402,6 @@
mergeTransitionInfo,
new StubTransaction(),
finishT,
- transition,
mock(Transitions.TransitionFinishCallback.class));
mRecentsTransitionHandler.findController(transition).finish(/* toHome= */ false,
false /* sendUserLeaveHint */, mock(IResultReceiver.class));
@@ -385,15 +450,23 @@
}
private TransitionInfo createTransitionInfo() {
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder()
+ final ActivityManager.RunningTaskInfo homeTask = new TestRunningTaskInfoBuilder()
.setTopActivityType(ACTIVITY_TYPE_HOME)
.build();
+ final ActivityManager.RunningTaskInfo appTask = new TestRunningTaskInfoBuilder()
+ .setTopActivityType(ACTIVITY_TYPE_STANDARD)
+ .build();
final TransitionInfo.Change homeChange = new TransitionInfo.Change(
- task.token, new SurfaceControl());
+ homeTask.token, new SurfaceControl());
homeChange.setMode(TRANSIT_TO_FRONT);
- homeChange.setTaskInfo(task);
+ homeChange.setTaskInfo(homeTask);
+ final TransitionInfo.Change appChange = new TransitionInfo.Change(
+ appTask.token, new SurfaceControl());
+ appChange.setMode(TRANSIT_TO_FRONT);
+ appChange.setTaskInfo(appTask);
return new TransitionInfoBuilder(TRANSIT_START_RECENTS_TRANSITION)
.addChange(homeChange)
+ .addChange(appChange)
.build();
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/MinimizeAnimatorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/MinimizeAnimatorTest.kt
new file mode 100644
index 0000000..ba609d4
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/MinimizeAnimatorTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.shared.animation
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.animation.ValueAnimator
+import android.content.Context
+import android.content.res.Resources
+import android.os.Handler
+import android.util.DisplayMetrics
+import android.view.SurfaceControl
+import android.view.SurfaceControl.Transaction
+import android.window.TransitionInfo
+import android.window.WindowContainerToken
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
+import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW
+import com.android.internal.jank.InteractionJankMonitor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.anyLong
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MinimizeAnimatorTest {
+ private val context = mock<Context>()
+ private val resources = mock<Resources>()
+ private val transaction = mock<Transaction>()
+ private val leash = mock<SurfaceControl>()
+ private val interactionJankMonitor = mock<InteractionJankMonitor>()
+ private val animationHandler = mock<Handler>()
+
+ private val displayMetrics = DisplayMetrics().apply { density = 1f }
+
+ @Before
+ fun setup() {
+ whenever(context.resources).thenReturn(resources)
+ whenever(resources.displayMetrics).thenReturn(displayMetrics)
+ whenever(transaction.setAlpha(any(), anyFloat())).thenReturn(transaction)
+ whenever(transaction.setPosition(any(), anyFloat(), anyFloat())).thenReturn(transaction)
+ whenever(transaction.setScale(any(), anyFloat(), anyFloat())).thenReturn(transaction)
+ whenever(transaction.setFrameTimeline(anyLong())).thenReturn(transaction)
+ }
+
+ @Test
+ fun create_returnsBoundsAndAlphaAnimators() {
+ val change = TransitionInfo.Change(mock<WindowContainerToken>(), leash)
+
+ val animator = createAnimator(change)
+
+ assertThat(animator).isInstanceOf(AnimatorSet::class.java)
+ val animatorSet = animator as AnimatorSet
+ assertThat(animatorSet.childAnimations).hasSize(2)
+ assertIsBoundsAnimator(animatorSet.childAnimations[0])
+ assertIsAlphaAnimator(animatorSet.childAnimations[1])
+ }
+
+ @Test
+ fun create_doesNotlogJankInstrumentation() = runOnUiThread {
+ val change = TransitionInfo.Change(mock<WindowContainerToken>(), leash)
+
+ createAnimator(change)
+
+ verify(interactionJankMonitor, never()).begin(
+ leash, context, animationHandler, CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
+ }
+
+ @Test
+ fun onAnimationStart_logsJankInstrumentation() = runOnUiThread {
+ val change = TransitionInfo.Change(mock<WindowContainerToken>(), leash)
+
+ createAnimator(change).start()
+
+ verify(interactionJankMonitor).begin(
+ leash, context, animationHandler, CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
+ }
+
+ private fun createAnimator(change: TransitionInfo.Change): Animator =
+ MinimizeAnimator.create(context, change, transaction, {}, interactionJankMonitor,
+ animationHandler)
+
+ private fun assertIsBoundsAnimator(animator: Animator) {
+ assertThat(animator).isInstanceOf(ValueAnimator::class.java)
+ assertThat(animator.duration).isEqualTo(200)
+ assertThat(animator.interpolator).isEqualTo(Interpolators.STANDARD_ACCELERATE)
+ }
+
+ private fun assertIsAlphaAnimator(animator: Animator) {
+ assertThat(animator).isInstanceOf(ValueAnimator::class.java)
+ assertThat(animator.duration).isEqualTo(100)
+ assertThat(animator.interpolator).isEqualTo(Interpolators.LINEAR)
+ }
+}
+
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
index f69bf34..88c6e49 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
@@ -16,13 +16,16 @@
package com.android.wm.shell.shared.desktopmode
+import android.Manifest.permission.SYSTEM_ALERT_WINDOW
import android.app.TaskInfo
import android.compat.testing.PlatformCompatChangeRule
import android.content.ComponentName
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
+import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Process
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
@@ -39,7 +42,9 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
@@ -55,6 +60,7 @@
private lateinit var desktopModeCompatPolicy: DesktopModeCompatPolicy
private val packageManager: PackageManager = mock()
private val homeActivities = ComponentName(HOME_LAUNCHER_PACKAGE_NAME, /* class */ "")
+ private val baseActivityTest = ComponentName("com.test.dummypackage", "TestClass")
@Before
fun setUp() {
@@ -64,6 +70,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION)
fun testIsTopActivityExemptFromDesktopWindowing_onlyTransparentActivitiesInStack() {
assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
createFreeformTask(/* displayId */ 0)
@@ -71,10 +78,39 @@
isActivityStackTransparent = true
isTopActivityNoDisplay = false
numActivities = 1
+ baseActivity = baseActivityTest
}))
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION)
+ fun testIsTopActivityExemptWithPermission_onlyTransparentActivitiesInStack() {
+ allowOverlayPermission(arrayOf(SYSTEM_ALERT_WINDOW))
+ assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
+ createFreeformTask(/* displayId */ 0)
+ .apply {
+ isActivityStackTransparent = true
+ isTopActivityNoDisplay = false
+ numActivities = 1
+ baseActivity = baseActivityTest
+ }))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION)
+ fun testIsTopActivityExemptWithNoPermission_onlyTransparentActivitiesInStack() {
+ allowOverlayPermission(arrayOf())
+ assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
+ createFreeformTask(/* displayId */ 0)
+ .apply {
+ isActivityStackTransparent = true
+ isTopActivityNoDisplay = false
+ numActivities = 1
+ baseActivity = baseActivityTest
+ }))
+ }
+
+ @Test
fun testIsTopActivityExemptFromDesktopWindowing_noActivitiesInStack() {
assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
createFreeformTask(/* displayId */ 0)
@@ -219,4 +255,15 @@
}
}
}
+
+ fun allowOverlayPermission(permissions: Array<String>) {
+ val packageInfo = mock<PackageInfo>()
+ packageInfo.requestedPermissions = permissions
+ whenever(
+ packageManager.getPackageInfo(
+ anyString(),
+ eq(PackageManager.GET_PERMISSIONS)
+ )
+ ).thenReturn(packageInfo)
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
index 6f28e656..3099b0f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
@@ -17,36 +17,44 @@
package com.android.wm.shell.transition;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION;
import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.WindowConfiguration.ActivityType;
import android.content.Context;
+import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.TransitionInfo.TransitionMode;
+import android.window.WindowContainerToken;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.wm.shell.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
@@ -188,6 +196,72 @@
}
@Test
+ @EnableFlags({Flags.FLAG_ENABLE_BUBBLE_TO_FULLSCREEN, Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE})
+ public void testDragTaskToBubbleOverHome_notifiesHomeIsVisible() throws RemoteException {
+ ActivityManager.RunningTaskInfo homeTask = createTaskInfo(1, ACTIVITY_TYPE_HOME);
+ ActivityManager.RunningTaskInfo bubbleTask = createTaskInfo(2, ACTIVITY_TYPE_STANDARD);
+
+ TransitionInfo startDragTransition =
+ new TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP)
+ .addChange(TRANSIT_TO_FRONT, homeTask)
+ .addChange(TRANSIT_TO_BACK, bubbleTask)
+ .build();
+
+ // Start drag to desktop which brings home to front
+ mHomeTransitionObserver.onTransitionReady(new Binder(), startDragTransition,
+ MockTransactionPool.create(), MockTransactionPool.create());
+ // Does not notify home visibility yet
+ verify(mListener, never()).onHomeVisibilityChanged(anyBoolean());
+
+ TransitionInfo convertToBubbleTransition =
+ new TransitionInfoBuilder(TRANSIT_CONVERT_TO_BUBBLE)
+ .addChange(TRANSIT_TO_FRONT, bubbleTask)
+ .build();
+
+ // Convert to bubble. Transition does not include changes for home task
+ mHomeTransitionObserver.onTransitionReady(new Binder(), convertToBubbleTransition,
+ MockTransactionPool.create(), MockTransactionPool.create());
+
+ // Notifies home visibility change that was pending from the start of drag
+ verify(mListener).onHomeVisibilityChanged(true);
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_ENABLE_BUBBLE_TO_FULLSCREEN, Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE})
+ public void testDragTaskToBubbleOverOtherTask_notifiesHomeIsNotVisible()
+ throws RemoteException {
+ ActivityManager.RunningTaskInfo homeTask = createTaskInfo(1, ACTIVITY_TYPE_HOME);
+ ActivityManager.RunningTaskInfo bubbleTask = createTaskInfo(2, ACTIVITY_TYPE_STANDARD);
+ ActivityManager.RunningTaskInfo otherTask = createTaskInfo(3, ACTIVITY_TYPE_STANDARD);
+
+ TransitionInfo startDragTransition =
+ new TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP)
+ .addChange(TRANSIT_TO_FRONT, homeTask)
+ .addChange(TRANSIT_TO_BACK, bubbleTask)
+ .build();
+
+ // Start drag to desktop which brings home to front
+ mHomeTransitionObserver.onTransitionReady(new Binder(), startDragTransition,
+ MockTransactionPool.create(), MockTransactionPool.create());
+ // Does not notify home visibility yet
+ verify(mListener, never()).onHomeVisibilityChanged(anyBoolean());
+
+ TransitionInfo convertToBubbleTransition =
+ new TransitionInfoBuilder(TRANSIT_CONVERT_TO_BUBBLE)
+ .addChange(TRANSIT_TO_FRONT, bubbleTask)
+ .addChange(TRANSIT_TO_FRONT, otherTask)
+ .addChange(TRANSIT_TO_BACK, homeTask)
+ .build();
+
+ // Convert to bubble. Transition includes home task to back which updates home visibility
+ mHomeTransitionObserver.onTransitionReady(new Binder(), convertToBubbleTransition,
+ MockTransactionPool.create(), MockTransactionPool.create());
+
+ // Notifies home visibility change due to home moving to back in the second transition
+ verify(mListener).onHomeVisibilityChanged(false);
+ }
+
+ @Test
public void testHomeActivityWithBackGestureNotifiesHomeIsVisibleAfterClose()
throws RemoteException {
TransitionInfo info = mock(TransitionInfo.class);
@@ -227,4 +301,14 @@
when(change.getMode()).thenReturn(mode);
taskInfo.isRunning = isRunning;
}
+
+ private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int activityType) {
+ ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
+ taskInfo.taskId = taskId;
+ taskInfo.topActivityType = activityType;
+ taskInfo.configuration.windowConfiguration.setActivityType(activityType);
+ taskInfo.token = mock(WindowContainerToken.class);
+ taskInfo.isRunning = true;
+ return taskInfo;
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
index 8cccdb2..81dfaed 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
@@ -52,6 +52,7 @@
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.MultiDisplayDragMoveIndicatorController
import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler
@@ -138,6 +139,8 @@
protected val mockFreeformTaskTransitionStarter = mock<FreeformTaskTransitionStarter>()
protected val mockActivityOrientationChangeHandler =
mock<DesktopActivityOrientationChangeHandler>()
+ protected val mockMultiDisplayDragMoveIndicatorController =
+ mock<MultiDisplayDragMoveIndicatorController>()
protected val mockInputManager = mock<InputManager>()
private val mockTaskPositionerFactory =
mock<DesktopModeWindowDecorViewModel.TaskPositionerFactory>()
@@ -229,6 +232,7 @@
mockRecentsTransitionHandler,
desktopModeCompatPolicy,
mockTilingWindowDecoration,
+ mockMultiDisplayDragMoveIndicatorController,
)
desktopModeWindowDecorViewModel.setSplitScreenController(mockSplitScreenController)
whenever(mockDisplayController.getDisplayLayout(any())).thenReturn(mockDisplayLayout)
@@ -243,6 +247,7 @@
any(),
any(),
any(),
+ any(),
any()
)
)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt
index 937938d..a6b0770 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt
@@ -41,6 +41,7 @@
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
+import com.android.wm.shell.common.MultiDisplayDragMoveIndicatorController
import com.android.wm.shell.common.MultiDisplayTestUtil
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TransitionFinishCallback
@@ -62,8 +63,8 @@
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
/**
@@ -93,7 +94,8 @@
@Mock private lateinit var mockTransitions: Transitions
@Mock private lateinit var mockInteractionJankMonitor: InteractionJankMonitor
@Mock private lateinit var mockSurfaceControl: SurfaceControl
-
+ @Mock private lateinit var mockMultiDisplayDragMoveIndicatorController:
+ MultiDisplayDragMoveIndicatorController
private lateinit var resources: TestableResources
private lateinit var spyDisplayLayout0: DisplayLayout
private lateinit var spyDisplayLayout1: DisplayLayout
@@ -170,10 +172,11 @@
mockDesktopWindowDecoration,
mockDisplayController,
mockDragEventListener,
- mockTransactionFactory,
+ { mockTransaction },
mockTransitions,
mockInteractionJankMonitor,
mainHandler,
+ mockMultiDisplayDragMoveIndicatorController,
)
}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index f5e10d9..7a51c20 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -44,6 +44,9 @@
namespace {
+constexpr int32_t kDefaultDisplayId = 0;
+constexpr int32_t kDefaultDeviceId = 0;
+
using EntryValue = std::variant<Res_value, incfs::verified_map_ptr<ResTable_map_entry>>;
/* NOTE: table_entry has been verified in LoadedPackage::GetEntryFromOffset(),
@@ -61,7 +64,7 @@
return table_entry->value();
}
-} // namespace
+} // namespace
struct FindEntryResult {
// The cookie representing the ApkAssets in which the value resides.
@@ -99,14 +102,15 @@
Res_value value;
};
-AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration) {
+AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration)
+ : display_id_(kDefaultDisplayId), device_id_(kDefaultDeviceId) {
configurations_.push_back(configuration);
// Don't invalidate caches here as there's nothing cached yet.
SetApkAssets(apk_assets, false);
}
-AssetManager2::AssetManager2() {
+AssetManager2::AssetManager2() : display_id_(kDefaultDisplayId), device_id_(kDefaultDeviceId) {
configurations_.emplace_back();
}
@@ -172,8 +176,7 @@
// to take effect.
auto iter = target_assets_package_ids.find(loaded_idmap->TargetApkPath());
if (iter == target_assets_package_ids.end()) {
- LOG(INFO) << "failed to find target package for overlay "
- << loaded_idmap->OverlayApkPath();
+ LOG(INFO) << "failed to find target package for overlay " << loaded_idmap->OverlayApkPath();
} else {
uint8_t target_package_id = iter->second;
@@ -189,10 +192,11 @@
<< " assigned package group";
PackageGroup& target_package_group = package_groups_[target_idx];
- target_package_group.overlays_.push_back(
- ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id,
- overlay_ref_table.get()),
- apk_assets_cookies[apk_assets]});
+ target_package_group.overlays_.push_back(ConfiguredOverlay{
+ loaded_idmap->GetTargetResourcesMap(target_package_id, overlay_ref_table.get()),
+ apk_assets_cookies[apk_assets],
+ IsAnyOverlayConstraintSatisfied(loaded_idmap->GetConstraints())
+ });
}
}
@@ -291,7 +295,7 @@
}
LOG(INFO) << "Package ID map: " << list;
- for (const auto& package_group: package_groups_) {
+ for (const auto& package_group : package_groups_) {
list = "";
for (const auto& package : package_group.packages_) {
const LoadedPackage* loaded_package = package.loaded_package_;
@@ -347,7 +351,6 @@
const std::unordered_map<std::string, std::string>*
AssetManager2::GetOverlayableMapForPackage(uint32_t package_id) const {
-
if (package_id >= package_ids_.size()) {
return nullptr;
}
@@ -462,6 +465,28 @@
}
}
+void AssetManager2::SetOverlayConstraints(int32_t display_id, int32_t device_id) {
+ bool changed = false;
+ if (display_id_ != display_id) {
+ display_id_ = display_id;
+ changed = true;
+ }
+ if (device_id_ != device_id) {
+ device_id_ = device_id;
+ changed = true;
+ }
+ if (changed) {
+ // Enable/disable overlays based on current constraints
+ for (PackageGroup& group : package_groups_) {
+ for (auto &overlay: group.overlays_) {
+ overlay.enabled = IsAnyOverlayConstraintSatisfied(
+ overlay.overlay_res_maps_.GetConstraints());
+ }
+ }
+ InvalidateCaches(static_cast<uint32_t>(-1));
+ }
+}
+
std::set<AssetManager2::ApkAssetsPtr> AssetManager2::GetNonSystemOverlays() const {
std::set<ApkAssetsPtr> non_system_overlays;
for (const PackageGroup& package_group : package_groups_) {
@@ -475,6 +500,8 @@
if (!found_system_package) {
auto op = StartOperation();
+ // Return all overlays, including the disabled ones as this is used for static info
+ // collection only.
for (const ConfiguredOverlay& overlay : package_group.overlays_) {
if (const auto& asset = GetApkAssets(overlay.cookie)) {
non_system_overlays.insert(std::move(asset));
@@ -651,7 +678,6 @@
auto op = StartOperation();
-
// Retrieve the package group from the package id of the resource id.
if (UNLIKELY(!is_valid_resid(resid))) {
LOG(ERROR) << base::StringPrintf("Invalid resource ID 0x%08x.", resid);
@@ -672,7 +698,7 @@
std::optional<FindEntryResult> final_result;
bool final_has_locale = false;
bool final_overlaid = false;
- for (auto & config : configurations_) {
+ for (auto& config : configurations_) {
// Might use this if density_override != 0.
ResTable_config density_override_config;
@@ -698,7 +724,8 @@
}
if (!assets->IsLoader()) {
for (const auto& id_map : package_group.overlays_) {
- auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid);
+ auto overlay_entry = id_map.enabled ?
+ id_map.overlay_res_maps_.Lookup(resid) : IdmapResMap::Result();
if (!overlay_entry) {
// No id map entry exists for this target resource.
continue;
@@ -708,7 +735,7 @@
ConfigDescription best_frro_config;
Res_value best_frro_value;
bool frro_found = false;
- for( const auto& [config, value] : overlay_entry.GetInlineValue()) {
+ for (const auto& [config, value] : overlay_entry.GetInlineValue()) {
if ((!frro_found || config.isBetterThan(best_frro_config, desired_config))
&& config.match(*desired_config)) {
frro_found = true;
@@ -1011,7 +1038,7 @@
resid, resource_name_string.c_str(), conf.toString().c_str());
char str[40];
str[0] = '\0';
- for(auto iter = configurations_.begin(); iter < configurations_.end(); iter++) {
+ for (auto iter = configurations_.begin(); iter < configurations_.end(); iter++) {
iter->getBcp47Locale(str);
log_stream << base::StringPrintf(" %s%s", str, iter < configurations_.end() ? "," : "");
}
@@ -1504,7 +1531,7 @@
package.loaded_package_->ForEachTypeSpec([&](const TypeSpec& type_spec, uint8_t type_id) {
FilteredConfigGroup* group = nullptr;
for (const auto& type_entry : type_spec.type_entries) {
- for (auto & config : configurations_) {
+ for (auto& config : configurations_) {
if (type_entry.config.match(config)) {
if (!group) {
group = &package.filtered_configs_.editItemAt(type_id - 1);
@@ -1521,6 +1548,27 @@
}
}
+bool AssetManager2::IsAnyOverlayConstraintSatisfied(const Idmap_constraints& constraints) const {
+ if (constraints.constraint_count == 0) {
+ // There are no constraints, return true.
+ return true;
+ }
+
+ for (uint32_t i = 0; i < constraints.constraint_count; i++) {
+ auto constraint = constraints.constraint_entries[i];
+ if (constraint.constraint_type == kOverlayConstraintTypeDisplayId &&
+ constraint.constraint_value == display_id_) {
+ return true;
+ }
+ if (constraint.constraint_type == kOverlayConstraintTypeDeviceId &&
+ constraint.constraint_value == device_id_) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void AssetManager2::InvalidateCaches(uint32_t diff) {
cached_resolved_values_.clear();
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index f0ef97e5..8d1de1a 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -56,13 +56,6 @@
// without having to read/store each header entry separately.
};
-struct Idmap_constraint {
- // Constraint type can be TYPE_DISPLAY_ID or TYP_DEVICE_ID, please refer
- // to ConstraintType in OverlayConstraint.java
- uint32_t constraint_type;
- uint32_t constraint_value;
-};
-
struct Idmap_data_header {
uint32_t target_entry_count;
uint32_t target_inline_entry_count;
@@ -148,12 +141,13 @@
return DynamicRefTable::lookupResourceId(resId);
}
-IdmapResMap::IdmapResMap(const Idmap_data_header* data_header, Idmap_target_entries entries,
- Idmap_target_inline_entries inline_entries,
+IdmapResMap::IdmapResMap(const Idmap_data_header* data_header, const Idmap_constraints& constraints,
+ Idmap_target_entries entries, Idmap_target_inline_entries inline_entries,
const Idmap_target_entry_inline_value* inline_entry_values,
const ConfigDescription* configs, uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table)
: data_header_(data_header),
+ constraints_(constraints),
entries_(entries),
inline_entries_(inline_entries),
inline_entry_values_(inline_entry_values),
@@ -254,7 +248,7 @@
}
return std::string_view(data, *len);
}
-} // namespace
+} // namespace
// O_PATH is a lightweight way of creating an FD, only exists on Linux
#ifndef O_PATH
@@ -262,9 +256,7 @@
#endif
LoadedIdmap::LoadedIdmap(const std::string& idmap_path, const Idmap_header* header,
- const Idmap_constraint* constraints,
- uint32_t constraints_count,
- const Idmap_data_header* data_header,
+ const Idmap_data_header* data_header, const Idmap_constraints& constraints,
Idmap_target_entries target_entries,
Idmap_target_inline_entries target_inline_entries,
const Idmap_target_entry_inline_value* inline_entry_values,
@@ -272,9 +264,8 @@
std::unique_ptr<ResStringPool>&& string_pool,
std::string_view overlay_apk_path, std::string_view target_apk_path)
: header_(header),
- constraints_(constraints),
- constraints_count_(constraints_count),
data_header_(data_header),
+ constraints_(constraints),
target_entries_(target_entries),
target_inline_entries_(target_inline_entries),
inline_entry_values_(inline_entry_values),
@@ -328,16 +319,20 @@
return {};
}
- auto constraints_count = ReadType<uint32_t>(&data_ptr, &data_size, "constraints count");
- if (!constraints_count) {
+ auto constraint_count = ReadType<uint32_t>(&data_ptr, &data_size, "constraint count");
+ if (!constraint_count) {
+ LOG(ERROR) << "idmap doesn't have constraint count";
return {};
}
- auto constraints = *constraints_count > 0 ?
- ReadType<Idmap_constraint>(&data_ptr, &data_size, "constraints", *constraints_count)
+ auto constraint_entries = *constraint_count > 0 ?
+ ReadType<Idmap_constraint>(&data_ptr, &data_size, "constraints", dtohl(*constraint_count))
: nullptr;
- if (*constraints_count > 0 && !constraints) {
+ if (*constraint_count > 0 && !constraint_entries) {
+ LOG(ERROR) << "no constraint entries in idmap with non-zero constraints";
return {};
}
+ Idmap_constraints constraints{.constraint_count = *constraint_count,
+ .constraint_entries = constraint_entries};
// Parse the idmap data blocks. Currently idmap2 can only generate one data block.
auto data_header = ReadType<Idmap_data_header>(&data_ptr, &data_size, "data header");
@@ -405,10 +400,9 @@
// Can't use make_unique because LoadedIdmap constructor is private.
return std::unique_ptr<LoadedIdmap>(
- new LoadedIdmap(std::string(idmap_path), header, constraints, *constraints_count,
- data_header, target_entries, target_inline_entries,
- target_inline_entry_values,configurations, overlay_entries,
- std::move(idmap_string_pool),*overlay_path, *target_path));
+ new LoadedIdmap(std::string(idmap_path), header, data_header, constraints, target_entries,
+ target_inline_entries, target_inline_entry_values, configurations,
+ overlay_entries, std::move(idmap_string_pool), *overlay_path, *target_path));
}
UpToDate LoadedIdmap::IsUpToDate() const {
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 0fdeefa..a47fe6a7 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -171,6 +171,8 @@
default_locale_ = default_locale;
}
+ void SetOverlayConstraints(int32_t display_id, int32_t device_id);
+
// Returns all configurations for which there are resources defined, or an I/O error if reading
// resource data failed.
//
@@ -389,6 +391,9 @@
// The cookie of the overlay assets.
ApkAssetsCookie cookie;
+
+ // Enable/disable status of the overlay based on current constraints of AssetManager.
+ bool enabled;
};
// Represents a logical package, which can be made up of many individual packages. Each package
@@ -457,6 +462,8 @@
// promoted apk assets when the last operation ends.
void FinishOperation() const;
+ bool IsAnyOverlayConstraintSatisfied(const Idmap_constraints& constraints) const;
+
// The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
// have a longer lifetime.
// The second pair element is the promoted version of the assets, that is held for the duration
@@ -480,6 +487,9 @@
// may need to be purged.
ftl::SmallVector<ResTable_config, 1> configurations_;
+ int32_t display_id_;
+ int32_t device_id_;
+
// Cached set of bags. These are cached because they can inherit keys from parent bags,
// which involves some calculation.
mutable std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_;
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index 0c08563..939b624 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -59,13 +59,25 @@
class LoadedIdmap;
class IdmapResMap;
struct Idmap_header;
-struct Idmap_constraint;
+struct Idmap_constraints;
struct Idmap_data_header;
-struct Idmap_target_entry;
struct Idmap_target_entry_inline;
struct Idmap_target_entry_inline_value;
-struct Idmap_overlay_entry;
+// LINT.IfChange
+constexpr int32_t kOverlayConstraintTypeDisplayId = 0;
+constexpr int32_t kOverlayConstraintTypeDeviceId = 1;
+// LINT.ThenChange(../../../../core/java/android/content/om/OverlayConstraint.java)
+
+struct Idmap_constraint {
+ // Constraint type can be kOverlayConstraintTypeDisplayId or kOverlayConstraintTypeDeviceId
+ const uint32_t constraint_type;
+ const uint32_t constraint_value;
+};
+struct Idmap_constraints {
+ const uint32_t constraint_count = 0;
+ const Idmap_constraint* constraint_entries = nullptr;
+};
struct Idmap_target_entries {
const uint32_t* target_id = nullptr;
const uint32_t* overlay_id = nullptr;
@@ -169,14 +181,19 @@
return overlay_ref_table_;
}
+ inline Idmap_constraints GetConstraints() const {
+ return constraints_;
+ }
+
private:
- explicit IdmapResMap(const Idmap_data_header* data_header, Idmap_target_entries entries,
- Idmap_target_inline_entries inline_entries,
+ explicit IdmapResMap(const Idmap_data_header* data_header, const Idmap_constraints& constraints,
+ Idmap_target_entries entries, Idmap_target_inline_entries inline_entries,
const Idmap_target_entry_inline_value* inline_entry_values,
const ConfigDescription* configs, uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table);
const Idmap_data_header* data_header_;
+ Idmap_constraints constraints_;
Idmap_target_entries entries_;
Idmap_target_inline_entries inline_entries_;
const Idmap_target_entry_inline_value* inline_entry_values_;
@@ -210,8 +227,9 @@
// Returns a mapping from target resource ids to overlay values.
IdmapResMap GetTargetResourcesMap(uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table) const {
- return IdmapResMap(data_header_, target_entries_, target_inline_entries_, inline_entry_values_,
- configurations_, target_assigned_package_id, overlay_ref_table);
+ return IdmapResMap(data_header_, constraints_, target_entries_, target_inline_entries_,
+ inline_entry_values_, configurations_, target_assigned_package_id,
+ overlay_ref_table);
}
// Returns a dynamic reference table for a loaded overlay package.
@@ -223,14 +241,17 @@
// LoadedIdmap.
UpToDate IsUpToDate() const;
+ inline const Idmap_constraints GetConstraints() const {
+ return constraints_;
+ }
+
protected:
// Exposed as protected so that tests can subclass and mock this class out.
LoadedIdmap() = default;
const Idmap_header* header_;
- const Idmap_constraint* constraints_;
- uint32_t constraints_count_;
const Idmap_data_header* data_header_;
+ Idmap_constraints constraints_;
Idmap_target_entries target_entries_;
Idmap_target_inline_entries target_inline_entries_;
const Idmap_target_entry_inline_value* inline_entry_values_;
@@ -247,9 +268,7 @@
DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
explicit LoadedIdmap(const std::string& idmap_path, const Idmap_header* header,
- const Idmap_constraint* constraints,
- uint32_t constraints_count,
- const Idmap_data_header* data_header,
+ const Idmap_data_header* data_header, const Idmap_constraints& constraints,
Idmap_target_entries target_entries,
Idmap_target_inline_entries target_inline_entries,
const Idmap_target_entry_inline_value* inline_entry_values_,
diff --git a/libs/hostgraphics/include/gui/BufferItemConsumer.h b/libs/hostgraphics/include/gui/BufferItemConsumer.h
index c259411..5c96c82 100644
--- a/libs/hostgraphics/include/gui/BufferItemConsumer.h
+++ b/libs/hostgraphics/include/gui/BufferItemConsumer.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GUI_BUFFERITEMCONSUMER_H
#define ANDROID_GUI_BUFFERITEMCONSUMER_H
+#include <com_android_graphics_libgui_flags.h>
+#include <gui/BufferQueue.h>
#include <gui/ConsumerBase.h>
#include <gui/IGraphicBufferConsumer.h>
#include <utils/RefBase.h>
@@ -26,9 +28,22 @@
class BufferItemConsumer : public ConsumerBase {
public:
BufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
- int bufferCount, bool controlledByApp)
+ int bufferCount = -1, bool controlledByApp = false)
: mConsumer(consumer) {}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ BufferItemConsumer(uint64_t consumerUsage, int bufferCount = -1,
+ bool controlledByApp = false, bool isConsumerSurfaceFlinger = false) {
+ sp<IGraphicBufferProducer> producer;
+ BufferQueue::createBufferQueue(&producer, &mConsumer);
+ mSurface = sp<Surface>::make(producer, controlledByApp);
+ }
+
+ status_t setConsumerIsProtected(bool isProtected) {
+ return OK;
+ }
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+
status_t acquireBuffer(BufferItem* item, nsecs_t presentWhen, bool waitForFence = true) {
return mConsumer->acquireBuffer(item, presentWhen, 0);
}
@@ -71,8 +86,20 @@
return OK;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+// Returns a Surface that can be used as the producer for this consumer.
+ sp<Surface> getSurface() const {
+ return mSurface;
+ }
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+
private:
sp<IGraphicBufferConsumer> mConsumer;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ // This Surface wraps the IGraphicBufferConsumer created for this
+ // ConsumerBase.
+ sp<Surface> mSurface;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
};
} // namespace android
diff --git a/libs/hostgraphics/include/gui/Surface.h b/libs/hostgraphics/include/gui/Surface.h
index 2774f89..e268ce6 100644
--- a/libs/hostgraphics/include/gui/Surface.h
+++ b/libs/hostgraphics/include/gui/Surface.h
@@ -34,6 +34,10 @@
ANativeWindow::query = hook_query;
}
+ sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
+ return mBufferProducer;
+ }
+
static bool isValid(const sp<Surface>& surface) {
return surface != nullptr;
}
diff --git a/libs/hostgraphics/include/ui/Fence.h b/libs/hostgraphics/include/ui/Fence.h
index 187c311..3364b8ae 100644
--- a/libs/hostgraphics/include/ui/Fence.h
+++ b/libs/hostgraphics/include/ui/Fence.h
@@ -60,6 +60,10 @@
return 0;
}
+ int get() const {
+ return 0;
+ }
+
inline Status getStatus() {
// The sync_wait call underlying wait() has been measured to be
// significantly faster than the sync_fence_info call underlying
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index bb2a53b..38ac8ab 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -233,6 +233,14 @@
}
filegroup {
+ name: "framework-graphics-ravenwood-policies",
+ srcs: [
+ "framework-graphics-ravenwood-policies.txt",
+ ],
+ visibility: ["//frameworks/base/ravenwood"],
+}
+
+filegroup {
name: "framework-graphics-srcs",
srcs: [
"apex/java/**/*.java",
@@ -461,6 +469,10 @@
},
linux: {
srcs: ["platform/linux/utils/SharedLib.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ ],
},
darwin: {
srcs: ["platform/darwin/utils/SharedLib.cpp"],
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 36feabd..0e52f4e 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -52,8 +52,8 @@
static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 24,
"Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");
-void FrameInfo::importUiThreadInfo(int64_t* info) {
- memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
+void FrameInfo::importUiThreadInfo(const int64_t* info) {
+ memcpy(mFrameInfo.data(), info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
mSkippedFrameReason.reset();
}
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 61c30b8..b1f479f 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -84,6 +84,8 @@
};
};
+using FrameInfoBuffer = std::array<int64_t, static_cast<size_t>(FrameInfoIndex::NumIndexes)>;
+
class UiFrameInfoBuilder {
public:
static constexpr int64_t INVALID_VSYNC_ID = -1;
@@ -132,7 +134,7 @@
class FrameInfo {
public:
- void importUiThreadInfo(int64_t* info);
+ void importUiThreadInfo(const int64_t* info);
void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(SYSTEM_TIME_MONOTONIC); }
@@ -152,7 +154,7 @@
set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
}
- const int64_t* data() const { return mFrameInfo; }
+ const FrameInfoBuffer& data() const { return mFrameInfo; }
inline int64_t operator[](FrameInfoIndex index) const { return get(index); }
@@ -201,7 +203,7 @@
}
private:
- int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
+ FrameInfoBuffer mFrameInfo;
std::optional<SkippedFrameReason> mSkippedFrameReason;
};
diff --git a/libs/hwui/FrameMetricsObserver.h b/libs/hwui/FrameMetricsObserver.h
index 3ea4951..d267740 100644
--- a/libs/hwui/FrameMetricsObserver.h
+++ b/libs/hwui/FrameMetricsObserver.h
@@ -18,12 +18,14 @@
#include <utils/RefBase.h>
+#include "FrameInfo.h"
+
namespace android {
namespace uirenderer {
class FrameMetricsObserver : public VirtualLightRefBase {
public:
- virtual void notify(const int64_t* buffer) = 0;
+ virtual void notify(const FrameInfoBuffer& buffer) = 0;
bool waitForPresentTime() const { return mWaitForPresentTime; };
void reportMetricsFrom(uint64_t frameNumber, int32_t surfaceControlId) {
diff --git a/libs/hwui/FrameMetricsReporter.cpp b/libs/hwui/FrameMetricsReporter.cpp
index ee32ea1..4ad9c9a 100644
--- a/libs/hwui/FrameMetricsReporter.cpp
+++ b/libs/hwui/FrameMetricsReporter.cpp
@@ -16,10 +16,12 @@
#include "FrameMetricsReporter.h"
+#include "FrameInfo.h"
+
namespace android {
namespace uirenderer {
-void FrameMetricsReporter::reportFrameMetrics(const int64_t* stats, bool hasPresentTime,
+void FrameMetricsReporter::reportFrameMetrics(const FrameInfoBuffer& stats, bool hasPresentTime,
uint64_t frameNumber, int32_t surfaceControlId) {
FatVector<sp<FrameMetricsObserver>, 10> copy;
{
diff --git a/libs/hwui/FrameMetricsReporter.h b/libs/hwui/FrameMetricsReporter.h
index 7e51df7c..71b3f52 100644
--- a/libs/hwui/FrameMetricsReporter.h
+++ b/libs/hwui/FrameMetricsReporter.h
@@ -35,12 +35,12 @@
public:
FrameMetricsReporter() {}
- void addObserver(FrameMetricsObserver* observer) {
+ void addObserver(sp<FrameMetricsObserver>&& observer) {
std::lock_guard lock(mObserversLock);
- mObservers.push_back(observer);
+ mObservers.push_back(std::move(observer));
}
- bool removeObserver(FrameMetricsObserver* observer) {
+ bool removeObserver(const sp<FrameMetricsObserver>& observer) {
std::lock_guard lock(mObserversLock);
for (size_t i = 0; i < mObservers.size(); i++) {
if (mObservers[i].get() == observer) {
@@ -69,7 +69,7 @@
* stats of frames that are from "old" surfaces (i.e. with surfaceControlIds older than the one
* the observer was attached on) nor those that are from "old" frame numbers.
*/
- void reportFrameMetrics(const int64_t* stats, bool hasPresentTime, uint64_t frameNumber,
+ void reportFrameMetrics(const FrameInfoBuffer& stats, bool hasPresentTime, uint64_t frameNumber,
int32_t surfaceControlId);
private:
diff --git a/libs/hwui/framework-graphics-ravenwood-policies.txt b/libs/hwui/framework-graphics-ravenwood-policies.txt
new file mode 100644
index 0000000..7296225
--- /dev/null
+++ b/libs/hwui/framework-graphics-ravenwood-policies.txt
@@ -0,0 +1 @@
+class android.graphics.ColorMatrix keepclass
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index cfde0b2..27d4ac7 100644
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -613,7 +613,7 @@
///////////////////////////////////////////////////////////////////////////////
// TODO: Move somewhere else
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
#define ON_ERROR_RETURN(X) \
if ((error = (X)) != STATUS_OK) return error
@@ -717,7 +717,7 @@
#undef ON_ERROR_RETURN
-#endif // __ANDROID__ // Layoutlib does not support parcel
+#endif // __linux__ // Only Linux support parcel
// This is the maximum possible size because the SkColorSpace must be
// representable (and therefore serializable) using a matrix and numerical
@@ -733,7 +733,7 @@
}
static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
if (parcel == NULL) {
jniThrowNullPointerException(env, "parcel cannot be null");
return NULL;
@@ -836,14 +836,14 @@
return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable), nullptr,
nullptr, density, sourceId);
#else
- jniThrowRuntimeException(env, "Cannot use parcels outside of Android");
+ jniThrowRuntimeException(env, "Cannot use parcels outside of Linux");
return NULL;
#endif
}
static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, jint density,
jobject parcel) {
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
if (parcel == NULL) {
ALOGD("------- writeToParcel null parcel\n");
return JNI_FALSE;
@@ -901,7 +901,7 @@
}
return JNI_TRUE;
#else
- doThrowRE(env, "Cannot use parcels outside of Android");
+ doThrowRE(env, "Cannot use parcels outside of Linux");
return JNI_FALSE;
#endif
}
diff --git a/libs/hwui/jni/Region.cpp b/libs/hwui/jni/Region.cpp
index 1e064b8..76986eeb 100644
--- a/libs/hwui/jni/Region.cpp
+++ b/libs/hwui/jni/Region.cpp
@@ -18,7 +18,7 @@
#include "SkPath.h"
#include "GraphicsJNI.h"
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
#include <android/binder_parcel.h>
#include <android/binder_parcel_jni.h>
#include <android/binder_parcel_utils.h>
@@ -202,7 +202,7 @@
static jlong Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel)
{
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
if (parcel == nullptr) {
return 0;
}
@@ -230,7 +230,7 @@
static jboolean Region_writeToParcel(JNIEnv* env, jobject clazz, jlong regionHandle, jobject parcel)
{
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
if (parcel == nullptr) {
return JNI_FALSE;
diff --git a/libs/hwui/jni/ScopedParcel.cpp b/libs/hwui/jni/ScopedParcel.cpp
index 95e4e01..52cd988 100644
--- a/libs/hwui/jni/ScopedParcel.cpp
+++ b/libs/hwui/jni/ScopedParcel.cpp
@@ -15,7 +15,7 @@
*/
#include "ScopedParcel.h"
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
using namespace android;
@@ -92,4 +92,4 @@
AParcel_writeByteArray(mParcel, nullptr, -1);
}
}
-#endif // __ANDROID__ // Layoutlib does not support parcel
+#endif // __linux__ // Only Linux support parcel
diff --git a/libs/hwui/jni/ScopedParcel.h b/libs/hwui/jni/ScopedParcel.h
index f2f138f..f2b793a 100644
--- a/libs/hwui/jni/ScopedParcel.h
+++ b/libs/hwui/jni/ScopedParcel.h
@@ -15,7 +15,7 @@
*/
#include "SkData.h"
-#ifdef __ANDROID__ // Layoutlib does not support parcel
+#ifdef __linux__ // Only Linux support parcel
#include <android-base/unique_fd.h>
#include <android/binder_parcel.h>
#include <android/binder_parcel_jni.h>
@@ -64,4 +64,4 @@
ASHMEM,
};
-#endif // __ANDROID__ // Layoutlib does not support parcel
\ No newline at end of file
+#endif // __linux__ // Only Linux support parcel
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 99e7740..cfec24b 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -915,20 +915,22 @@
static void android_view_ThreadedRenderer_addObserver(JNIEnv* env, jclass clazz,
jlong proxyPtr, jlong observerPtr) {
- HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
+ FrameMetricsObserver* rawObserver = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
+ sp<FrameMetricsObserver> observer = sp<FrameMetricsObserver>::fromExisting(rawObserver);
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- renderProxy->addFrameMetricsObserver(observer);
+ renderProxy->addFrameMetricsObserver(std::move(observer));
}
static void android_view_ThreadedRenderer_removeObserver(JNIEnv* env, jclass clazz,
jlong proxyPtr, jlong observerPtr) {
- HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
+ FrameMetricsObserver* rawObserver = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
+ sp<FrameMetricsObserver> observer = sp<FrameMetricsObserver>::fromExisting(rawObserver);
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- renderProxy->removeFrameMetricsObserver(observer);
+ renderProxy->removeFrameMetricsObserver(std::move(observer));
}
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
index 6cae5ff..4f383ee 100644
--- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
@@ -16,11 +16,12 @@
#include "android_graphics_HardwareRendererObserver.h"
+#include <array>
+
+#include "FrameInfo.h"
#include "graphics_jni_helpers.h"
#include "nativehelper/jni_macros.h"
-#include <array>
-
namespace android {
struct {
@@ -65,13 +66,13 @@
return false;
}
-void HardwareRendererObserver::notify(const int64_t* stats) {
+void HardwareRendererObserver::notify(const uirenderer::FrameInfoBuffer& stats) {
if (!mKeepListening) return;
FrameMetricsNotification& elem = mRingBuffer[mNextFree];
if (!elem.hasData.load()) {
- memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
+ memcpy(elem.buffer, stats.data(), kBufferSize * sizeof(stats[0]));
elem.dropCount = mDroppedReports;
mDroppedReports = 0;
diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
index 5ee3e16..cf20ee1 100644
--- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
+++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
@@ -43,7 +43,7 @@
*/
bool getNextBuffer(JNIEnv* env, jlongArray metrics, int* dropCount);
- void notify(const int64_t* stats) override;
+ void notify(const uirenderer::FrameInfoBuffer& stats) override;
private:
static constexpr int kBufferSize = static_cast<int>(uirenderer::FrameInfoIndex::NumIndexes);
diff --git a/libs/hwui/jni/graphics_jni_helpers.h b/libs/hwui/jni/graphics_jni_helpers.h
index 91db134..ff26ec1 100644
--- a/libs/hwui/jni/graphics_jni_helpers.h
+++ b/libs/hwui/jni/graphics_jni_helpers.h
@@ -21,6 +21,7 @@
#include <nativehelper/JNIPlatformHelp.h>
#include <nativehelper/scoped_local_ref.h>
#include <nativehelper/scoped_utf_chars.h>
+#include <nativehelper/scoped_primitive_array.h>
#include <string>
// Host targets (layoutlib) do not differentiate between regular and critical native methods,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e3e393c..b248c4b 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -859,7 +859,7 @@
} // release lock
}
-void CanvasContext::addFrameMetricsObserver(FrameMetricsObserver* observer) {
+void CanvasContext::addFrameMetricsObserver(sp<FrameMetricsObserver>&& observer) {
std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter.get() == nullptr) {
mFrameMetricsReporter.reset(new FrameMetricsReporter());
@@ -870,10 +870,10 @@
// their frame metrics.
uint64_t nextFrameNumber = getFrameNumber();
observer->reportMetricsFrom(nextFrameNumber, mSurfaceControlGenerationId);
- mFrameMetricsReporter->addObserver(observer);
+ mFrameMetricsReporter->addObserver(std::move(observer));
}
-void CanvasContext::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
+void CanvasContext::removeFrameMetricsObserver(const sp<FrameMetricsObserver>& observer) {
std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter.get() != nullptr) {
mFrameMetricsReporter->removeObserver(observer);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index cb37538..f119102 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -176,8 +176,8 @@
void setContentDrawBounds(const Rect& bounds) { mContentDrawBounds = bounds; }
- void addFrameMetricsObserver(FrameMetricsObserver* observer);
- void removeFrameMetricsObserver(FrameMetricsObserver* observer);
+ void addFrameMetricsObserver(sp<FrameMetricsObserver>&& observer);
+ void removeFrameMetricsObserver(const sp<FrameMetricsObserver>& observer);
// Used to queue up work that needs to be completed before this frame completes
void enqueueFrameWork(std::function<void()>&& func);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 715153b..ebfd8fde9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -206,7 +206,7 @@
}
bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
- ATRACE_NAME("TextureView#getBitmap");
+ ATRACE_NAME("RenderProxy#copyLayerInto readback");
auto& thread = RenderThread::getInstance();
return thread.queue().runSync([&]() -> bool {
return thread.readback().copyLayerInto(layer, &bitmap) == CopyResult::Success;
@@ -420,15 +420,15 @@
mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
}
-void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
- mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
- mContext->addFrameMetricsObserver(observer.get());
+void RenderProxy::addFrameMetricsObserver(sp<FrameMetricsObserver>&& observer) {
+ mRenderThread.queue().post([this, observer = std::move(observer)]() mutable {
+ mContext->addFrameMetricsObserver(std::move(observer));
});
}
-void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
- mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
- mContext->removeFrameMetricsObserver(observer.get());
+void RenderProxy::removeFrameMetricsObserver(sp<FrameMetricsObserver>&& observer) {
+ mRenderThread.queue().post([this, observer = std::move(observer)]() {
+ mContext->removeFrameMetricsObserver(observer);
});
}
@@ -473,7 +473,7 @@
}
int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
- ATRACE_NAME("HardwareBitmap readback");
+ ATRACE_NAME("RenderProxy#copyHWBitmapInto readback");
RenderThread& thread = RenderThread::getInstance();
if (RenderThread::isCurrent()) {
// TODO: fix everything that hits this. We should never be triggering a readback ourselves.
@@ -485,6 +485,7 @@
}
int RenderProxy::copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap) {
+ ATRACE_NAME("RenderProxy#copyImageInto readback");
RenderThread& thread = RenderThread::getInstance();
if (RenderThread::isCurrent()) {
// TODO: fix everything that hits this. We should never be triggering a readback ourselves.
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index f2d8e94..ad6d54b 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -141,8 +141,8 @@
void setFrameCommitCallback(std::function<void(bool)>&& callback);
void setFrameCompleteCallback(std::function<void()>&& callback);
- void addFrameMetricsObserver(FrameMetricsObserver* observer);
- void removeFrameMetricsObserver(FrameMetricsObserver* observer);
+ void addFrameMetricsObserver(sp<FrameMetricsObserver>&& observer);
+ void removeFrameMetricsObserver(sp<FrameMetricsObserver>&& observer);
void setForceDark(ForceDarkType type);
static void copySurfaceInto(ANativeWindow* window, std::shared_ptr<CopyRequest>&& request);
diff --git a/libs/hwui/tests/unit/FrameMetricsReporterTests.cpp b/libs/hwui/tests/unit/FrameMetricsReporterTests.cpp
index 571a267..c7935ac 100644
--- a/libs/hwui/tests/unit/FrameMetricsReporterTests.cpp
+++ b/libs/hwui/tests/unit/FrameMetricsReporterTests.cpp
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
#include <FrameMetricsObserver.h>
#include <FrameMetricsReporter.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <utils/TimeUtils.h>
+#include "FrameInfo.h"
+
using namespace android;
using namespace android::uirenderer;
@@ -31,7 +32,7 @@
explicit TestFrameMetricsObserver(bool waitForPresentTime)
: FrameMetricsObserver(waitForPresentTime){};
- MOCK_METHOD(void, notify, (const int64_t* buffer), (override));
+ MOCK_METHOD(void, notify, (const FrameInfoBuffer& buffer), (override));
};
// To make sure it is clear that something went wrong if no from frame is set (to make it easier
@@ -44,7 +45,7 @@
reporter->addObserver(observer.get());
- const int64_t* stats;
+ FrameInfoBuffer stats;
bool hasPresentTime = false;
uint64_t frameNumber = 1;
int32_t surfaceControlId = 0;
@@ -64,7 +65,7 @@
}
TEST(FrameMetricsReporter, respectsWaitForPresentTimeUnset) {
- const int64_t* stats;
+ FrameInfoBuffer stats;
bool hasPresentTime = false;
uint64_t frameNumber = 3;
int32_t surfaceControlId = 0;
@@ -85,7 +86,7 @@
}
TEST(FrameMetricsReporter, respectsWaitForPresentTimeSet) {
- const int64_t* stats;
+ FrameInfoBuffer stats;
bool hasPresentTime = true;
uint64_t frameNumber = 3;
int32_t surfaceControlId = 0;
@@ -106,7 +107,7 @@
}
TEST(FrameMetricsReporter, reportsAllFramesAfterSpecifiedFromFrame) {
- const int64_t* stats;
+ FrameInfoBuffer stats;
bool hasPresentTime = false;
std::vector<uint64_t> frameNumbers{0, 1, 10};
@@ -138,7 +139,7 @@
}
TEST(FrameMetricsReporter, doesNotReportsFramesBeforeSpecifiedFromFrame) {
- const int64_t* stats;
+ FrameInfoBuffer stats;
bool hasPresentTime = false;
std::vector<uint64_t> frameNumbers{1, 10};
@@ -165,7 +166,7 @@
}
TEST(FrameMetricsReporter, canRemoveObservers) {
- const int64_t* stats;
+ FrameInfoBuffer stats;
bool hasPresentTime = false;
uint64_t frameNumber = 3;
int32_t surfaceControlId = 0;
@@ -187,7 +188,7 @@
}
TEST(FrameMetricsReporter, canSupportMultipleObservers) {
- const int64_t* stats;
+ FrameInfoBuffer stats;
bool hasPresentTime = false;
uint64_t frameNumber = 3;
int32_t surfaceControlId = 0;
diff --git a/libs/hwui/tests/unit/JankTrackerTests.cpp b/libs/hwui/tests/unit/JankTrackerTests.cpp
index c289d67..08718c9 100644
--- a/libs/hwui/tests/unit/JankTrackerTests.cpp
+++ b/libs/hwui/tests/unit/JankTrackerTests.cpp
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
-#include <gmock/gmock.h>
-
#include <JankTracker.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <utils/TimeUtils.h>
+#include "FrameInfo.h"
+
using namespace android;
using namespace android::uirenderer;
class TestFrameMetricsObserver : public FrameMetricsObserver {
public:
- void notify(const int64_t*) {}
+ void notify(const FrameInfoBuffer&) override {}
};
TEST(JankTracker, noJank) {
diff --git a/media/java/android/media/AudioDeviceVolumeManager.java b/media/java/android/media/AudioDeviceVolumeManager.java
index 892a861..56d3df3 100644
--- a/media/java/android/media/AudioDeviceVolumeManager.java
+++ b/media/java/android/media/AudioDeviceVolumeManager.java
@@ -16,6 +16,9 @@
package android.media;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.media.audio.Flags.FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT;
+
import static com.android.media.flags.Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL;
import android.Manifest;
@@ -91,6 +94,8 @@
* @see #setDeviceAbsoluteVolumeBehavior(AudioDeviceAttributes, VolumeInfo, boolean, Executor,
* OnAudioDeviceVolumeChangedListener)
*/
+ @SystemApi(client = MODULE_LIBRARIES)
+ @FlaggedApi(FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT)
public interface OnAudioDeviceVolumeChangedListener {
/**
* Called the device for the given audio device has changed.
@@ -203,6 +208,30 @@
* volume updates to apply on that device
* @param device the audio device set to absolute volume mode
* @param volume the type of volume this device responds to
+ * @param executor the Executor used for receiving volume updates through the listener
+ * @param vclistener the callback for volume updates
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+ android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ android.Manifest.permission.BLUETOOTH_STACK})
+ @FlaggedApi(FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT)
+ public void setDeviceAbsoluteVolumeBehavior(
+ @NonNull AudioDeviceAttributes device,
+ @NonNull VolumeInfo volume,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnAudioDeviceVolumeChangedListener vclistener) {
+ setDeviceAbsoluteVolumeBehavior(device, volume, /*handlesVolumeAdjustment=*/false, executor,
+ vclistener);
+ }
+
+ /**
+ * @hide
+ * Configures a device to use absolute volume model, and registers a listener for receiving
+ * volume updates to apply on that device
+ * @param device the audio device set to absolute volume mode
+ * @param volume the type of volume this device responds to
* @param handlesVolumeAdjustment whether the controller handles volume adjustments separately
* from volume changes. If true, adjustments from {@link AudioManager#adjustStreamVolume}
* will be sent via {@link OnAudioDeviceVolumeChangedListener#onAudioDeviceVolumeAdjusted}.
@@ -210,7 +239,7 @@
* @param vclistener the callback for volume updates
*/
@RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED })
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED})
public void setDeviceAbsoluteVolumeBehavior(
@NonNull AudioDeviceAttributes device,
@NonNull VolumeInfo volume,
@@ -229,6 +258,30 @@
* registers a listener for receiving volume updates to apply on that device
* @param device the audio device set to absolute multi-volume mode
* @param volumes the list of volumes the given device responds to
+ * @param executor the Executor used for receiving volume updates through the listener
+ * @param vclistener the callback for volume updates
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+ android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ android.Manifest.permission.BLUETOOTH_STACK})
+ @FlaggedApi(FLAG_UNIFY_ABSOLUTE_VOLUME_MANAGEMENT)
+ public void setDeviceAbsoluteMultiVolumeBehavior(
+ @NonNull AudioDeviceAttributes device,
+ @NonNull List<VolumeInfo> volumes,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnAudioDeviceVolumeChangedListener vclistener) {
+ setDeviceAbsoluteMultiVolumeBehavior(device, volumes, /*handlesVolumeAdjustment=*/false,
+ executor, vclistener);
+ }
+
+ /**
+ * @hide
+ * Configures a device to use absolute volume model applied to different volume types, and
+ * registers a listener for receiving volume updates to apply on that device
+ * @param device the audio device set to absolute multi-volume mode
+ * @param volumes the list of volumes the given device responds to
* @param handlesVolumeAdjustment whether the controller handles volume adjustments separately
* from volume changes. If true, adjustments from {@link AudioManager#adjustStreamVolume}
* will be sent via {@link OnAudioDeviceVolumeChangedListener#onAudioDeviceVolumeAdjusted}.
@@ -236,7 +289,7 @@
* @param vclistener the callback for volume updates
*/
@RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED })
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED})
public void setDeviceAbsoluteMultiVolumeBehavior(
@NonNull AudioDeviceAttributes device,
@NonNull List<VolumeInfo> volumes,
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 23f87ab..b8259ef 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -2037,9 +2037,10 @@
// Ignore exceptions in order to keep the compatibility with the old versions of
// ExifInterface.
mIsSupportedFile = false;
- Log.w(TAG, "Invalid image: ExifInterface got an unsupported image format file"
- + "(ExifInterface supports JPEG and some RAW image formats only) "
- + "or a corrupted JPEG file to ExifInterface.", e);
+ Log.d(
+ TAG,
+ "Invalid image: ExifInterface got an unsupported or corrupted image file",
+ e);
} finally {
addDefaultValuesForCompatibility();
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 88981ea..1cb540b 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -481,9 +481,9 @@
/**
* Indicates that a route supports routing playback to remote routes through control commands.
*
- * <p>This type of routing does not affect affect this system's audio or video, but instead
- * relies on the device that corresponds to this route to fetch and play the media. It also
- * requires the media app to take care of initializing and controlling playback.
+ * <p>This type of routing does not affect this system's audio or video, but instead relies on
+ * the device that corresponds to this route to fetch and play the media. It also requires the
+ * media app to take care of initializing and controlling playback.
*/
@FlaggedApi(FLAG_ENABLE_MIRRORING_IN_MEDIA_ROUTER_2)
public static final int FLAG_ROUTING_TYPE_REMOTE = 1 << 2;
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index e94fb7d..4ae8daa 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -348,18 +348,21 @@
* <p>This method must only be called as the result of a prior call to {@link
* #onCreateSystemRoutingSession}.
*
+ * <p>This method returns a {@link MediaStreams} instance that holds the media streams to route
+ * as part of the newly created routing session. May be null if system media capture failed, in
+ * which case you can ignore the return value, as you will receive a call to {@link
+ * #onReleaseSession} where you can clean up this session. {@link AudioRecord#startRecording()}
+ * must be called immediately on {@link MediaStreams#getAudioRecord()} after calling this
+ * method, in order to start streaming audio to the receiver.
+ *
* @param requestId the ID of the {@link #onCreateSystemRoutingSession} request which this call
* is in response to.
* @param sessionInfo a {@link RoutingSessionInfo} that describes the newly created routing
* session.
* @param formats the {@link MediaStreamsFormats} that describes the format for the {@link
* MediaStreams} to return.
- * @return a {@link MediaStreams} instance that holds the media streams to route as part of the
- * newly created routing session. May be null if system media capture failed, in which case
- * you can ignore the return value, as you will receive a call to {@link #onReleaseSession}
- * where you can clean up this session. {@link AudioRecord#startRecording()} must be called
- * immediately on {@link MediaStreams#getAudioRecord()} after calling this method, in order
- * to start streaming audio to the receiver.
+ * @return The {@link MediaStreams} to route as part of the new session, or null if system media
+ * capture failed and the result can be ignored.
* @throws IllegalStateException If the provided {@code requestId} doesn't correspond to a
* previous call to {@link #onCreateSystemRoutingSession}.
*/
@@ -1191,8 +1194,8 @@
*
* <p>The default value is an empty {@link Bundle}.
*
- * <p>Note that this bundle is not copied, so avoiding mutating the given {@link Bundle}
- * after passing it to this method.
+ * <p>Do not mutate the given {@link Bundle} after passing it to this method. You can
+ * use {@link Bundle#deepCopy()} to keep a mutable copy.
*/
@NonNull
public Builder setExtras(@NonNull Bundle extras) {
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 4fe0b80..2759724 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -715,47 +715,45 @@
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
- int fd = -1;
+ base::unique_fd fd;
std::vector<int32_t> offsets;
std::vector<int32_t> dimensions;
std::vector<int32_t> sizes;
std::vector<int32_t> samplingKeys;
if (luts) {
- std::vector<float> buffer(luts->totalBufferSize);
int32_t count = luts->offsets.size();
offsets = luts->offsets;
dimensions.reserve(count);
sizes.reserve(count);
samplingKeys.reserve(count);
- for (int32_t i = 0; i < count; i++) {
- dimensions.emplace_back(luts->entries[i]->properties.dimension);
- sizes.emplace_back(luts->entries[i]->properties.size);
- samplingKeys.emplace_back(luts->entries[i]->properties.samplingKey);
- std::copy(luts->entries[i]->buffer.data.begin(), luts->entries[i]->buffer.data.end(),
- buffer.begin() + offsets[i]);
- }
// mmap
- fd = ashmem_create_region("lut_shared_mem", luts->totalBufferSize * sizeof(float));
+ fd.reset(ashmem_create_region("lut_shared_mem", luts->totalBufferSize * sizeof(float)));
if (fd < 0) {
LOG_ALWAYS_FATAL("setLuts, ashmem_create_region() failed");
return;
}
- void* ptr = mmap(nullptr, luts->totalBufferSize * sizeof(float), PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0);
+ float* ptr = (float*)mmap(nullptr, luts->totalBufferSize * sizeof(float),
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
LOG_ALWAYS_FATAL("setLuts, Failed to map the shared memory");
return;
}
- memcpy(ptr, buffer.data(), luts->totalBufferSize * sizeof(float));
+ for (int32_t i = 0; i < count; i++) {
+ dimensions.emplace_back(luts->entries[i]->properties.dimension);
+ sizes.emplace_back(luts->entries[i]->properties.size);
+ samplingKeys.emplace_back(luts->entries[i]->properties.samplingKey);
+ std::copy(luts->entries[i]->buffer.data.begin(), luts->entries[i]->buffer.data.end(),
+ ptr + offsets[i]);
+ }
+
munmap(ptr, luts->totalBufferSize * sizeof(float));
}
- transaction->setLuts(surfaceControl, base::unique_fd(fd), offsets, dimensions, sizes,
- samplingKeys);
+ transaction->setLuts(surfaceControl, std::move(fd), offsets, dimensions, sizes, samplingKeys);
}
void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction,
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index d002c9c..c5ed386 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -27,7 +27,7 @@
<string name="chooser_title_non_profile" msgid="6035023914517087400">"Odaberite uređaj kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
<string name="chooser_title" msgid="2235819929238267637">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> koji želite postaviti"</string>
<string name="single_device_title" msgid="4199861437545438606">"Traži se <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
- <string name="summary_watch" msgid="8134580124808507407">"Aplikacija će moći sinkronizirati podatke kao što je ime pozivatelja i pristupiti tim dopuštenjima na vašem uređaju <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+ <string name="summary_watch" msgid="8134580124808507407">"Aplikacija će moći sinkronizirati podatke kao što je ime pozivatelja i pristupiti tim dopuštenjima na vašem <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
<string name="confirmation_title_glasses" msgid="8288346850537727333">"Dopustiti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja uređajem <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
<string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string>
<string name="summary_glasses" msgid="5469208629679579157">"Aplikacija će moći pristupati ovim dopuštenjima na vašem uređaju <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index 77e2396..3f6eacf 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4470785958457506021">"កម្មវិធីគ្រប់គ្រងឧបករណ៍ដៃគូ"</string>
<string name="confirmation_title" msgid="2244241995958340998">"អនុញ្ញាតឱ្យកម្មវិធី <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលប្រើ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ឬ?"</string>
- <string name="message_discovery_soft_timeout" msgid="473346859407859161">"សូមប្រាកដថា<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>នេះបានបើក<xliff:g id="DISCOVERY_METHOD">%2$s</xliff:g> និងទុក<xliff:g id="PROFILE_NAME">%3$s</xliff:g>នៅជិតអ្នក។"</string>
+ <string name="message_discovery_soft_timeout" msgid="473346859407859161">"សូមប្រាកដថា<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>នេះបានបើក<xliff:g id="DISCOVERY_METHOD">%2$s</xliff:g> និងទុក<xliff:g id="PROFILE_NAME">%3$s</xliff:g>របស់អ្នកនៅជិតអ្នក។"</string>
<string name="message_discovery_hard_timeout" msgid="677514663495711424">"រកមិនឃើញឧបករណ៍ទេ។ សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ។"</string>
<string name="discovery_bluetooth" msgid="5693557668470016164">"ប៊្លូធូស"</string>
<string name="discovery_wifi" msgid="1551782459721758773">"Wi-Fi"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index ee4db7d..0b4274e 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -18,12 +18,12 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4470785958457506021">"부속 기기 관리자"</string>
<string name="confirmation_title" msgid="2244241995958340998">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 앱에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 액세스하도록 허용하시겠습니까?"</string>
- <string name="message_discovery_soft_timeout" msgid="473346859407859161">"이 <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>에서 <xliff:g id="DISCOVERY_METHOD">%2$s</xliff:g> 기능을 사용 설정하고 <xliff:g id="PROFILE_NAME">%3$s</xliff:g> 기기를 근처에 두세요."</string>
+ <string name="message_discovery_soft_timeout" msgid="473346859407859161">"이 <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>에서 <xliff:g id="DISCOVERY_METHOD">%2$s</xliff:g> 기능을 사용 설정하고 <xliff:g id="PROFILE_NAME">%3$s</xliff:g>을(를) 근처에 두세요."</string>
<string name="message_discovery_hard_timeout" msgid="677514663495711424">"기기를 찾을 수 없습니다. 나중에 다시 시도해 주세요."</string>
<string name="discovery_bluetooth" msgid="5693557668470016164">"블루투스"</string>
<string name="discovery_wifi" msgid="1551782459721758773">"Wi-Fi"</string>
<string name="discovery_mixed" msgid="7071466134150760127">"블루투스 및 Wi-Fi"</string>
- <string name="profile_name_watch" msgid="576290739483672360">"시계"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"워치"</string>
<string name="chooser_title_non_profile" msgid="6035023914517087400">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 관리할 기기 선택"</string>
<string name="chooser_title" msgid="2235819929238267637">"설정할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g> 선택"</string>
<string name="single_device_title" msgid="4199861437545438606">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> 찾는 중"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 8ba76bc..86c0e46 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -23,7 +23,7 @@
<string name="discovery_bluetooth" msgid="5693557668470016164">"Bluetooth"</string>
<string name="discovery_wifi" msgid="1551782459721758773">"Kablosuz"</string>
<string name="discovery_mixed" msgid="7071466134150760127">"Bluetooth ve Kablosuz"</string>
- <string name="profile_name_watch" msgid="576290739483672360">"saat"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"Saat"</string>
<string name="chooser_title_non_profile" msgid="6035023914517087400">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tarafından yönetilecek bir cihaz seçin"</string>
<string name="chooser_title" msgid="2235819929238267637">"Ayarlamak için bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
<string name="single_device_title" msgid="4199861437545438606">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> aranıyor"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index f517742..8c50d81 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -23,9 +23,9 @@
<string name="discovery_bluetooth" msgid="5693557668470016164">"بلوٹوتھ"</string>
<string name="discovery_wifi" msgid="1551782459721758773">"Wi-Fi"</string>
<string name="discovery_mixed" msgid="7071466134150760127">"بلوٹوتھ اور Wi-Fi"</string>
- <string name="profile_name_watch" msgid="576290739483672360">"دیکھیں"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"گھڑی"</string>
<string name="chooser_title_non_profile" msgid="6035023914517087400">"کوئی آلہ منتخب کریں جس کا نظم و نسق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کرے"</string>
- <string name="chooser_title" msgid="2235819929238267637">"سیٹ اپ کرنے کے لیے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کا انتخاب کریں"</string>
+ <string name="chooser_title" msgid="2235819929238267637">"سیٹ اپ کرنے کے لیے ایک <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کا انتخاب کریں"</string>
<string name="single_device_title" msgid="4199861437545438606">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو تلاش کیا جا رہا ہے"</string>
<string name="summary_watch" msgid="8134580124808507407">"اس ایپ کو آپ کے <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> پر کسی کال کرنے والے کے نام جیسی معلومات کی مطابقت پذیری کرنے اور ان اجازتوں تک رسائی کی اجازت ہوگی"</string>
<string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کا نظم کرنے کی اجازت دیں؟"</string>
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 d6e19a6..a75aeaf 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
@@ -104,6 +104,7 @@
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/screens/multiple/MultiCredentialsFlattenScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
index 932b345..96cadab 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
@@ -36,7 +36,7 @@
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.rememberColumnState
+import com.google.android.horologist.compose.layout.ScalingLazyColumnState
import com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults
import androidx.compose.ui.text.style.TextAlign
import androidx.wear.compose.material.MaterialTheme as WearMaterialTheme
@@ -45,6 +45,7 @@
* 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
*/
@@ -52,15 +53,14 @@
@Composable
fun MultiCredentialsFlattenScreen(
credentialSelectorUiState: MultipleEntry,
+ columnState: ScalingLazyColumnState,
flowEngine: FlowEngine,
) {
val selectEntry = flowEngine.getEntrySelector()
Row {
Spacer(Modifier.weight(0.052f)) // 5.2% side margin
ScalingLazyColumn(
- columnState = rememberColumnState(
- ScalingLazyColumnDefaults.belowTimeText(horizontalAlignment = Alignment.Start),
- ),
+ columnState = columnState,
modifier = Modifier.weight(0.896f).fillMaxSize(), // 5.2% side margin
) {
diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp
index bd89263..853d1ad 100644
--- a/packages/CtsShim/build/Android.bp
+++ b/packages/CtsShim/build/Android.bp
@@ -152,34 +152,6 @@
}
//##########################################################
-// Variant: System app upgrade
-
-android_app {
- name: "CtsShimUpgrade",
-
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
- dex_preopt: {
- enabled: false,
- },
-
- manifest: "shim/AndroidManifestUpgrade.xml",
- min_sdk_version: "24",
-}
-
-java_genrule {
- name: "generate_shim_manifest",
- srcs: [
- "shim/AndroidManifest.xml",
- ":CtsShimUpgrade",
- ],
- out: ["AndroidManifest.xml"],
- cmd: "sed -e s/__HASH__/`sha512sum -b $(location :CtsShimUpgrade) | cut -d' ' -f1`/ $(location shim/AndroidManifest.xml) > $(out)",
-}
-
-//##########################################################
// Variant: System app
android_app {
@@ -193,7 +165,7 @@
enabled: false,
},
- manifest: ":generate_shim_manifest",
+ manifest: "shim/AndroidManifest.xml",
apex_available: [
"//apex_available:platform",
"com.android.apex.cts.shim.v1",
diff --git a/packages/CtsShim/build/shim/AndroidManifest.xml b/packages/CtsShim/build/shim/AndroidManifest.xml
index 3b8276b6..1ffe56c 100644
--- a/packages/CtsShim/build/shim/AndroidManifest.xml
+++ b/packages/CtsShim/build/shim/AndroidManifest.xml
@@ -17,15 +17,13 @@
<!-- Manifest for the system CTS shim -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
- package="com.android.cts.ctsshim"
- android:sharedUserId="com.android.cts.ctsshim" >
+ package="com.android.cts.ctsshim" >
- <uses-sdk
- android:minSdkVersion="24"
+ <uses-sdk android:minSdkVersion="24"
android:targetSdkVersion="28" />
<restrict-update
- android:hash="__HASH__" />
+ android:hash="__CAN_NOT_BE_UPDATED__" />
<application
android:hasCode="false"
diff --git a/packages/CtsShim/build/shim/AndroidManifestUpgrade.xml b/packages/CtsShim/build/shim/AndroidManifestUpgrade.xml
deleted file mode 100644
index 7f3644a..0000000
--- a/packages/CtsShim/build/shim/AndroidManifestUpgrade.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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 for the system CTS shim -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- package="com.android.cts.ctsshim" >
-
- <uses-sdk
- android:minSdkVersion="24"
- android:targetSdkVersion="28" />
-
- <application
- android:hasCode="false"
- tools:ignore="AllowBackup,MissingApplicationIcon" />
-</manifest>
-
diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml
index e364576..273cfa0 100644
--- a/packages/InputDevices/res/values-af/strings.xml
+++ b/packages/InputDevices/res/values-af/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serwies (Cyrillies)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegryns (Cyrillies)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Roemeens"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index db5a7d4..8593253 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"ሰርቢያኛ (ሲሪሊክኛ)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"ሞንቴኔግሮኛ (ሲሪሊክኛ)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ሮማኒያኛ"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index 6d917da..67b7b6a 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"الصربية (السيريلية)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"لغة الجبل الأسود (السيريلية)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"الرومانية"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"الإنجليزية (الهند)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml
index c4eaafb..e6540e4 100644
--- a/packages/InputDevices/res/values-as/strings.xml
+++ b/packages/InputDevices/res/values-as/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"ছাৰ্বিয়ান (চিৰিলিক)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"মণ্টেনেগ্ৰিণ (চিৰিলিক)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ৰোমানিয়ান"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-az/strings.xml b/packages/InputDevices/res/values-az/strings.xml
index d71c396..aa93a92 100644
--- a/packages/InputDevices/res/values-az/strings.xml
+++ b/packages/InputDevices/res/values-az/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serb dili (Kiril)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Monteneqro dili (Kiril)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumın dili"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-b+sr+Latn/strings.xml b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
index e670ed4..1d21a06 100644
--- a/packages/InputDevices/res/values-b+sr+Latn/strings.xml
+++ b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"srpski (ćirilica)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"crnogorski (ćirilica)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumunski"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"engleski (Indija)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml
index c8c04d4..b374a61 100644
--- a/packages/InputDevices/res/values-be/strings.xml
+++ b/packages/InputDevices/res/values-be/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Сербская (кірыліца)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Чарнагорская (кірыліца)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Румынская"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Англійская (Індыя)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index 82c3965..ceb7e37 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"сръбски (кирилица)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"черногорски (кирилица)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"румънски"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-bn/strings.xml b/packages/InputDevices/res/values-bn/strings.xml
index de54cdf..369a803 100644
--- a/packages/InputDevices/res/values-bn/strings.xml
+++ b/packages/InputDevices/res/values-bn/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"সার্বিয়ান (সিরিলিক)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"মন্টেনেগ্রিন (সিরিলিক)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"রোমানিয়ান"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-bs/strings.xml b/packages/InputDevices/res/values-bs/strings.xml
index 9b7b331..6b6b23f 100644
--- a/packages/InputDevices/res/values-bs/strings.xml
+++ b/packages/InputDevices/res/values-bs/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"srpski (ćirilica)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"crnogorski (ćirilica)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumunski"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"engleski (Indija)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml
index 874e06b..bbf3946 100644
--- a/packages/InputDevices/res/values-ca/strings.xml
+++ b/packages/InputDevices/res/values-ca/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbi (ciríl·lic)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrí (ciríl·lic)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romanès"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index c7a4896..e88aa97 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"srbština (cyrilice)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"černohorština (cyrilice)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumunština"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"angličtina (Indie)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index 246baba..00a2a620 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbisk (kyrillisk)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrinsk (kyrillisk)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumænsk"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index 21a939a..717c597 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbisch (kyrillisch)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrinisch (kyrillisch)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumänisch"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index eabb90c..02b7f1f 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Σερβικά (Κυριλλικά)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Μαυροβουνιακά (Κυριλλικά)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Ρουμανικά"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml
index 7b72cba..1cdcc55 100644
--- a/packages/InputDevices/res/values-en-rAU/strings.xml
+++ b/packages/InputDevices/res/values-en-rAU/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbian (Cyrillic)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrin (Cyrillic)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romanian"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml
index d78dce2..36e0988 100644
--- a/packages/InputDevices/res/values-en-rCA/strings.xml
+++ b/packages/InputDevices/res/values-en-rCA/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbian (Cyrillic)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrin (Cyrillic)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romanian"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"English (India)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index 7b72cba..1cdcc55 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbian (Cyrillic)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrin (Cyrillic)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romanian"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index 7b72cba..1cdcc55 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbian (Cyrillic)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrin (Cyrillic)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romanian"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index 2a4035a..edd7657 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbio (cirílico)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrino (cirílico)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumano"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index ba1ef20..b522845 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbio (cirílico)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrino (cirílico)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumano"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml
index 99f3626..82670dd 100644
--- a/packages/InputDevices/res/values-et/strings.xml
+++ b/packages/InputDevices/res/values-et/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"serbia (kirillitsa)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"montenegro (kirillitsa)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumeenia"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 9fae4f9..b777b8c 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbiarra (zirilikoa)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegroarra (zirilikoa)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Errumaniera"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index cbc6b65..9ec7a34 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"صربی (سیریلیک)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"مونتهنگرویی (سیریلیک)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"رومانیایی"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index 736d7cb..6825ea9 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"serbia (kyrillinen)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"montenegro (kyrillinen)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"romania"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index 7b99d3b..353d7ad 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbe (cyrillique)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Monténégrin (cyrillique)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Roumain"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Anglais (Inde)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index 8628f8f..fb4d144 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbe (cyrillique)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Monténégrin (cyrillique)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Roumain"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml
index 5e681e6..925adf9 100644
--- a/packages/InputDevices/res/values-gl/strings.xml
+++ b/packages/InputDevices/res/values-gl/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbio (cirílico)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrino (cirílico)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romanés"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml
index a5a522e..60965dc 100644
--- a/packages/InputDevices/res/values-gu/strings.xml
+++ b/packages/InputDevices/res/values-gu/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"સર્બિયન (સિરિલિક)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"મોંટેનેગ્રીન (સિરિલિક)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"રોમાનિયન"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"અંગ્રેજી (ભારત)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index ad9c980..1751979 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"सर्बियन (सिरिलिक)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"मोंटेनेग्रिन (सिरिलिक)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"रोमेनियन"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index b7e8ee4..746eb03 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"srpski (ćirilica)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"crnogorski (ćirilica)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumunjski"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"engleski (Indija)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index 756cc08..c83ba84 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"szerb (cirill betűs)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"montenegrói (cirill betűs)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"román"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml
index eced5cd..718f8d1 100644
--- a/packages/InputDevices/res/values-hy/strings.xml
+++ b/packages/InputDevices/res/values-hy/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"սերբերեն (կյուրեղատառ)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"չեռնոգորերեն (կյուրեղատառ)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Ռումիներեն"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml
index e871d19..ba2e5bd3 100644
--- a/packages/InputDevices/res/values-in/strings.xml
+++ b/packages/InputDevices/res/values-in/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbia (Sirilik)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegro (Sirilik)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumania"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-is/strings.xml b/packages/InputDevices/res/values-is/strings.xml
index ec5d98b..842119d 100644
--- a/packages/InputDevices/res/values-is/strings.xml
+++ b/packages/InputDevices/res/values-is/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbneska (kyrillískt)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Svartfellska (kyrillískt)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rúmenska"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml
index 06ceb7af..f7f76e0 100644
--- a/packages/InputDevices/res/values-it/strings.xml
+++ b/packages/InputDevices/res/values-it/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbo (cirillico)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrino (cirillico)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumeno"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index 85f9656..0df5d20 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"סרבית (אותיות קיריליות)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"מונטנגרית (אותיות קיריליות)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"רומנית"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 4c6de70..41c244c 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"セルビア語(キリル)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"モンテネグロ語(キリル)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ルーマニア語"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"英語(インド)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ka/strings.xml b/packages/InputDevices/res/values-ka/strings.xml
index 7232c1a..0a9ba3f 100644
--- a/packages/InputDevices/res/values-ka/strings.xml
+++ b/packages/InputDevices/res/values-ka/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"სერბული (კირილიცა)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"მონტენეგრული (კირილიცა)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"რუმინული"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"ინგლისური (ინდოეთი)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-kk/strings.xml b/packages/InputDevices/res/values-kk/strings.xml
index 278c868..60ad838 100644
--- a/packages/InputDevices/res/values-kk/strings.xml
+++ b/packages/InputDevices/res/values-kk/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Сербия (кириллица)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Черногория (кириллица)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Румын"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml
index 2eaeaa7..936c925 100644
--- a/packages/InputDevices/res/values-km/strings.xml
+++ b/packages/InputDevices/res/values-km/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"សែប៊ី (ស៊ីរីលីក)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"ម៉ុងតេណេហ្គ្រោ (ស៊ីរីលីក)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"រ៉ូម៉ានី"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml
index 8039039..2453951 100644
--- a/packages/InputDevices/res/values-kn/strings.xml
+++ b/packages/InputDevices/res/values-kn/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"ಸೆರ್ಬಿಯನ್ (ಸಿರಿಲಿಕ್)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"ಮೊಂಟೆನೆಗ್ರಿನ್ (ಸಿರಿಲಿಕ್)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ರೊಮೇನಿಯನ್"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index de1bb3d..07975a4 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"세르비아어(키릴 자모)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"몬테네그로어(키릴)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"루마니아어"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"영어(인도)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ky/strings.xml b/packages/InputDevices/res/values-ky/strings.xml
index 47bf7b7..f6d018e 100644
--- a/packages/InputDevices/res/values-ky/strings.xml
+++ b/packages/InputDevices/res/values-ky/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Сербче (Кирилл)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Черногориялыкча (Кирилл)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Румынча"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-lo/strings.xml b/packages/InputDevices/res/values-lo/strings.xml
index 6a35f23..61f8f71 100644
--- a/packages/InputDevices/res/values-lo/strings.xml
+++ b/packages/InputDevices/res/values-lo/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"ເຊີບຽນ (ຊີຣິວລິກ)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"ມອນເທເນກຣິນ (ຊີຣິວລິກ)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ໂຣມານຽນ"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml
index 4bf9223..fc9941f 100644
--- a/packages/InputDevices/res/values-lt/strings.xml
+++ b/packages/InputDevices/res/values-lt/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbų (kirilica)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Juodkalniečių (kirilica)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumunų"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Anglų k. (Indija)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml
index 90d690ca..cc2c94c 100644
--- a/packages/InputDevices/res/values-lv/strings.xml
+++ b/packages/InputDevices/res/values-lv/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbu (kirilica)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Melnkalniešu (kirilica)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumāņu"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml
index 4c80a80..60981d6 100644
--- a/packages/InputDevices/res/values-mk/strings.xml
+++ b/packages/InputDevices/res/values-mk/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"српски (кирилица)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"црногорски (кирилица)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"романски"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ml/strings.xml b/packages/InputDevices/res/values-ml/strings.xml
index 41ea10f..8064c74 100644
--- a/packages/InputDevices/res/values-ml/strings.xml
+++ b/packages/InputDevices/res/values-ml/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"സെർബിയൻ (സിറിലിക്)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"മോണ്ടിനെഗ്രിൻ (സിറിലിക്)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"റൊമേനിയൻ"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml
index 056e728..547ce49 100644
--- a/packages/InputDevices/res/values-mn/strings.xml
+++ b/packages/InputDevices/res/values-mn/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Серби (кирилл)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Монтенегро (кирилл)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Румын"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index fe032fe..25bdfab 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"सर्बियन (सिरिलिक)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"मॉन्टेनेग्रिन (सिरिलिक)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"रोमानियन"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ms/strings.xml b/packages/InputDevices/res/values-ms/strings.xml
index f9d18a1..b6e36ab 100644
--- a/packages/InputDevices/res/values-ms/strings.xml
+++ b/packages/InputDevices/res/values-ms/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbia (Cyril)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrin (Cyril)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Bahasa Romania"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Bahasa Inggeris (India)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-my/strings.xml b/packages/InputDevices/res/values-my/strings.xml
index 47498e0..4ef5aab 100644
--- a/packages/InputDevices/res/values-my/strings.xml
+++ b/packages/InputDevices/res/values-my/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"ဆားဘီးယား (စီရီလစ်)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"မွန်တီနီဂရင်း (စီရီလစ်)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ရိုမေးနီးယား"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index 954462c..837e246 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbisk (kyrillisk)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrisk (kyrillisk)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumensk"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml
index e2804d4..0ab1ea6 100644
--- a/packages/InputDevices/res/values-ne/strings.xml
+++ b/packages/InputDevices/res/values-ne/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"सर्बियाली (सिरिलिक)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"मोन्टेनिग्रिन (सिरिलिक)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"रोमानियाली"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml
index 67f78ba..5c175fb 100644
--- a/packages/InputDevices/res/values-nl/strings.xml
+++ b/packages/InputDevices/res/values-nl/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Servisch (Cyrillisch)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrijns (Cyrillisch)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Roemeens"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Engels (India)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
index c6e020c..97f9088 100644
--- a/packages/InputDevices/res/values-or/strings.xml
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"ସର୍ବିଆନ (ସିରିଲିକ)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"ମଣ୍ଟେନେଗ୍ରିନ (ସିରିଲିକ)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ରୋମାନିଆନ"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index 29c3b7d..343418e 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"ਸਰਬੀਆਈ (ਸਿਰਿਲਿਕ)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"ਮਾਂਟੇਨੀਗਰਿਨ (ਸਿਰਿਲਿਕ)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ਰੋਮਾਨੀਆਈ"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"ਅੰਗਰੇਜ਼ੀ (ਭਾਰਤ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 8ce00d3..0fd962b 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"serbski (cyrylica)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"czarnogórski (cyrylica)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumuński"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml
index 3b1fc9b..e649b58 100644
--- a/packages/InputDevices/res/values-pt-rBR/strings.xml
+++ b/packages/InputDevices/res/values-pt-rBR/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Sérvio (cirílico)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrino (cirílico)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romeno"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Inglês (Índia)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml
index 163108d..cd0a046 100644
--- a/packages/InputDevices/res/values-pt-rPT/strings.xml
+++ b/packages/InputDevices/res/values-pt-rPT/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Sérvio (cirílico)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrino (cirílico)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romeno"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Inglês (Índia)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index 3b1fc9b..e649b58 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Sérvio (cirílico)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrino (cirílico)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romeno"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Inglês (Índia)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index 78c99ce..169378d 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Sârbă (caractere chirilice)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Muntenegreană (Chirilică)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Română"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index 183b00e..2d5a6b0 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Сербский (кириллица)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Черногорский (кириллица)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Румынский"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"Английский (Индия)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-si/strings.xml b/packages/InputDevices/res/values-si/strings.xml
index 78d1010..ba27136 100644
--- a/packages/InputDevices/res/values-si/strings.xml
+++ b/packages/InputDevices/res/values-si/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"සර්බියානු (සිරිලික්)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"මොන්ටෙනේග්රීන් (සිරිලික්)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"රුමේනියානු"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index c269085..8ae45be 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"srbčina (cyrilika)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"čiernohorčina (cyrilika)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumunčina"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"angličtina (India)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index d2e9fd1..ced6ab1 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"srbščina (cirilica)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"črnogorščina (cirilica)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"romunščina"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"angleščina (Indija)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sq/strings.xml b/packages/InputDevices/res/values-sq/strings.xml
index 066129e..c77de92 100644
--- a/packages/InputDevices/res/values-sq/strings.xml
+++ b/packages/InputDevices/res/values-sq/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbisht (cirilike)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Malazisht (cirilike)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumanisht"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index e4fed03..0c0748d 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"српски (ћирилица)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"црногорски (ћирилица)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"румунски"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"енглески (Индија)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index 4eaf856..5701d01 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"serbiska (kyrilliskt)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"montenegrinska (kyrilliskt)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"rumänska"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"engelska (Indien)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index 30b52b2..d9ac91f8 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Kiserbia (Kisiriliki)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Kimontenegri (Kisiriliki)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Kiromania"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ta/strings.xml b/packages/InputDevices/res/values-ta/strings.xml
index d60084c..fc91d696 100644
--- a/packages/InputDevices/res/values-ta/strings.xml
+++ b/packages/InputDevices/res/values-ta/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"செர்பியன் (சிரிலிக்)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"மாண்டினெக்ரன் (சிரிலிக்)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"ரோமானியன்"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-te/strings.xml b/packages/InputDevices/res/values-te/strings.xml
index 2f40442..f164736 100644
--- a/packages/InputDevices/res/values-te/strings.xml
+++ b/packages/InputDevices/res/values-te/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"సెర్బియన్ (సిరిలిక్)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"మాంటెనెగ్రిన్ (సిరిలిక్)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"రొమేనియన్"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"ఇంగ్లీష్ (భారతదేశం)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index ae10f04..1538fdb 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -57,4 +57,5 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"เซอร์เบีย (ซีริลลิก)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"มอนเตเนโกร (ซีริลลิก)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"โรมาเนีย"</string>
+ <string name="keyboard_layout_english_india" msgid="7962353311188603367">"อังกฤษ (อินเดีย)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml
index dc0d1f5..ea815d5 100644
--- a/packages/InputDevices/res/values-tl/strings.xml
+++ b/packages/InputDevices/res/values-tl/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbian (Cyrillic)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrin (Cyrillic)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Romanian"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index 2e7084d..3a40c84 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Sırpça (Kiril)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Karadağca (Kiril)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumence"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index 01d34e3..0e0d562 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Сербська (кирилиця)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Чорногорська (кирилиця)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Румунська"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ur/strings.xml b/packages/InputDevices/res/values-ur/strings.xml
index 94cd329..44721b8 100644
--- a/packages/InputDevices/res/values-ur/strings.xml
+++ b/packages/InputDevices/res/values-ur/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"سربیائی (سیریلک)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"مونٹے نیگریائی (سیریلک)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"رومانیائی"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml
index e63fc09..776c1c7 100644
--- a/packages/InputDevices/res/values-uz/strings.xml
+++ b/packages/InputDevices/res/values-uz/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serb (kirill)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Chernogor (kirill)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Rumin"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml
index 8384c3e..1fcba42 100644
--- a/packages/InputDevices/res/values-vi/strings.xml
+++ b/packages/InputDevices/res/values-vi/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Tiếng Serbia (Chữ Kirin)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Tiếng Montenegro (Chữ Kirin)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"Tiếng Romania"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index e3a8af3..cb7f6cb 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"塞尔维亚语(西里尔字母)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"黑山语(西里尔字母)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"罗马尼亚语"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml
index 56681b8..c718760 100644
--- a/packages/InputDevices/res/values-zh-rHK/strings.xml
+++ b/packages/InputDevices/res/values-zh-rHK/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"塞爾維亞文 (西里爾字母)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"蒙特內哥羅文 (西里爾字母)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"羅馬尼亞文"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml
index 60c085b..68cf9b0 100644
--- a/packages/InputDevices/res/values-zh-rTW/strings.xml
+++ b/packages/InputDevices/res/values-zh-rTW/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"塞爾維亞文 (西里爾字母)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"蒙特內哥羅文 (西里爾字母)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"羅馬尼亞文"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index 6697333..4ae9e47 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -57,4 +57,6 @@
<string name="keyboard_layout_serbian_cyrillic" msgid="7013541044323542196">"Serbian (Cyrillic)"</string>
<string name="keyboard_layout_montenegrin_cyrillic" msgid="2391253952894077421">"Montenegrin (Cyrillic)"</string>
<string name="keyboard_layout_romanian" msgid="8698989892731726903">"IsiRomanian"</string>
+ <!-- no translation found for keyboard_layout_english_india (7962353311188603367) -->
+ <skip />
</resources>
diff --git a/packages/NeuralNetworks/OWNERS b/packages/NeuralNetworks/OWNERS
index 6b39150..bf3c8fe 100644
--- a/packages/NeuralNetworks/OWNERS
+++ b/packages/NeuralNetworks/OWNERS
@@ -1,5 +1,4 @@
# Bug component: 195575
sandeepbandaru@google.com
-shivanker@google.com
-shiqing@google.com
\ No newline at end of file
+shiqing@google.com
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
index a30c0c3..8b1828c 100644
--- a/packages/PackageInstaller/Android.bp
+++ b/packages/PackageInstaller/Android.bp
@@ -47,19 +47,21 @@
sdk_version: "system_current",
rename_resources_package: false,
static_libs: [
- "androidx.leanback_leanback",
+ "android.content.pm.flags-aconfig-java",
+ "android.multiuser.flags-aconfig-java",
+ "android.os.flags-aconfig-java",
"androidx.annotation_annotation",
"androidx.fragment_fragment",
- "androidx.lifecycle_lifecycle-livedata",
+ "androidx.leanback_leanback",
"androidx.lifecycle_lifecycle-extensions",
- "android.content.pm.flags-aconfig-java",
- "android.os.flags-aconfig-java",
- "android.multiuser.flags-aconfig-java",
+ "androidx.lifecycle_lifecycle-livedata",
+ "kotlin-parcelize-runtime",
],
lint: {
error_checks: ["Recycle"],
},
+ kotlin_plugins: ["kotlin-parcelize-compiler-plugin"],
}
android_app {
@@ -79,19 +81,22 @@
overrides: ["PackageInstaller"],
static_libs: [
- "androidx.leanback_leanback",
- "androidx.fragment_fragment",
- "androidx.lifecycle_lifecycle-livedata",
- "androidx.lifecycle_lifecycle-extensions",
"android.content.pm.flags-aconfig-java",
- "android.os.flags-aconfig-java",
"android.multiuser.flags-aconfig-java",
+ "android.os.flags-aconfig-java",
+ "androidx.annotation_annotation",
+ "androidx.fragment_fragment",
+ "androidx.leanback_leanback",
+ "androidx.lifecycle_lifecycle-extensions",
+ "androidx.lifecycle_lifecycle-livedata",
+ "kotlin-parcelize-runtime",
],
aaptflags: ["--product tablet"],
lint: {
error_checks: ["Recycle"],
},
+ kotlin_plugins: ["kotlin-parcelize-compiler-plugin"],
}
android_app {
@@ -111,18 +116,20 @@
overrides: ["PackageInstaller"],
static_libs: [
- "androidx.leanback_leanback",
+ "android.content.pm.flags-aconfig-java",
+ "android.multiuser.flags-aconfig-java",
+ "android.os.flags-aconfig-java",
"androidx.annotation_annotation",
"androidx.fragment_fragment",
- "androidx.lifecycle_lifecycle-livedata",
+ "androidx.leanback_leanback",
"androidx.lifecycle_lifecycle-extensions",
- "android.content.pm.flags-aconfig-java",
- "android.os.flags-aconfig-java",
- "android.multiuser.flags-aconfig-java",
+ "androidx.lifecycle_lifecycle-livedata",
+ "kotlin-parcelize-runtime",
],
aaptflags: ["--product tv"],
lint: {
error_checks: ["Recycle"],
},
+ kotlin_plugins: ["kotlin-parcelize-compiler-plugin"],
}
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index b99bf1a..dab2401 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -58,7 +58,7 @@
<string name="uninstall_application_title" msgid="4045420072401428123">"ଆପ୍କୁ ଅନଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
<string name="uninstall_update_title" msgid="824411791011583031">"ଅପଡେଟ୍ ଅନଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
<string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ହେଉଛି ନିମ୍ନ ଆପ୍ର ଏକ ଅଂଶ।"</string>
- <string name="uninstall_application_text" msgid="3816830743706143980">"ଆପଣ ଏହି ଆପ୍ ଅନଇନଷ୍ଟଲ୍ କରିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
+ <string name="uninstall_application_text" msgid="3816830743706143980">"ଆପଣ ଏହି ଆପ ଅନଇନଷ୍ଟଲ କରିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
<string name="archive_application_text" msgid="8482325710714386348">"ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ଡାଟା ସେଭ ହୋଇଯିବ"</string>
<string name="archive_application_text_all_users" msgid="3151229641681672580">"ସମସ୍ତ ୟୁଜରଙ୍କ ପାଇଁ ଏହି ଆପକୁ ଆର୍କାଇଭ କରିବେ? ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ଡାଟା ସେଭ ହୋଇଯିବ"</string>
<string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲରେ ଏହି ଆପକୁ ଆର୍କାଇଭ କରିବେ? ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ଡାଟା ସେଭ ହୋଇଯିବ"</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt
index 8de8fbb..a8dad09 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt
@@ -18,8 +18,8 @@
import android.app.Activity
import android.content.Intent
-import android.content.pm.PackageManager
import android.content.pm.PackageInstaller
+import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
sealed class InstallStage(val stageCode: Int) {
@@ -42,7 +42,7 @@
data class InstallUserActionRequired(
val actionReason: Int,
- private val appSnippet: PackageUtil.AppSnippet? = null,
+ val appSnippet: PackageUtil.AppSnippet? = null,
val isAppUpdating: Boolean = false,
/**
* This holds either a package name or the app label of the install source.
@@ -63,7 +63,7 @@
}
}
-data class InstallInstalling(private val appSnippet: PackageUtil.AppSnippet) :
+data class InstallInstalling(val appSnippet: PackageUtil.AppSnippet) :
InstallStage(STAGE_INSTALLING) {
val appIcon: Drawable?
@@ -74,7 +74,7 @@
}
data class InstallSuccess(
- private val appSnippet: PackageUtil.AppSnippet,
+ val appSnippet: PackageUtil.AppSnippet,
val shouldReturnResult: Boolean = false,
/**
*
@@ -95,7 +95,7 @@
}
data class InstallFailed(
- private val appSnippet: PackageUtil.AppSnippet? = null,
+ val appSnippet: PackageUtil.AppSnippet? = null,
val legacyCode: Int,
val statusCode: Int,
val message: String? = null,
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt
index 828a95f..e8477ef 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt
@@ -17,21 +17,32 @@
package com.android.packageinstaller.v2.model
import android.Manifest
+import android.annotation.SuppressLint
+import android.app.ActivityManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageInstaller
import android.content.pm.PackageManager
import android.content.res.Resources
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
+import android.os.Parcel
+import android.os.Parcelable
import android.os.Process
import android.os.UserHandle
import android.os.UserManager
import android.util.Log
+import com.android.packageinstaller.v2.model.PackageUtil.getAppSnippet
+import java.io.ByteArrayOutputStream
import java.io.File
+import kotlinx.parcelize.Parceler
+import kotlinx.parcelize.Parcelize
object PackageUtil {
private val LOG_TAG = InstallRepository::class.java.simpleName
@@ -39,6 +50,24 @@
private const val SPLIT_BASE_APK_SUFFIX = "base.apk"
const val localLogv = false
+ const val ARGS_ABORT_REASON: String = "abort_reason"
+ const val ARGS_ACTION_REASON: String = "action_reason"
+ const val ARGS_ACTIVITY_RESULT_CODE: String = "activity_result_code"
+ const val ARGS_APP_DATA_SIZE: String = "app_data_size"
+ const val ARGS_APP_LABEL: String = "app_label"
+ const val ARGS_APP_SNIPPET: String = "app_snippet"
+ const val ARGS_ERROR_DIALOG_TYPE: String = "error_dialog_type"
+ const val ARGS_IS_ARCHIVE: String = "is_archive"
+ const val ARGS_IS_CLONE_USER: String = "clone_user"
+ const val ARGS_IS_UPDATING: String = "is_updating"
+ const val ARGS_LEGACY_CODE: String = "legacy_code"
+ const val ARGS_MESSAGE: String = "message"
+ const val ARGS_RESULT_INTENT: String = "result_intent"
+ const val ARGS_SHOULD_RETURN_RESULT: String = "should_return_result"
+ const val ARGS_SOURCE_APP: String = "source_app"
+ const val ARGS_STATUS_CODE: String = "status_code"
+ const val ARGS_TITLE: String = "title"
+
/**
* Determines if the UID belongs to the system downloads provider and returns the
* [ApplicationInfo] of the provider
@@ -238,7 +267,8 @@
context.resources,
info.getAppIcon()
) else pm.defaultActivityIcon
- return AppSnippet(label, icon)
+ val largeIconSize = getLargeIconSize(context)
+ return AppSnippet(label, icon, largeIconSize)
}
/**
@@ -247,8 +277,11 @@
*/
@JvmStatic
fun getAppSnippet(context: Context, pkgInfo: PackageInfo): AppSnippet {
+ val largeIconSize = getLargeIconSize(context)
return pkgInfo.applicationInfo?.let { getAppSnippet(context, it) } ?: run {
- AppSnippet(pkgInfo.packageName, context.packageManager.defaultActivityIcon)
+ AppSnippet(
+ pkgInfo.packageName, context.packageManager.defaultActivityIcon, largeIconSize
+ )
}
}
@@ -261,7 +294,8 @@
val pm = context.packageManager
val label = pm.getApplicationLabel(appInfo)
val icon = pm.getApplicationIcon(appInfo)
- return AppSnippet(label, icon)
+ val largeIconSize = getLargeIconSize(context)
+ return AppSnippet(label, icon, largeIconSize)
}
/**
@@ -270,16 +304,24 @@
*/
@JvmStatic
fun getAppSnippet(context: Context, pkgInfo: PackageInfo, sourceFile: File): AppSnippet {
+ val largeIconSize = getLargeIconSize(context)
pkgInfo.applicationInfo?.let {
val appInfoFromFile = processAppInfoForFile(it, sourceFile)
val label = getAppLabelFromFile(context, appInfoFromFile)
val icon = getAppIconFromFile(context, appInfoFromFile)
- return AppSnippet(label, icon)
+ return AppSnippet(label, icon, largeIconSize)
} ?: run {
- return AppSnippet(pkgInfo.packageName, context.packageManager.defaultActivityIcon)
+ return AppSnippet(
+ pkgInfo.packageName, context.packageManager.defaultActivityIcon, largeIconSize
+ )
}
}
+ private fun getLargeIconSize(context: Context): Int {
+ val am = context.getSystemService<ActivityManager>(ActivityManager::class.java)
+ return am.launcherLargeIconSize
+ }
+
/**
* Utility method to load application label
*
@@ -438,7 +480,69 @@
* The class to hold an incoming package's icon and label.
* See [getAppSnippet]
*/
- data class AppSnippet(var label: CharSequence?, var icon: Drawable?) {
+ @Parcelize
+ data class AppSnippet(
+ var label: CharSequence?,
+ var icon: Drawable?,
+ var iconSize: Int,
+ ) : Parcelable {
+ private companion object : Parceler<AppSnippet> {
+ override fun AppSnippet.write(dest: Parcel, flags: Int) {
+ dest.writeString(label.toString())
+
+ val bmp = getBitmapFromDrawable(icon!!)
+ dest.writeBlob(getBytesFromBitmap(bmp))
+ bmp.recycle()
+
+ dest.writeInt(iconSize)
+ }
+
+ @SuppressLint("UseKtx")
+ override fun create(parcel: Parcel): AppSnippet {
+ val label = parcel.readString()
+
+ val b: ByteArray = parcel.readBlob()!!
+ val bmp: Bitmap? = BitmapFactory.decodeByteArray(b, 0, b.size)
+ val icon = BitmapDrawable(Resources.getSystem(), bmp)
+
+ val iconSize = parcel.readInt()
+
+ return AppSnippet(label.toString(), icon, iconSize)
+ }
+ }
+
+ @SuppressLint("UseKtx")
+ private fun getBitmapFromDrawable(drawable: Drawable): Bitmap {
+ // Create an empty bitmap with the dimensions of our drawable
+ val bmp = Bitmap.createBitmap(
+ drawable.intrinsicWidth,
+ drawable.intrinsicHeight, Bitmap.Config.ARGB_8888
+ )
+ // Associate it with a canvas. This canvas will draw the icon on the bitmap
+ val canvas = Canvas(bmp)
+ // Draw the drawable in the canvas. The canvas will ultimately paint the drawable in the
+ // bitmap held within
+ drawable.draw(canvas)
+
+ // Scale it down if the icon is too large
+ if ((bmp.getWidth() > iconSize * 2) || (bmp.getHeight() > iconSize * 2)) {
+ val scaledBitmap = Bitmap.createScaledBitmap(bmp, iconSize, iconSize, true)
+ if (scaledBitmap != bmp) {
+ bmp.recycle()
+ }
+ return scaledBitmap
+ }
+ return bmp
+ }
+
+ private fun getBytesFromBitmap(bmp: Bitmap): ByteArray? {
+ var baos = ByteArrayOutputStream()
+ baos.use {
+ bmp.compress(Bitmap.CompressFormat.PNG, 100, it)
+ }
+ return baos.toByteArray()
+ }
+
override fun toString(): String {
return "AppSnippet[label = $label, hasIcon = ${icon != null}]"
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
index 481023e..4a8be8d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
@@ -133,9 +133,10 @@
val aborted = installStage as InstallAborted
when (aborted.abortReason) {
InstallAborted.ABORT_REASON_DONE,
- InstallAborted.ABORT_REASON_INTERNAL_ERROR -> {
+ InstallAborted.ABORT_REASON_INTERNAL_ERROR,
+ -> {
if (aborted.errorDialogType == InstallAborted.DLG_PACKAGE_ERROR) {
- val parseErrorDialog = ParseErrorFragment(aborted)
+ val parseErrorDialog = ParseErrorFragment.newInstance(aborted)
showDialogInner(parseErrorDialog)
} else {
setResult(aborted.activityResultCode, aborted.resultIntent, true)
@@ -151,12 +152,12 @@
val uar = installStage as InstallUserActionRequired
when (uar.actionReason) {
InstallUserActionRequired.USER_ACTION_REASON_INSTALL_CONFIRMATION -> {
- val actionDialog = InstallConfirmationFragment(uar)
+ val actionDialog = InstallConfirmationFragment.newInstance(uar)
showDialogInner(actionDialog)
}
InstallUserActionRequired.USER_ACTION_REASON_UNKNOWN_SOURCE -> {
- val externalSourceDialog = ExternalSourcesBlockedFragment(uar)
+ val externalSourceDialog = ExternalSourcesBlockedFragment.newInstance(uar)
showDialogInner(externalSourceDialog)
}
@@ -169,7 +170,7 @@
InstallStage.STAGE_INSTALLING -> {
val installing = installStage as InstallInstalling
- val installingDialog = InstallInstallingFragment(installing)
+ val installingDialog = InstallInstallingFragment.newInstance(installing)
showDialogInner(installingDialog)
}
@@ -179,7 +180,7 @@
val successIntent = success.resultIntent
setResult(RESULT_OK, successIntent, true)
} else {
- val successDialog = InstallSuccessFragment(success)
+ val successDialog = InstallSuccessFragment.newInstance(success)
showDialogInner(successDialog)
}
}
@@ -190,7 +191,7 @@
val failureIntent = failed.resultIntent
setResult(RESULT_FIRST_USER, failureIntent, true)
} else {
- val failureDialog = InstallFailedFragment(failed)
+ val failureDialog = InstallFailedFragment.newInstance(failed)
showDialogInner(failureDialog)
}
}
@@ -242,11 +243,11 @@
}
return when (restriction) {
UserManager.DISALLOW_INSTALL_APPS ->
- SimpleErrorFragment(R.string.install_apps_user_restriction_dlg_text)
+ SimpleErrorFragment.newInstance(R.string.install_apps_user_restriction_dlg_text)
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY ->
- SimpleErrorFragment(R.string.unknown_apps_user_restriction_dlg_text)
+ SimpleErrorFragment.newInstance(R.string.unknown_apps_user_restriction_dlg_text)
else -> null
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
index 0a02845e..08bc766 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
@@ -101,7 +101,7 @@
if (aborted.abortReason == UninstallAborted.ABORT_REASON_APP_UNAVAILABLE ||
aborted.abortReason == UninstallAborted.ABORT_REASON_USER_NOT_ALLOWED
) {
- val errorDialog = UninstallErrorFragment(aborted)
+ val errorDialog = UninstallErrorFragment.newInstance(aborted)
showDialogInner(errorDialog)
} else {
setResult(aborted.activityResultCode, null, true)
@@ -110,7 +110,7 @@
UninstallStage.STAGE_USER_ACTION_REQUIRED -> {
val uar = uninstallStage as UninstallUserActionRequired
- val confirmationDialog = UninstallConfirmationFragment(uar)
+ val confirmationDialog = UninstallConfirmationFragment.newInstance(uar)
showDialogInner(confirmationDialog)
}
@@ -120,7 +120,7 @@
// And a fragment if the user requests a result back. Should we consolidate and
// show a fragment always?
val uninstalling = uninstallStage as UninstallUninstalling
- val uninstallingDialog = UninstallUninstallingFragment(uninstalling)
+ val uninstallingDialog = UninstallUninstallingFragment.newInstance(uninstalling)
showDialogInner(uninstallingDialog)
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java
index 343a213..4c69b9d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java
@@ -16,17 +16,25 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ACTION_REASON;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_UPDATING;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SOURCE_APP;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallUserActionRequired;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
/**
@@ -37,14 +45,34 @@
private static final String LOG_TAG = ExternalSourcesBlockedFragment.class.getSimpleName();
@NonNull
- private final InstallUserActionRequired mDialogData;
+ private InstallUserActionRequired mDialogData;
@NonNull
private InstallActionListener mInstallActionListener;
@NonNull
private AlertDialog mDialog;
- public ExternalSourcesBlockedFragment(InstallUserActionRequired dialogData) {
- mDialogData = dialogData;
+ public ExternalSourcesBlockedFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallUserActionRequired} object containing data to display
+ * in the dialog
+ * @return an instance of the fragment
+ */
+ public static ExternalSourcesBlockedFragment newInstance(
+ @NonNull InstallUserActionRequired dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ACTION_REASON, dialogData.getActionReason());
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putBoolean(ARGS_IS_UPDATING, dialogData.isAppUpdating());
+ args.putString(ARGS_SOURCE_APP, dialogData.getSourceApp());
+
+ ExternalSourcesBlockedFragment fragment = new ExternalSourcesBlockedFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -56,6 +84,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
mDialog = new AlertDialog.Builder(requireContext())
.setTitle(mDialogData.getAppLabel())
@@ -96,4 +126,14 @@
super.onResume();
mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
}
+
+ private void setDialogData(Bundle args) {
+ int actionReason = args.getInt(ARGS_ACTION_REASON);
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ boolean isUpdating = args.getBoolean(ARGS_IS_UPDATING);
+ String sourceApp = args.getString(ARGS_SOURCE_APP);
+
+ mDialogData = new InstallUserActionRequired(actionReason, appSnippet, isUpdating,
+ sourceApp);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java
index e186590..03768fb 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java
@@ -16,6 +16,11 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ACTION_REASON;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_UPDATING;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SOURCE_APP;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@@ -26,11 +31,14 @@
import android.util.Log;
import android.view.View;
import android.widget.TextView;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallUserActionRequired;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
/**
@@ -39,15 +47,34 @@
public class InstallConfirmationFragment extends DialogFragment {
public static final String LOG_TAG = InstallConfirmationFragment.class.getSimpleName();
- @NonNull
- private final InstallUserActionRequired mDialogData;
+ private InstallUserActionRequired mDialogData;
@NonNull
private InstallActionListener mInstallActionListener;
@NonNull
private AlertDialog mDialog;
- public InstallConfirmationFragment(@NonNull InstallUserActionRequired dialogData) {
- mDialogData = dialogData;
+ public InstallConfirmationFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallUserActionRequired} object containing data to display
+ * in the dialog
+ * @return an instance of the fragment
+ */
+ public static InstallConfirmationFragment newInstance(
+ @NonNull InstallUserActionRequired dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ACTION_REASON, dialogData.getActionReason());
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putBoolean(ARGS_IS_UPDATING, dialogData.isAppUpdating());
+ args.putString(ARGS_SOURCE_APP, dialogData.getSourceApp());
+
+ InstallConfirmationFragment fragment = new InstallConfirmationFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -59,6 +86,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
@@ -127,4 +156,14 @@
super.onResume();
mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
}
+
+ private void setDialogData(Bundle args) {
+ int actionReason = args.getInt(ARGS_ACTION_REASON);
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ boolean isUpdating = args.getBoolean(ARGS_IS_UPDATING);
+ String sourceApp = args.getString(ARGS_SOURCE_APP);
+
+ mDialogData = new InstallUserActionRequired(actionReason, appSnippet, isUpdating,
+ sourceApp);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java
index 7c9d98d..6f65441 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java
@@ -16,19 +16,30 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_LEGACY_CODE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_RESULT_INTENT;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SHOULD_RETURN_RESULT;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_STATUS_CODE;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallFailed;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
/**
@@ -39,11 +50,32 @@
public class InstallFailedFragment extends DialogFragment {
private static final String LOG_TAG = InstallFailedFragment.class.getSimpleName();
- private final InstallFailed mDialogData;
+ private InstallFailed mDialogData;
private InstallActionListener mInstallActionListener;
- public InstallFailedFragment(InstallFailed dialogData) {
- mDialogData = dialogData;
+ public InstallFailedFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallFailed} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static InstallFailedFragment newInstance(@NonNull InstallFailed dialogData) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putInt(ARGS_LEGACY_CODE, dialogData.getLegacyCode());
+ args.putInt(ARGS_STATUS_CODE, dialogData.getStatusCode());
+ args.putString(ARGS_MESSAGE, dialogData.getMessage());
+ args.putBoolean(ARGS_SHOULD_RETURN_RESULT, dialogData.getShouldReturnResult());
+ args.putParcelable(ARGS_RESULT_INTENT, dialogData.getResultIntent());
+
+ InstallFailedFragment fragment = new InstallFailedFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -55,6 +87,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
AlertDialog dialog = new AlertDialog.Builder(requireContext())
@@ -105,4 +139,16 @@
super.onCancel(dialog);
mInstallActionListener.onNegativeResponse(mDialogData.getStageCode());
}
+
+ private void setDialogData(Bundle args) {
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ int legacyCode = args.getInt(ARGS_LEGACY_CODE);
+ int statusCode = args.getInt(ARGS_STATUS_CODE);
+ String message = args.getString(ARGS_MESSAGE);
+ boolean shouldReturnResult = args.getBoolean(ARGS_SHOULD_RETURN_RESULT);
+ Intent resultIntent = args.getParcelable(ARGS_RESULT_INTENT, Intent.class);
+
+ mDialogData = new InstallFailed(appSnippet, legacyCode, statusCode, message,
+ shouldReturnResult, resultIntent);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java
index 27210b7..17093cf 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java
@@ -16,17 +16,22 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallInstalling;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
/**
* Dialog to show when an install is in progress.
@@ -34,16 +39,34 @@
public class InstallInstallingFragment extends DialogFragment {
private static final String LOG_TAG = InstallInstallingFragment.class.getSimpleName();
- private final InstallInstalling mDialogData;
+ private InstallInstalling mDialogData;
private AlertDialog mDialog;
- public InstallInstallingFragment(InstallInstalling dialogData) {
- mDialogData = dialogData;
+ public InstallInstallingFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallInstalling} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static InstallInstallingFragment newInstance(@NonNull InstallInstalling dialogData) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+
+ InstallInstallingFragment fragment = new InstallInstallingFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
mDialog = new AlertDialog.Builder(requireContext())
@@ -64,4 +87,9 @@
super.onStart();
mDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setEnabled(false);
}
+
+ private void setDialogData(Bundle args) {
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ mDialogData = new InstallInstalling(appSnippet);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java
index 28b5423b..5696afa 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java
@@ -16,22 +16,31 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_RESULT_INTENT;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SHOULD_RETURN_RESULT;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallSuccess;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
+
import java.util.List;
/**
@@ -41,13 +50,31 @@
public class InstallSuccessFragment extends DialogFragment {
private static final String LOG_TAG = InstallSuccessFragment.class.getSimpleName();
- private final InstallSuccess mDialogData;
+ private InstallSuccess mDialogData;
private AlertDialog mDialog;
private InstallActionListener mInstallActionListener;
private PackageManager mPm;
- public InstallSuccessFragment(InstallSuccess dialogData) {
- mDialogData = dialogData;
+ public InstallSuccessFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallSuccess} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static InstallSuccessFragment newInstance(@NonNull InstallSuccess dialogData) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putBoolean(ARGS_SHOULD_RETURN_RESULT, dialogData.getShouldReturnResult());
+ args.putParcelable(ARGS_RESULT_INTENT, dialogData.getResultIntent());
+
+ InstallSuccessFragment fragment = new InstallSuccessFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -60,6 +87,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
mDialog = new AlertDialog.Builder(requireContext())
@@ -105,4 +134,12 @@
Log.i(LOG_TAG, "Finished installing " + mDialogData.getAppLabel());
mInstallActionListener.onNegativeResponse(mDialogData.getStageCode());
}
+
+ private void setDialogData(Bundle args) {
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ boolean shouldReturnResult = args.getBoolean(ARGS_SHOULD_RETURN_RESULT);
+ Intent resultIntent = args.getParcelable(ARGS_RESULT_INTENT, Intent.class);
+
+ mDialogData = new InstallSuccess(appSnippet, shouldReturnResult, resultIntent);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java
index cde3d8d..6834f44 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java
@@ -16,14 +16,23 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ABORT_REASON;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ACTIVITY_RESULT_CODE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ERROR_DIALOG_TYPE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_RESULT_INTENT;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallAborted;
import com.android.packageinstaller.v2.ui.InstallActionListener;
@@ -31,11 +40,31 @@
public class ParseErrorFragment extends DialogFragment {
private static final String LOG_TAG = ParseErrorFragment.class.getSimpleName();
- private final InstallAborted mDialogData;
+ private InstallAborted mDialogData;
private InstallActionListener mInstallActionListener;
- public ParseErrorFragment(InstallAborted dialogData) {
- mDialogData = dialogData;
+ public ParseErrorFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallAborted} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static ParseErrorFragment newInstance(@NonNull InstallAborted dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ABORT_REASON, dialogData.getAbortReason());
+ args.putString(ARGS_MESSAGE, dialogData.getMessage());
+ args.putParcelable(ARGS_RESULT_INTENT, dialogData.getResultIntent());
+ args.putInt(ARGS_ACTIVITY_RESULT_CODE, dialogData.getActivityResultCode());
+ args.putInt(ARGS_ERROR_DIALOG_TYPE, dialogData.getErrorDialogType());
+
+ ParseErrorFragment fragment = new ParseErrorFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -47,6 +76,8 @@
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
return new AlertDialog.Builder(requireContext())
.setMessage(R.string.Parse_error_dlg_text)
@@ -63,4 +94,15 @@
mInstallActionListener.onNegativeResponse(
mDialogData.getActivityResultCode(), mDialogData.getResultIntent());
}
+
+ private void setDialogData(Bundle args) {
+ int abortReason = args.getInt(ARGS_ABORT_REASON);
+ String message = args.getString(ARGS_MESSAGE);
+ Intent resultIntent = args.getParcelable(ARGS_RESULT_INTENT, Intent.class);
+ int activityResultCode = args.getInt(ARGS_ACTIVITY_RESULT_CODE);
+ int errorDialogType = args.getInt(ARGS_ERROR_DIALOG_TYPE);
+
+ mDialogData = new InstallAborted(abortReason, message, resultIntent, activityResultCode,
+ errorDialogType);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java
index 66a353a..8b1ccd8 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java
@@ -16,14 +16,18 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallStage;
import com.android.packageinstaller.v2.ui.InstallActionListener;
@@ -31,11 +35,25 @@
public class SimpleErrorFragment extends DialogFragment {
private static final String LOG_TAG = SimpleErrorFragment.class.getSimpleName();
- private final int mMessageResId;
+ private int mMessageResId;
private InstallActionListener mInstallActionListener;
- public SimpleErrorFragment(int messageResId) {
- mMessageResId = messageResId;
+ public SimpleErrorFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @return an instance of the fragment
+ */
+ public static SimpleErrorFragment newInstance(int messageResId) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_MESSAGE, messageResId);
+
+ SimpleErrorFragment fragment = new SimpleErrorFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -47,6 +65,8 @@
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
+ mMessageResId = requireArguments().getInt(ARGS_MESSAGE);
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" +
"Dialog message: " + requireContext().getString(mMessageResId));
return new AlertDialog.Builder(requireContext())
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java
index 524b4e6..860f6a0 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java
@@ -18,6 +18,11 @@
import static android.text.format.Formatter.formatFileSize;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_DATA_SIZE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_ARCHIVE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_TITLE;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@@ -27,9 +32,11 @@
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.UninstallUserActionRequired;
import com.android.packageinstaller.v2.ui.UninstallActionListener;
@@ -38,14 +45,34 @@
* Dialog to show while requesting user confirmation for uninstalling an app.
*/
public class UninstallConfirmationFragment extends DialogFragment {
- private static final String LOG_TAG = UninstallConfirmationFragment.class.getSimpleName();
- private final UninstallUserActionRequired mDialogData;
- private UninstallActionListener mUninstallActionListener;
+ private static final String LOG_TAG = UninstallConfirmationFragment.class.getSimpleName();
+ private UninstallUserActionRequired mDialogData;
+ private UninstallActionListener mUninstallActionListener;
private CheckBox mKeepData;
- public UninstallConfirmationFragment(UninstallUserActionRequired dialogData) {
- mDialogData = dialogData;
+ public UninstallConfirmationFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link UninstallUserActionRequired} object containing data to
+ * display in the dialog
+ * @return an instance of the fragment
+ */
+ public static UninstallConfirmationFragment newInstance(
+ @NonNull UninstallUserActionRequired dialogData) {
+ Bundle args = new Bundle();
+ args.putLong(ARGS_APP_DATA_SIZE, dialogData.getAppDataSize());
+ args.putBoolean(ARGS_IS_ARCHIVE, dialogData.isArchive());
+ args.putString(ARGS_TITLE, dialogData.getTitle());
+ args.putString(ARGS_MESSAGE, dialogData.getMessage());
+
+ UninstallConfirmationFragment fragment = new UninstallConfirmationFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -57,6 +84,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
.setTitle(mDialogData.getTitle())
@@ -88,4 +117,13 @@
super.onCancel(dialog);
mUninstallActionListener.onNegativeResponse();
}
+
+ private void setDialogData(Bundle args) {
+ long appDataSize = args.getLong(ARGS_APP_DATA_SIZE);
+ boolean isArchive = args.getBoolean(ARGS_IS_ARCHIVE);
+ String title = args.getString(ARGS_TITLE);
+ String message = args.getString(ARGS_MESSAGE);
+
+ mDialogData = new UninstallUserActionRequired(title, message, appDataSize, isArchive);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java
index 51e16cb..9ed6412 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java
@@ -16,15 +16,19 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ABORT_REASON;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.UninstallAborted;
import com.android.packageinstaller.v2.ui.UninstallActionListener;
@@ -35,11 +39,27 @@
public class UninstallErrorFragment extends DialogFragment {
private static final String LOG_TAG = UninstallErrorFragment.class.getSimpleName();
- private final UninstallAborted mDialogData;
+ private UninstallAborted mDialogData;
private UninstallActionListener mUninstallActionListener;
- public UninstallErrorFragment(UninstallAborted dialogData) {
- mDialogData = dialogData;
+ public UninstallErrorFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link UninstallAborted} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static UninstallErrorFragment newInstance(UninstallAborted dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ABORT_REASON, dialogData.getAbortReason());
+
+ UninstallErrorFragment fragment = new UninstallErrorFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -51,6 +71,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
.setMessage(mDialogData.getDialogTextResource())
@@ -68,4 +90,9 @@
super.onCancel(dialog);
mUninstallActionListener.onNegativeResponse();
}
+
+ private void setDialogData(Bundle args) {
+ int abortReason = args.getInt(ARGS_ABORT_REASON);
+ mDialogData = new UninstallAborted(abortReason);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java
index 626ff6b..ae56c4d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java
@@ -16,12 +16,17 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_LABEL;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_CLONE_USER;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.UninstallUninstalling;
@@ -33,13 +38,32 @@
private static final String LOG_TAG = UninstallUninstallingFragment.class.getSimpleName();
UninstallUninstalling mDialogData;
- public UninstallUninstallingFragment(UninstallUninstalling dialogData) {
- mDialogData = dialogData;
+ UninstallUninstallingFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link UninstallUninstalling} object containing data to display in
+ * the dialog
+ * @return an instance of the fragment
+ */
+ public static UninstallUninstallingFragment newInstance(UninstallUninstalling dialogData) {
+ Bundle args = new Bundle();
+ args.putCharSequence(ARGS_APP_LABEL, dialogData.getAppLabel());
+ args.putBoolean(ARGS_IS_CLONE_USER, dialogData.isCloneUser());
+
+ UninstallUninstallingFragment fragment = new UninstallUninstallingFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
.setCancelable(false);
@@ -55,4 +79,11 @@
return dialog;
}
+
+ private void setDialogData(Bundle args) {
+ CharSequence label = args.getCharSequence(ARGS_APP_LABEL);
+ boolean isCloneUser = args.getBoolean(ARGS_IS_CLONE_USER);
+
+ mDialogData = new UninstallUninstalling(label, isCloneUser);
+ }
}
diff --git a/packages/SettingsLib/AndroidManifest.xml b/packages/SettingsLib/AndroidManifest.xml
index 412ff29..473b7eb 100644
--- a/packages/SettingsLib/AndroidManifest.xml
+++ b/packages/SettingsLib/AndroidManifest.xml
@@ -21,6 +21,13 @@
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<application>
+ <activity
+ android:name=".users.CreateUserActivity"
+ android:excludeFromRecents="true"
+ android:exported="false"
+ android:finishOnCloseSystemDialogs="true"
+ android:launchMode="singleInstance"
+ android:theme="@style/Theme.Transparent"/>
</application>
</manifest>
diff --git a/packages/SettingsLib/BannerMessagePreference/Android.bp b/packages/SettingsLib/BannerMessagePreference/Android.bp
index 182daeb..203a3bf 100644
--- a/packages/SettingsLib/BannerMessagePreference/Android.bp
+++ b/packages/SettingsLib/BannerMessagePreference/Android.bp
@@ -31,5 +31,6 @@
apex_available: [
"//apex_available:platform",
"com.android.healthfitness",
+ "com.android.permission",
],
}
diff --git a/packages/SettingsLib/BannerMessagePreference/res/drawable-v35/settingslib_resolved_banner_avd.xml b/packages/SettingsLib/BannerMessagePreference/res/drawable-v35/settingslib_resolved_banner_avd.xml
new file mode 100644
index 0000000..c999de7
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/drawable-v35/settingslib_resolved_banner_avd.xml
@@ -0,0 +1,157 @@
+<!--
+ ~ Copyright (C) 2025 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="112dp"
+ android:height="112dp"
+ android:viewportHeight="112"
+ android:viewportWidth="112">
+ <group android:name="_R_G">
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="56.5"
+ android:translateY="56.625">
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="0"
+ android:fillColor="?android:attr/textColorPrimary"
+ android:fillType="nonZero"
+ android:pathData=" M-14.75 -0.59 C-14.75,-0.59 -15.32,-1.16 -15.32,-1.16 C-15.32,-1.16 -14.67,-0.73 -14.67,-0.73 C-14.67,-0.73 -14.39,-0.44 -14.39,-0.44 C-14.39,-0.44 -17.32,2.5 -17.32,2.5 C-17.32,2.5 -17.59,2.23 -17.59,2.23 C-17.59,2.23 -14.75,-0.59 -14.75,-0.59c "
+ android:trimPathEnd="1"
+ android:trimPathOffset="0"
+ android:trimPathStart="0" />
+ </group>
+ <group
+ android:name="_R_G_L_0_G"
+ android:rotation="-90"
+ android:translateX="56"
+ android:translateY="56">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M53.5 0 C53.5,-29.53 29.53,-53.5 0,-53.5 C0,-53.5 0,-53.5 0,-53.5 C-29.53,-53.5 -53.5,-29.53 -53.5,0 C-53.5,0 -53.5,0 -53.5,0 C-53.5,29.53 -29.53,53.5 0,53.5 C0,53.5 0,53.5 0,53.5 C29.53,53.5 53.5,29.53 53.5,0 C53.5,0 53.5,0 53.5,0c "
+ android:strokeAlpha="1"
+ android:strokeColor="?android:attr/textColorTertiary"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="5"
+ android:trimPathEnd="0"
+ android:trimPathOffset="0"
+ android:trimPathStart="0" />
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="0"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="400"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M-14.75 -0.59 C-14.75,-0.59 -15.32,-1.16 -15.32,-1.16 C-15.32,-1.16 -14.67,-0.73 -14.67,-0.73 C-14.67,-0.73 -14.39,-0.44 -14.39,-0.44 C-14.39,-0.44 -17.32,2.5 -17.32,2.5 C-17.32,2.5 -17.59,2.23 -17.59,2.23 C-17.59,2.23 -14.75,-0.59 -14.75,-0.59c "
+ android:valueTo="M-14.75 -0.59 C-14.75,-0.59 -15.32,-1.16 -15.32,-1.16 C-15.32,-1.16 -14.67,-0.73 -14.67,-0.73 C-14.67,-0.73 -14.39,-0.44 -14.39,-0.44 C-14.39,-0.44 -17.32,2.5 -17.32,2.5 C-17.32,2.5 -17.59,2.23 -17.59,2.23 C-17.59,2.23 -14.75,-0.59 -14.75,-0.59c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="pathData"
+ android:startOffset="400"
+ android:valueFrom="M-14.75 -0.59 C-14.75,-0.59 -15.32,-1.16 -15.32,-1.16 C-15.32,-1.16 -14.67,-0.73 -14.67,-0.73 C-14.67,-0.73 -14.39,-0.44 -14.39,-0.44 C-14.39,-0.44 -17.32,2.5 -17.32,2.5 C-17.32,2.5 -17.59,2.23 -17.59,2.23 C-17.59,2.23 -14.75,-0.59 -14.75,-0.59c "
+ android:valueTo="M-14.75 -0.59 C-14.75,-0.59 -6.41,7.75 -6.41,7.75 C-6.41,7.75 -6.3,7.65 -6.3,7.65 C-6.3,7.65 -3.48,10.47 -3.48,10.47 C-3.48,10.47 -6.41,13.41 -6.41,13.41 C-6.41,13.41 -17.59,2.23 -17.59,2.23 C-17.59,2.23 -14.75,-0.59 -14.75,-0.59c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="pathData"
+ android:startOffset="483"
+ android:valueFrom="M-14.75 -0.59 C-14.75,-0.59 -6.41,7.75 -6.41,7.75 C-6.41,7.75 -6.3,7.65 -6.3,7.65 C-6.3,7.65 -3.48,10.47 -3.48,10.47 C-3.48,10.47 -6.41,13.41 -6.41,13.41 C-6.41,13.41 -17.59,2.23 -17.59,2.23 C-17.59,2.23 -14.75,-0.59 -14.75,-0.59c "
+ android:valueTo="M-14.75 -0.59 C-14.75,-0.59 -6.41,7.75 -6.41,7.75 C-6.41,7.75 14.77,-13.41 14.77,-13.41 C14.77,-13.41 17.59,-10.59 17.59,-10.59 C17.59,-10.59 -6.41,13.41 -6.41,13.41 C-6.41,13.41 -17.59,2.23 -17.59,2.23 C-17.59,2.23 -14.75,-0.59 -14.75,-0.59c "
+ android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="500"
+ android:propertyName="trimPathEnd"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="667"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/layout-v35/settingslib_expressive_banner_message.xml b/packages/SettingsLib/BannerMessagePreference/res/layout-v35/settingslib_expressive_banner_message.xml
index b10ef6e..c448a2d 100644
--- a/packages/SettingsLib/BannerMessagePreference/res/layout-v35/settingslib_expressive_banner_message.xml
+++ b/packages/SettingsLib/BannerMessagePreference/res/layout-v35/settingslib_expressive_banner_message.xml
@@ -28,81 +28,104 @@
android:orientation="vertical"
style="@style/Banner.Preference.SettingsLib.Expressive">
- <RelativeLayout
- android:id="@+id/top_row"
+ <FrameLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:layout_height="wrap_content">
<LinearLayout
+ android:id="@+id/banner_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_marginEnd="@dimen/settingslib_expressive_space_medium4"
android:orientation="vertical">
- <TextView
- android:id="@+id/banner_header"
+
+ <RelativeLayout
+ android:id="@+id/top_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/Banner.Header.SettingsLib.Expressive"/>
+ android:orientation="horizontal">
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/banner_icon"
- android:layout_width="@dimen/settingslib_expressive_space_small3"
- android:layout_height="@dimen/settingslib_expressive_space_small3"
- android:layout_gravity="center_vertical"
- android:importantForAccessibility="no"
- android:scaleType="fitCenter" />
-
- <TextView
- android:id="@+id/banner_title"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/Banner.Title.SettingsLib.Expressive" />
- </LinearLayout>
+ android:layout_alignParentStart="true"
+ android:layout_marginEnd="@dimen/settingslib_expressive_space_medium4"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/banner_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/Banner.Header.SettingsLib.Expressive"/>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/banner_icon"
+ android:layout_width="@dimen/settingslib_expressive_space_small3"
+ android:layout_height="@dimen/settingslib_expressive_space_small3"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="@dimen/settingslib_expressive_space_extrasmall4"
+ android:importantForAccessibility="no"
+ android:scaleType="fitCenter" />
+
+ <TextView
+ android:id="@+id/banner_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/Banner.Title.SettingsLib.Expressive" />
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/banner_subtitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/Banner.Subtitle.SettingsLib.Expressive"/>
+ </LinearLayout>
+
+ <ImageButton
+ android:id="@+id/banner_dismiss_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@string/accessibility_banner_message_dismiss"
+ style="@style/Banner.Dismiss.SettingsLib.Expressive" />
+ </RelativeLayout>
<TextView
- android:id="@+id/banner_subtitle"
+ android:id="@+id/banner_summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/Banner.Summary.SettingsLib.Expressive"/>
+
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/Banner.Subtitle.SettingsLib.Expressive"/>
+ android:id="@+id/banner_buttons_frame"
+ android:paddingTop="@dimen/settingslib_expressive_space_extrasmall6"
+ android:orientation="horizontal">
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/banner_negative_btn"
+ android:layout_weight="1"
+ style="@style/Banner.NegativeButton.SettingsLib.Expressive"/>
+ <Space
+ android:id="@+id/banner_button_space"
+ android:layout_width="@dimen/settingslib_expressive_space_extrasmall4"
+ android:layout_height="@dimen/settingslib_expressive_space_small1"/>
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/banner_positive_btn"
+ android:layout_weight="1"
+ style="@style/Banner.PositiveButton.SettingsLib.Expressive"/>
+ </LinearLayout>
</LinearLayout>
- <ImageButton
- android:id="@+id/banner_dismiss_btn"
+ <TextView
+ android:id="@+id/resolved_banner_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="@style/Banner.Dismiss.SettingsLib.Expressive" />
- </RelativeLayout>
-
- <TextView
- android:id="@+id/banner_summary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="@style/Banner.Summary.SettingsLib.Expressive"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/banner_buttons_frame"
- android:paddingTop="@dimen/settingslib_expressive_space_extrasmall6"
- android:orientation="horizontal">
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/banner_negative_btn"
- android:layout_weight="1"
- style="@style/Banner.NegativeButton.SettingsLib.Expressive"/>
- <Space
- android:layout_width="@dimen/settingslib_expressive_space_extrasmall4"
- android:layout_height="@dimen/settingslib_expressive_space_small1"/>
- <com.google.android.material.button.MaterialButton
- android:id="@+id/banner_positive_btn"
- android:layout_weight="1"
- style="@style/Banner.PositiveButton.SettingsLib.Expressive"/>
- </LinearLayout>
+ android:drawableTop="@drawable/settingslib_resolved_banner_avd"
+ android:visibility="gone"
+ style="@style/Banner.ResolvedText.SettingsLib.Expressive"/>
+ </FrameLayout>
</com.android.settingslib.widget.BannerMessageView>
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-v35/styles_expressive.xml b/packages/SettingsLib/BannerMessagePreference/res/values-v35/styles_expressive.xml
index b864311..09e07cc 100644
--- a/packages/SettingsLib/BannerMessagePreference/res/values-v35/styles_expressive.xml
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-v35/styles_expressive.xml
@@ -33,7 +33,6 @@
<style name="Banner.Title.SettingsLib.Expressive"
parent="">
<item name="android:layout_gravity">start</item>
- <item name="android:layout_marginLeft">@dimen/settingslib_expressive_space_extrasmall4</item>
<item name="android:textAlignment">viewStart</item>
<item name="android:textAppearance">@style/TextAppearance.SettingsLib.TitleLarge.Emphasized</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -73,4 +72,11 @@
parent="@style/SettingsLibButtonStyle.Expressive.Outline.Extra">
<item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Small</item>
</style>
+
+ <style name="Banner.ResolvedText.SettingsLib.Expressive" parent="">
+ <item name="android:layout_gravity">center</item>
+ <item name="android:drawablePadding">@dimen/settingslib_expressive_space_small1</item>
+ <item name="android:textAppearance">@style/TextAppearance.SettingsLib.BodyMedium</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java
index c82829d..c90a76a 100644
--- a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java
+++ b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessagePreference.java
@@ -35,6 +35,8 @@
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.preference.Preference;
@@ -43,6 +45,9 @@
import com.android.settingslib.widget.preference.banner.R;
import com.google.android.material.button.MaterialButton;
+
+import java.util.Objects;
+
/**
* Banner message is a banner displaying important information (permission request, page error etc),
* and provide actions for user to address. It requires a user action to be dismissed.
@@ -67,13 +72,15 @@
R.color.banner_accent_attention_normal,
R.color.settingslib_banner_button_background_normal);
- // Corresponds to the enum valye of R.attr.attentionLevel
+ // Corresponds to the enum value of R.attr.attentionLevel
private final int mAttrValue;
@ColorRes private final int mBackgroundColorResId;
@ColorRes private final int mAccentColorResId;
@ColorRes private final int mButtonBackgroundColorResId;
- AttentionLevel(int attrValue, @ColorRes int backgroundColorResId,
+ AttentionLevel(
+ int attrValue,
+ @ColorRes int backgroundColorResId,
@ColorRes int accentColorResId,
@ColorRes int buttonBackgroundColorResId) {
mAttrValue = attrValue;
@@ -115,33 +122,38 @@
new BannerMessagePreference.DismissButtonInfo();
// Default attention level is High.
- private AttentionLevel mAttentionLevel = AttentionLevel.HIGH;
- private CharSequence mSubtitle;
- private CharSequence mHeader;
+ @NonNull private AttentionLevel mAttentionLevel = AttentionLevel.HIGH;
+ @Nullable private CharSequence mSubtitle;
+ @Nullable private CharSequence mHeader;
private int mButtonOrientation;
+ @Nullable private ResolutionAnimator.Data mResolutionData;
- public BannerMessagePreference(Context context) {
+ public BannerMessagePreference(@NonNull Context context) {
super(context);
init(context, null /* attrs */);
}
- public BannerMessagePreference(Context context, AttributeSet attrs) {
+ public BannerMessagePreference(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
- public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ public BannerMessagePreference(
+ @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
- public BannerMessagePreference(Context context, AttributeSet attrs, int defStyleAttr,
+ public BannerMessagePreference(
+ @NonNull Context context,
+ @Nullable AttributeSet attrs,
+ int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
- private void init(Context context, AttributeSet attrs) {
+ private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
setSelectable(false);
int resId = SettingsThemeHelper.isExpressiveTheme(context)
? R.layout.settingslib_expressive_banner_message
@@ -166,7 +178,7 @@
}
@Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
+ public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final Context context = getContext();
@@ -193,14 +205,20 @@
final ImageView iconView = (ImageView) holder.findViewById(R.id.banner_icon);
if (iconView != null) {
Drawable icon = getIcon();
- iconView.setImageDrawable(
- icon == null
- ? getContext().getDrawable(R.drawable.ic_warning)
- : icon);
- if (mAttentionLevel != AttentionLevel.NORMAL
- && !SettingsThemeHelper.isExpressiveTheme(context)) {
- iconView.setColorFilter(
- new PorterDuffColorFilter(accentColor, PorterDuff.Mode.SRC_IN));
+
+ if (icon == null && SettingsThemeHelper.isExpressiveTheme(context)) {
+ iconView.setVisibility(View.GONE);
+ } else {
+ iconView.setVisibility(View.VISIBLE);
+ iconView.setImageDrawable(
+ icon == null
+ ? getContext().getDrawable(R.drawable.ic_warning)
+ : icon);
+ if (mAttentionLevel != AttentionLevel.NORMAL
+ && !SettingsThemeHelper.isExpressiveTheme(context)) {
+ iconView.setColorFilter(
+ new PorterDuffColorFilter(accentColor, PorterDuff.Mode.SRC_IN));
+ }
}
}
@@ -233,8 +251,10 @@
mDismissButtonInfo.setUpButton();
final TextView subtitleView = (TextView) holder.findViewById(R.id.banner_subtitle);
- subtitleView.setText(mSubtitle);
- subtitleView.setVisibility(mSubtitle == null ? View.GONE : View.VISIBLE);
+ if (subtitleView != null) {
+ subtitleView.setText(mSubtitle);
+ subtitleView.setVisibility(mSubtitle == null ? View.GONE : View.VISIBLE);
+ }
TextView headerView = (TextView) holder.findViewById(R.id.banner_header);
if (headerView != null) {
@@ -268,11 +288,25 @@
linearLayout.setOrientation(mButtonOrientation);
}
}
+
+ View buttonSpace = holder.findViewById(R.id.banner_button_space);
+ if (buttonSpace != null) {
+ if (mPositiveButtonInfo.shouldBeVisible() && mNegativeButtonInfo.shouldBeVisible()) {
+ buttonSpace.setVisibility(View.VISIBLE);
+ } else {
+ buttonSpace.setVisibility(View.GONE);
+ }
+ }
+
+ if (mResolutionData != null) {
+ new ResolutionAnimator(mResolutionData, holder).startResolutionAnimation();
+ }
}
/**
- * Set the visibility state of positive button.
+ * Sets the visibility state of the positive button.
*/
+ @NonNull
public BannerMessagePreference setPositiveButtonVisible(boolean isVisible) {
if (isVisible != mPositiveButtonInfo.mIsVisible) {
mPositiveButtonInfo.mIsVisible = isVisible;
@@ -282,8 +316,9 @@
}
/**
- * Set the visibility state of negative button.
+ * Sets the visibility state of the negative button.
*/
+ @NonNull
public BannerMessagePreference setNegativeButtonVisible(boolean isVisible) {
if (isVisible != mNegativeButtonInfo.mIsVisible) {
mNegativeButtonInfo.mIsVisible = isVisible;
@@ -293,9 +328,10 @@
}
/**
- * Set the visibility state of dismiss button.
+ * Sets the visibility state of the dismiss button.
*/
@RequiresApi(Build.VERSION_CODES.S)
+ @NonNull
public BannerMessagePreference setDismissButtonVisible(boolean isVisible) {
if (isVisible != mDismissButtonInfo.mIsVisible) {
mDismissButtonInfo.mIsVisible = isVisible;
@@ -305,10 +341,35 @@
}
/**
- * Register a callback to be invoked when positive button is clicked.
+ * Sets the enabled state of the positive button.
*/
+ @NonNull
+ public BannerMessagePreference setPositiveButtonEnabled(boolean isEnabled) {
+ if (isEnabled != mPositiveButtonInfo.mIsEnabled) {
+ mPositiveButtonInfo.mIsEnabled = isEnabled;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the enabled state of the negative button.
+ */
+ @NonNull
+ public BannerMessagePreference setNegativeButtonEnabled(boolean isEnabled) {
+ if (isEnabled != mNegativeButtonInfo.mIsEnabled) {
+ mNegativeButtonInfo.mIsEnabled = isEnabled;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Registers a callback to be invoked when positive button is clicked.
+ */
+ @NonNull
public BannerMessagePreference setPositiveButtonOnClickListener(
- View.OnClickListener listener) {
+ @Nullable View.OnClickListener listener) {
if (listener != mPositiveButtonInfo.mListener) {
mPositiveButtonInfo.mListener = listener;
notifyChanged();
@@ -317,10 +378,11 @@
}
/**
- * Register a callback to be invoked when negative button is clicked.
+ * Registers a callback to be invoked when negative button is clicked.
*/
+ @NonNull
public BannerMessagePreference setNegativeButtonOnClickListener(
- View.OnClickListener listener) {
+ @Nullable View.OnClickListener listener) {
if (listener != mNegativeButtonInfo.mListener) {
mNegativeButtonInfo.mListener = listener;
notifyChanged();
@@ -329,11 +391,12 @@
}
/**
- * Register a callback to be invoked when the dismiss button is clicked.
+ * Registers a callback to be invoked when the dismiss button is clicked.
*/
@RequiresApi(Build.VERSION_CODES.S)
+ @NonNull
public BannerMessagePreference setDismissButtonOnClickListener(
- View.OnClickListener listener) {
+ @Nullable View.OnClickListener listener) {
if (listener != mDismissButtonInfo.mListener) {
mDismissButtonInfo.mListener = listener;
notifyChanged();
@@ -344,6 +407,7 @@
/**
* Sets the text to be displayed in positive button.
*/
+ @NonNull
public BannerMessagePreference setPositiveButtonText(@StringRes int textResId) {
return setPositiveButtonText(getContext().getString(textResId));
}
@@ -351,7 +415,9 @@
/**
* Sets the text to be displayed in positive button.
*/
- public BannerMessagePreference setPositiveButtonText(CharSequence positiveButtonText) {
+ @NonNull
+ public BannerMessagePreference setPositiveButtonText(
+ @Nullable CharSequence positiveButtonText) {
if (!TextUtils.equals(positiveButtonText, mPositiveButtonInfo.mText)) {
mPositiveButtonInfo.mText = positiveButtonText;
notifyChanged();
@@ -362,6 +428,7 @@
/**
* Sets the text to be displayed in negative button.
*/
+ @NonNull
public BannerMessagePreference setNegativeButtonText(@StringRes int textResId) {
return setNegativeButtonText(getContext().getString(textResId));
}
@@ -369,7 +436,9 @@
/**
* Sets the text to be displayed in negative button.
*/
- public BannerMessagePreference setNegativeButtonText(CharSequence negativeButtonText) {
+ @NonNull
+ public BannerMessagePreference setNegativeButtonText(
+ @Nullable CharSequence negativeButtonText) {
if (!TextUtils.equals(negativeButtonText, mNegativeButtonInfo.mText)) {
mNegativeButtonInfo.mText = negativeButtonText;
notifyChanged();
@@ -380,8 +449,12 @@
/**
* Sets button orientation.
*/
- @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ @NonNull
public BannerMessagePreference setButtonOrientation(int orientation) {
+ if (!SettingsThemeHelper.isExpressiveTheme(getContext())) {
+ return this;
+ }
+
if (mButtonOrientation != orientation) {
mButtonOrientation = orientation;
notifyChanged();
@@ -393,6 +466,7 @@
* Sets the subtitle.
*/
@RequiresApi(Build.VERSION_CODES.S)
+ @NonNull
public BannerMessagePreference setSubtitle(@StringRes int textResId) {
return setSubtitle(getContext().getString(textResId));
}
@@ -401,7 +475,8 @@
* Sets the subtitle.
*/
@RequiresApi(Build.VERSION_CODES.S)
- public BannerMessagePreference setSubtitle(CharSequence subtitle) {
+ @NonNull
+ public BannerMessagePreference setSubtitle(@Nullable CharSequence subtitle) {
if (!TextUtils.equals(subtitle, mSubtitle)) {
mSubtitle = subtitle;
notifyChanged();
@@ -412,7 +487,7 @@
/**
* Sets the header.
*/
- @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ @NonNull
public BannerMessagePreference setHeader(@StringRes int textResId) {
return setHeader(getContext().getString(textResId));
}
@@ -420,8 +495,12 @@
/**
* Sets the header.
*/
- @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
- public BannerMessagePreference setHeader(CharSequence header) {
+ @NonNull
+ public BannerMessagePreference setHeader(@Nullable CharSequence header) {
+ if (!SettingsThemeHelper.isExpressiveTheme(getContext())) {
+ return this;
+ }
+
if (!TextUtils.equals(header, mHeader)) {
mHeader = header;
notifyChanged();
@@ -430,32 +509,75 @@
}
/**
- * Sets the attention level. This will update the color theme of the preference.
+ * Plays a resolution animation, showing the given message.
*/
- public BannerMessagePreference setAttentionLevel(AttentionLevel attentionLevel) {
- if (attentionLevel == mAttentionLevel) {
+ @NonNull
+ public BannerMessagePreference showResolutionAnimation(
+ @NonNull CharSequence resolutionMessage,
+ @NonNull ResolutionCompletedCallback onCompletionCallback) {
+ if (!SettingsThemeHelper.isExpressiveTheme(getContext())) {
return this;
}
-
- if (attentionLevel != null) {
- mAttentionLevel = attentionLevel;
+ ResolutionAnimator.Data resolutionData =
+ new ResolutionAnimator.Data(resolutionMessage, onCompletionCallback);
+ if (!Objects.equals(mResolutionData, resolutionData)) {
+ mResolutionData = resolutionData;
notifyChanged();
}
return this;
}
+ /**
+ * Removes the resolution animation from this preference.
+ *
+ * <p>Should be called after the resolution animation completes if this preference will be
+ * reused. Otherwise the resolution animation will be played everytime this preference is
+ * displayed.
+ */
+ @NonNull
+ public BannerMessagePreference clearResolutionAnimation() {
+ if (!SettingsThemeHelper.isExpressiveTheme(getContext())) {
+ return this;
+ }
+ if (mResolutionData != null) {
+ mResolutionData = null;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the attention level. This will update the color theme of the preference.
+ */
+ @NonNull
+ public BannerMessagePreference setAttentionLevel(@NonNull AttentionLevel attentionLevel) {
+ if (attentionLevel == mAttentionLevel) {
+ return this;
+ }
+
+ mAttentionLevel = attentionLevel;
+ notifyChanged();
+ return this;
+ }
+
static class ButtonInfo {
- private Button mButton;
- private CharSequence mText;
- private View.OnClickListener mListener;
+ @Nullable private Button mButton;
+ @Nullable private CharSequence mText;
+ @Nullable private View.OnClickListener mListener;
private boolean mIsVisible = true;
+ private boolean mIsEnabled = true;
@ColorInt private int mColor;
@ColorInt private int mBackgroundColor;
- private ColorStateList mStrokeColor;
+ @Nullable private ColorStateList mStrokeColor;
void setUpButton() {
+ if (mButton == null) {
+ return;
+ }
+
mButton.setText(mText);
mButton.setOnClickListener(mListener);
+ mButton.setEnabled(mIsEnabled);
MaterialButton btn = null;
if (mButton instanceof MaterialButton) {
@@ -492,11 +614,15 @@
}
static class DismissButtonInfo {
- private ImageButton mButton;
- private View.OnClickListener mListener;
+ @Nullable private ImageButton mButton;
+ @Nullable private View.OnClickListener mListener;
private boolean mIsVisible = true;
void setUpButton() {
+ if (mButton == null) {
+ return;
+ }
+
mButton.setOnClickListener(mListener);
if (shouldBeVisible()) {
mButton.setVisibility(View.VISIBLE);
diff --git a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessageView.java b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessageView.java
index ff4e79d..eabb634 100644
--- a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessageView.java
+++ b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/BannerMessageView.java
@@ -23,6 +23,7 @@
import android.view.View;
import android.widget.LinearLayout;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settingslib.widget.preference.banner.R;
@@ -34,22 +35,25 @@
* {@link BannerMessagePreference} to a {@code PreferenceScreen}.
*/
public class BannerMessageView extends LinearLayout {
- private Rect mTouchTargetForDismissButton;
+ @Nullable private Rect mTouchTargetForDismissButton;
- public BannerMessageView(Context context) {
+ public BannerMessageView(@NonNull Context context) {
super(context);
}
- public BannerMessageView(Context context,
- @Nullable AttributeSet attrs) {
+ public BannerMessageView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
- public BannerMessageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ public BannerMessageView(
+ @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
- public BannerMessageView(Context context, AttributeSet attrs, int defStyleAttr,
+ public BannerMessageView(
+ @NonNull Context context,
+ @Nullable AttributeSet attrs,
+ int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
diff --git a/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/ResolutionAnimator.kt b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/ResolutionAnimator.kt
new file mode 100644
index 0000000..fbf910a
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/src/com/android/settingslib/widget/ResolutionAnimator.kt
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget
+
+import android.graphics.drawable.Animatable2
+import android.graphics.drawable.AnimatedVectorDrawable
+import android.graphics.drawable.Drawable
+import android.os.Build
+import android.provider.DeviceConfig
+import android.transition.Fade
+import android.transition.Transition
+import android.transition.TransitionListenerAdapter
+import android.transition.TransitionManager
+import android.transition.TransitionSet
+import android.view.View
+import android.view.ViewGroup
+import android.view.animation.LinearInterpolator
+import android.widget.TextView
+import androidx.preference.PreferenceViewHolder
+import com.android.settingslib.widget.preference.banner.R
+import java.time.Duration
+
+/** Callback to communicate when a banner message resolution animation is completed. */
+fun interface ResolutionCompletedCallback {
+ fun onCompleted()
+}
+
+internal class ResolutionAnimator(
+ private val data: Data,
+ private val preferenceViewHolder: PreferenceViewHolder,
+) {
+
+ data class Data(
+ val resolutionMessage: CharSequence,
+ val resolutionCompletedCallback: ResolutionCompletedCallback,
+ )
+
+ private val defaultBannerContent: View?
+ get() = preferenceViewHolder.findView(R.id.banner_content)
+ private val resolvedTextView: TextView?
+ get() = preferenceViewHolder.findView(R.id.resolved_banner_text)
+
+ fun startResolutionAnimation() {
+ resolvedTextView?.text = data.resolutionMessage
+ resolvedTextView?.resolutionDrawable?.reset()
+
+ val transitionSet =
+ TransitionSet()
+ .setOrdering(TransitionSet.ORDERING_SEQUENTIAL)
+ .setInterpolator(linearInterpolator)
+ .addTransition(hideIssueContentTransition)
+ .addTransition(
+ showResolvedContentTransition
+ .clone()
+ .addListener(
+ object : TransitionListenerAdapter() {
+ override fun onTransitionEnd(transition: Transition) {
+ super.onTransitionEnd(transition)
+ startIssueResolvedAnimation()
+ }
+ }
+ )
+ )
+
+ preferenceViewHolder.itemView.post {
+ TransitionManager.beginDelayedTransition(
+ preferenceViewHolder.itemView as ViewGroup,
+ transitionSet,
+ )
+
+ defaultBannerContent?.visibility = View.INVISIBLE
+ resolvedTextView?.visibility = View.VISIBLE
+ }
+
+ preferenceViewHolder.itemView.addOnAttachStateChangeListener(
+ object : View.OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(v: View) {}
+
+ override fun onViewDetachedFromWindow(v: View) {
+ v.removeOnAttachStateChangeListener(this)
+ cancelAnimationsAndFinish()
+ }
+ }
+ )
+ }
+
+ private fun startIssueResolvedAnimation() {
+ val animatedDrawable = resolvedTextView?.resolutionDrawable
+
+ if (animatedDrawable == null) {
+ hideResolvedUiAndFinish()
+ return
+ }
+
+ animatedDrawable.apply {
+ clearAnimationCallbacks()
+ registerAnimationCallback(
+ object : Animatable2.AnimationCallback() {
+ override fun onAnimationEnd(drawable: Drawable) {
+ super.onAnimationEnd(drawable)
+ hideResolvedUiAndFinish()
+ }
+ }
+ )
+ start()
+ }
+ }
+
+ private fun hideResolvedUiAndFinish() {
+ val hideTransition =
+ hideResolvedContentTransition
+ .clone()
+ .setInterpolator(linearInterpolator)
+ .addListener(
+ object : TransitionListenerAdapter() {
+ override fun onTransitionEnd(transition: Transition) {
+ super.onTransitionEnd(transition)
+ data.resolutionCompletedCallback.onCompleted()
+ }
+ }
+ )
+ TransitionManager.beginDelayedTransition(
+ preferenceViewHolder.itemView as ViewGroup,
+ hideTransition,
+ )
+ resolvedTextView?.visibility = View.GONE
+ }
+
+ private fun cancelAnimationsAndFinish() {
+ TransitionManager.endTransitions(preferenceViewHolder.itemView as ViewGroup)
+
+ resolvedTextView?.visibility = View.GONE
+
+ val animatedDrawable = resolvedTextView?.resolutionDrawable
+ animatedDrawable?.clearAnimationCallbacks()
+ animatedDrawable?.stop()
+
+ data.resolutionCompletedCallback.onCompleted()
+ }
+
+ private companion object {
+ private val linearInterpolator = LinearInterpolator()
+
+ private val HIDE_ISSUE_CONTENT_TRANSITION_DURATION = Duration.ofMillis(333)
+ private val hideIssueContentTransition =
+ Fade(Fade.OUT).setDuration(HIDE_ISSUE_CONTENT_TRANSITION_DURATION.toMillis())
+
+ private val SHOW_RESOLVED_CONTENT_TRANSITION_DELAY = Duration.ofMillis(133)
+ private val SHOW_RESOLVED_CONTENT_TRANSITION_DURATION = Duration.ofMillis(250)
+ private val showResolvedContentTransition =
+ Fade(Fade.IN)
+ .setStartDelay(SHOW_RESOLVED_CONTENT_TRANSITION_DELAY.toMillis())
+ .setDuration(SHOW_RESOLVED_CONTENT_TRANSITION_DURATION.toMillis())
+
+ private val hideResolvedContentTransitionDelay
+ get() =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ Duration.ofMillis(
+ DeviceConfig.getLong(
+ "settings_ui",
+ "banner_message_pref_hide_resolved_content_delay_millis",
+ 400,
+ )
+ )
+ } else {
+ Duration.ofMillis(400)
+ }
+
+ private val HIDE_RESOLVED_UI_TRANSITION_DURATION = Duration.ofMillis(167)
+ private val hideResolvedContentTransition
+ get() =
+ Fade(Fade.OUT)
+ .setStartDelay(hideResolvedContentTransitionDelay.toMillis())
+ .setDuration(HIDE_RESOLVED_UI_TRANSITION_DURATION.toMillis())
+
+ inline fun <reified T : View> PreferenceViewHolder.findView(id: Int): T? =
+ findViewById(id) as? T
+
+ val TextView.resolutionDrawable: AnimatedVectorDrawable?
+ get() = compoundDrawables.find { it != null } as? AnimatedVectorDrawable
+ }
+}
diff --git a/packages/SettingsLib/ButtonPreference/Android.bp b/packages/SettingsLib/ButtonPreference/Android.bp
index a377f31..c8375a9 100644
--- a/packages/SettingsLib/ButtonPreference/Android.bp
+++ b/packages/SettingsLib/ButtonPreference/Android.bp
@@ -30,5 +30,6 @@
apex_available: [
"//apex_available:platform",
"com.android.healthfitness",
+ "com.android.permission",
],
}
diff --git a/packages/SettingsLib/IllustrationPreference/AndroidManifest.xml b/packages/SettingsLib/IllustrationPreference/AndroidManifest.xml
index a0d10c3..56b0515 100644
--- a/packages/SettingsLib/IllustrationPreference/AndroidManifest.xml
+++ b/packages/SettingsLib/IllustrationPreference/AndroidManifest.xml
@@ -18,6 +18,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settingslib.widget.preference.illustration">
- <uses-sdk android:minSdkVersion="28" />
+ <uses-sdk android:minSdkVersion="30" />
</manifest>
diff --git a/packages/SettingsLib/IllustrationPreference/res/values/strings.xml b/packages/SettingsLib/IllustrationPreference/res/values/strings.xml
new file mode 100644
index 0000000..3a8aaf8
--- /dev/null
+++ b/packages/SettingsLib/IllustrationPreference/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2025 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Label for an accessibility action that starts an animation [CHAR LIMIT=30] -->
+ <string name="settingslib_action_label_resume">resume</string>
+ <!-- Label for an accessibility action that stops an animation [CHAR LIMIT=30] -->
+ <string name="settingslib_action_label_pause">pause</string>
+ <!-- Label for an accessibility action that stops an animation [CHAR LIMIT=50] -->
+ <string name="settingslib_state_animation_playing">Animation playing</string>
+ <!-- Label for an accessibility action that stops an animation [CHAR LIMIT=50] -->
+ <string name="settingslib_state_animation_paused">Animation paused</string>
+</resources>
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index af40c64..e818a60 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -32,6 +32,8 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -73,6 +75,7 @@
private boolean mLottieDynamicColor;
private CharSequence mContentDescription;
private boolean mIsTablet;
+ private boolean mIsAnimatable;
private boolean mIsAnimationPaused;
/**
@@ -81,6 +84,7 @@
public interface OnBindListener {
/**
* Called when when {@link #onBindViewHolder(PreferenceViewHolder)} occurs.
+ *
* @param animationView the animation view for this preference.
*/
void onBind(LottieAnimationView animationView);
@@ -144,16 +148,6 @@
(FrameLayout) holder.findViewById(R.id.middleground_layout);
final LottieAnimationView illustrationView =
(LottieAnimationView) holder.findViewById(R.id.lottie_view);
- // Pause and resume animation
- illustrationFrame.setOnClickListener(v -> {
- mIsAnimationPaused = !mIsAnimationPaused;
- if (mIsAnimationPaused) {
- illustrationView.pauseAnimation();
- } else {
- illustrationView.resumeAnimation();
- }
- });
-
if (illustrationView != null && !TextUtils.isEmpty(mContentDescription)) {
illustrationView.setContentDescription(mContentDescription);
illustrationView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
@@ -171,12 +165,13 @@
illustrationView.setCacheComposition(mCacheComposition);
handleImageWithAnimation(illustrationView, illustrationFrame);
+ handleAnimationControl(illustrationView, illustrationFrame);
handleImageFrameMaxHeight(backgroundView, illustrationView);
if (mIsAutoScale) {
illustrationView.setScaleType(mIsAutoScale
- ? ImageView.ScaleType.CENTER_CROP
- : ImageView.ScaleType.CENTER_INSIDE);
+ ? ImageView.ScaleType.CENTER_CROP
+ : ImageView.ScaleType.CENTER_INSIDE);
}
handleMiddleGroundView(middleGroundLayout);
@@ -377,6 +372,7 @@
final Drawable drawable = illustrationView.getDrawable();
if (drawable != null) {
startAnimation(drawable);
+ mIsAnimatable = false;
}
}
@@ -386,10 +382,12 @@
final Drawable drawable = illustrationView.getDrawable();
if (drawable != null) {
startAnimation(drawable);
+ mIsAnimatable = false;
} else {
// The lottie image from the raw folder also returns null because the ImageView
// couldn't handle it now.
startLottieAnimationWith(illustrationView, mImageUri);
+ mIsAnimatable = true;
}
}
@@ -418,10 +416,12 @@
final Drawable drawable = illustrationView.getDrawable();
if (drawable != null) {
startAnimation(drawable);
+ mIsAnimatable = false;
} else {
// The lottie image from the raw folder also returns null because the ImageView
// couldn't handle it now.
startLottieAnimationWith(illustrationView, mImageResId);
+ mIsAnimatable = true;
}
}
}
@@ -459,6 +459,60 @@
((Animatable) drawable).start();
}
+ private void handleAnimationControl(LottieAnimationView illustrationView,
+ ViewGroup container) {
+ if (mIsAnimatable) {
+ // TODO(b/397340540): list out pages having illustration without a content description.
+ if (TextUtils.isEmpty(mContentDescription)) {
+ Log.w(TAG, "Illustration should have a content description. preference key = "
+ + getKey());
+ }
+ // Enable pause and resume abilities to animation only
+ container.setOnClickListener(v -> {
+ mIsAnimationPaused = !mIsAnimationPaused;
+ if (mIsAnimationPaused) {
+ illustrationView.pauseAnimation();
+ } else {
+ illustrationView.resumeAnimation();
+ }
+ updateAccessibilityAction(container);
+ });
+
+ updateAccessibilityAction(container);
+ }
+ }
+
+ private void updateAccessibilityAction(ViewGroup container) {
+ // Setting the state of animation
+ container.setStateDescription(getStateDescriptionForAnimation());
+ container.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ final AccessibilityAction clickAction = new AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CLICK,
+ getActionLabelForAnimation());
+ info.addAction(clickAction);
+ }
+ });
+ }
+
+ private String getActionLabelForAnimation() {
+ if (mIsAnimationPaused) {
+ return getContext().getString(R.string.settingslib_action_label_resume);
+ } else {
+ return getContext().getString(R.string.settingslib_action_label_pause);
+ }
+ }
+
+ private String getStateDescriptionForAnimation() {
+ if (mIsAnimationPaused) {
+ return getContext().getString(R.string.settingslib_state_animation_paused);
+ } else {
+ return getContext().getString(R.string.settingslib_state_animation_playing);
+ }
+ }
+
private static void startLottieAnimationWith(LottieAnimationView illustrationView,
Uri imageUri) {
final InputStream inputStream =
@@ -514,15 +568,20 @@
mIsAutoScale = false;
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs,
- com.airbnb.lottie.R.styleable.LottieAnimationView, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
- mImageResId = a.getResourceId(com.airbnb.lottie.R.styleable.LottieAnimationView_lottie_rawRes, 0);
+ com.airbnb.lottie.R.styleable.LottieAnimationView, /* defStyleAttr= */ 0,
+ /* defStyleRes= */ 0);
+ mImageResId = a.getResourceId(
+ com.airbnb.lottie.R.styleable.LottieAnimationView_lottie_rawRes,
+ /* defValue= */ 0);
mCacheComposition = a.getBoolean(
- com.airbnb.lottie.R.styleable.LottieAnimationView_lottie_cacheComposition, true);
+ com.airbnb.lottie.R.styleable.LottieAnimationView_lottie_cacheComposition,
+ /* defValue= */ true);
a = context.obtainStyledAttributes(attrs,
- R.styleable.IllustrationPreference, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
+ R.styleable.IllustrationPreference, /* defStyleAttr= */ 0,
+ /* defStyleRes= */ 0);
mLottieDynamicColor = a.getBoolean(R.styleable.IllustrationPreference_dynamicColor,
- false);
+ /* defValue= */ false);
a.recycle();
}
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
index dc5c9b2..b6e80c7 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
@@ -18,7 +18,7 @@
<resources>
<style name="Theme.SettingsBase_v35" parent="Theme.SettingsBase_v33" >
<item name="android:colorAccent">@color/settingslib_materialColorPrimary</item>
- <item name="android:colorBackground">@color/settingslib_materialColorSurfaceContainerLowest</item>
+ <item name="android:colorBackground">@color/settingslib_materialColorSurfaceContainer</item>
<item name="android:textColorPrimary">@color/settingslib_materialColorOnSurface</item>
<item name="android:textColorSecondary">@color/settingslib_text_color_secondary</item>
<item name="android:textColorTertiary">@color/settingslib_materialColorOutline</item>
diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
index 6a06320..a04fce7 100644
--- a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
+++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
@@ -47,7 +47,7 @@
private val mHandler = Handler(Looper.getMainLooper())
- private val syncRunnable = Runnable { updatePreferences() }
+ private val syncRunnable = Runnable { updatePreferencesList() }
init {
val context = preferenceGroup.context
@@ -64,7 +64,7 @@
true, /* resolveRefs */
)
mLegacyBackgroundRes = outValue.resourceId
- updatePreferences()
+ updatePreferencesList()
}
@SuppressLint("RestrictedApi")
@@ -82,7 +82,7 @@
updateBackground(holder, position)
}
- private fun updatePreferences() {
+ private fun updatePreferencesList() {
val oldList = ArrayList(mRoundCornerMappingList)
mRoundCornerMappingList = ArrayList()
mappingPreferenceGroup(mRoundCornerMappingList, mPreferenceGroup)
diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt
index 1776d25..1f4a48d 100644
--- a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt
+++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt
@@ -50,10 +50,6 @@
}
private fun tryInit(context: Context) {
- if (expressiveThemeState != ExpressiveThemeState.UNKNOWN) {
- return
- }
-
expressiveThemeState =
if (
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) &&
diff --git a/packages/SettingsLib/Spa/spa/Android.bp b/packages/SettingsLib/Spa/spa/Android.bp
index ac44a1b..5aeea9c 100644
--- a/packages/SettingsLib/Spa/spa/Android.bp
+++ b/packages/SettingsLib/Spa/spa/Android.bp
@@ -24,7 +24,9 @@
srcs: ["src/**/*.kt"],
use_resource_processor: true,
static_libs: [
+ "MPAndroidChart",
"SettingsLibColor",
+ "aconfig_settingstheme_exported_flags_java_lib",
"androidx.compose.animation_animation",
"androidx.compose.material3_material3",
"androidx.compose.material_material-icons-extended",
@@ -36,7 +38,6 @@
"androidx.navigation_navigation-compose",
"com.google.android.material_material",
"lottie_compose",
- "MPAndroidChart",
],
kotlincflags: [
"-Xjvm-default=all",
diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts
index 1396629..de1fa4e 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/spa/build.gradle.kts
@@ -51,6 +51,7 @@
dependencies {
api(project(":SettingsLibColor"))
+ api(project(":SettingsLib:SettingsTheme"))
api("androidx.appcompat:appcompat:1.7.0")
api("androidx.compose.material3:material3:1.4.0-alpha05")
api("androidx.compose.material:material-icons-extended")
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
index f948d51..badf7ae 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
@@ -22,6 +22,7 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import com.android.settingslib.spa.framework.util.SystemProperties
+import com.android.settingslib.widget.theme.flags.Flags
/**
* The Material 3 Theme for Settings.
@@ -42,5 +43,7 @@
}
}
-val isSpaExpressiveEnabled
- by lazy { SystemProperties.getBoolean("is_expressive_design_enabled", false) }
+val isSpaExpressiveEnabled by lazy {
+ SystemProperties.getBoolean("is_expressive_design_enabled", false) ||
+ Flags.isExpressiveDesignEnabled()
+}
diff --git a/packages/SettingsLib/Spa/tests/Android.bp b/packages/SettingsLib/Spa/tests/Android.bp
index 871449e..315b400 100644
--- a/packages/SettingsLib/Spa/tests/Android.bp
+++ b/packages/SettingsLib/Spa/tests/Android.bp
@@ -30,10 +30,14 @@
static_libs: [
"SpaLib",
"SpaLibTestUtils",
+ "aconfig_settingstheme_exported_flags_java_lib",
"androidx.compose.runtime_runtime",
"androidx.test.ext.junit",
"androidx.test.runner",
+ "flag-junit",
+ "flag-junit-base",
"mockito-target-minus-junit4",
+ "platform-test-annotations",
],
kotlincflags: ["-Xjvm-default=all"],
sdk_version: "current",
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/button/ActionButtonsTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/button/ActionButtonsTest.kt
index 8d9bac6..bab02b0 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/button/ActionButtonsTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/button/ActionButtonsTest.kt
@@ -16,6 +16,8 @@
package com.android.settingslib.spa.widget.button
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Launch
import androidx.compose.material.icons.outlined.Close
@@ -28,6 +30,7 @@
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.widget.theme.flags.Flags.FLAG_IS_EXPRESSIVE_DESIGN_ENABLED
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -37,6 +40,8 @@
class ActionButtonsTest {
@get:Rule
val composeTestRule = createComposeRule()
+ @get:Rule
+ val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@Test
fun button_displayed() {
@@ -54,6 +59,7 @@
composeTestRule.onNodeWithText("Open").assertIsDisplayed()
}
+ @RequiresFlagsDisabled(FLAG_IS_EXPRESSIVE_DESIGN_ENABLED)
@Test
fun button_clickable() {
var clicked by mutableStateOf(false)
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBarTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBarTest.kt
index 0a4f0d9..89206ba 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBarTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBarTest.kt
@@ -16,6 +16,8 @@
package com.android.settingslib.spa.widget.scaffold
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -52,6 +54,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.testutils.rootWidth
import com.android.settingslib.spa.testutils.setContentForSizeAssertions
+import com.android.settingslib.widget.theme.flags.Flags.FLAG_IS_EXPRESSIVE_DESIGN_ENABLED
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -62,6 +65,8 @@
class CustomizedAppBarTest {
@get:Rule val rule = createComposeRule()
+ @get:Rule
+ val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@Test
fun smallTopAppBar_expandsToScreen() {
@@ -97,6 +102,7 @@
assertThat(textStyle).isEqualTo(expectedTextStyle)
}
+ @RequiresFlagsDisabled(FLAG_IS_EXPRESSIVE_DESIGN_ENABLED)
@Test
fun smallTopAppBar_contentColor() {
var titleColor: Color = Color.Unspecified
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index d94450b..a029f56 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -26,14 +26,14 @@
name: "enable_le_audio_sharing"
namespace: "pixel_cross_device_control"
description: "Gates whether to enable LE audio sharing"
- bug: "323125723"
+ bug: "388674074"
}
flag {
name: "enable_le_audio_qr_code_private_broadcast_sharing"
namespace: "pixel_cross_device_control"
description: "Gates whether to enable LE audio private broadcast sharing via QR code"
- bug: "323125723"
+ bug: "388674074"
}
flag {
@@ -229,3 +229,23 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "adopt_primary_group_management_api_v2"
+ namespace: "cross_device_experiences"
+ description: "Adopt more Bluetooth LE broadcast primary group management APIs post launch"
+ bug: "381946931"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "promote_audio_sharing_for_second_auto_connected_lea_device"
+ namespace: "cross_device_experiences"
+ description: "Show audio sharing promote notification or dialog when the second lea device is auto connected"
+ bug: "395786392"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SettingsLib/res/drawable/ic_mobile_0_4_bar_error.xml b/packages/SettingsLib/res/drawable/ic_mobile_0_4_bar_error.xml
index 6015be8..aa5e9d2 100644
--- a/packages/SettingsLib/res/drawable/ic_mobile_0_4_bar_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_mobile_0_4_bar_error.xml
@@ -23,10 +23,10 @@
<clip-path
android:pathData="
M0,0
- V13.5,0
- H13.5,20
- V0,20
- H0,0
+ H16
+ V12
+ H0
+ Z
M14.999,13.5C17.761,13.5 19.999,11.261 19.999,8.5C19.999,5.739 17.761,3.5 14.999,3.5C12.238,3.5 9.999,5.739 9.999,8.5C9.999,11.261 12.238,13.5 14.999,13.5Z" />
<path
android:pathData="M1.249,7C1.939,7 2.499,7.56 2.499,8.25L2.499,10.75C2.499,11.44 1.939,12 1.249,12C0.559,12 -0.001,11.44 -0.001,10.75L-0.001,8.25C-0.001,7.56 0.559,7 1.249,7Z"
diff --git a/packages/SettingsLib/res/drawable/ic_mobile_1_4_bar_error.xml b/packages/SettingsLib/res/drawable/ic_mobile_1_4_bar_error.xml
index fb73b6b..f7bf851 100644
--- a/packages/SettingsLib/res/drawable/ic_mobile_1_4_bar_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_mobile_1_4_bar_error.xml
@@ -8,10 +8,10 @@
<clip-path
android:pathData="
M0,0
- V13.5,0
- H13.5,20
- V0,20
- H0,0
+ H16
+ V12
+ H0
+ Z
M14.999,13.5C17.761,13.5 19.999,11.261 19.999,8.5C19.999,5.739 17.761,3.5 14.999,3.5C12.238,3.5 9.999,5.739 9.999,8.5C9.999,11.261 12.238,13.5 14.999,13.5Z" />
<path
android:pathData="M1.249,7C1.939,7 2.499,7.56 2.499,8.25L2.499,10.75C2.499,11.44 1.939,12 1.249,12C0.559,12 -0.001,11.44 -0.001,10.75L-0.001,8.25C-0.001,7.56 0.559,7 1.249,7Z"
diff --git a/packages/SettingsLib/res/drawable/ic_mobile_3_4_bar_error.xml b/packages/SettingsLib/res/drawable/ic_mobile_3_4_bar_error.xml
index 7c4c1c6..016c614 100644
--- a/packages/SettingsLib/res/drawable/ic_mobile_3_4_bar_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_mobile_3_4_bar_error.xml
@@ -23,10 +23,10 @@
<clip-path
android:pathData="
M0,0
- V13.5,0
- H13.5,20
- V0,20
- H0,0
+ H16
+ V12
+ H0
+ Z
M14.999,13.5C17.761,13.5 19.999,11.261 19.999,8.5C19.999,5.739 17.761,3.5 14.999,3.5C12.238,3.5 9.999,5.739 9.999,8.5C9.999,11.261 12.238,13.5 14.999,13.5Z" />
<path
android:pathData="M1.249,7C1.939,7 2.499,7.56 2.499,8.25L2.499,10.75C2.499,11.44 1.939,12 1.249,12C0.559,12 -0.001,11.44 -0.001,10.75L-0.001,8.25C-0.001,7.56 0.559,7 1.249,7Z"
diff --git a/packages/SettingsLib/res/drawable/ic_mobile_4_4_bar_error.xml b/packages/SettingsLib/res/drawable/ic_mobile_4_4_bar_error.xml
index d23680d..b830415 100644
--- a/packages/SettingsLib/res/drawable/ic_mobile_4_4_bar_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_mobile_4_4_bar_error.xml
@@ -23,10 +23,10 @@
<clip-path
android:pathData="
M0,0
- V13.5,0
- H13.5,20
- V0,20
- H0,0
+ H16
+ V12
+ H0
+ Z
M14.999,13.5C17.761,13.5 19.999,11.261 19.999,8.5C19.999,5.739 17.761,3.5 14.999,3.5C12.238,3.5 9.999,5.739 9.999,8.5C9.999,11.261 12.238,13.5 14.999,13.5Z" />
<path
android:pathData="M1.249,7C1.939,7 2.499,7.56 2.499,8.25L2.499,10.75C2.499,11.44 1.939,12 1.249,12C0.559,12 -0.001,11.44 -0.001,10.75L-0.001,8.25C-0.001,7.56 0.559,7 1.249,7Z"
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_0.xml b/packages/SettingsLib/res/drawable/ic_wifi_0.xml
index 8ff6554..7f98457 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_0.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_0.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2023 The Android Open Source Project
+ Copyright (C) 2025 The Android Open 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,24 +14,24 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="13dp"
- android:viewportWidth="18.0"
- android:viewportHeight="13.0">
+ android:width="17.0dp"
+ android:height="12.58dp"
+ android:viewportHeight="12.0"
+ android:viewportWidth="16.21">
+
<path
- android:pathData="M0.523,3.314C0.32,3.502 0.32,3.819 0.516,4.015L1.223,4.722C1.418,4.917 1.734,4.916 1.938,4.73C5.936,1.09 12.066,1.09 16.064,4.73C16.268,4.916 16.584,4.917 16.779,4.722L17.486,4.015C17.682,3.819 17.682,3.502 17.479,3.314C12.698,-1.105 5.304,-1.105 0.523,3.314Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
<path
- android:pathData="M15.011,6.49C15.207,6.294 15.207,5.976 15.002,5.792C11.592,2.736 6.411,2.736 3,5.792C2.795,5.976 2.795,6.294 2.991,6.49L3.698,7.197C3.893,7.392 4.209,7.39 4.417,7.209C7.042,4.93 10.96,4.93 13.585,7.209C13.793,7.39 14.109,7.392 14.304,7.197L15.011,6.49Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+
<path
- android:pathData="M5.465,8.964C5.27,8.769 5.269,8.45 5.481,8.273C7.515,6.576 10.487,6.576 12.521,8.273C12.733,8.45 12.732,8.769 12.537,8.964L11.83,9.672C11.634,9.867 11.319,9.863 11.099,9.698C9.859,8.767 8.143,8.767 6.904,9.698C6.683,9.863 6.368,9.867 6.173,9.672L5.465,8.964Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
- <path
- android:pathData="M10.062,11.439C10.257,11.244 10.259,10.92 10.022,10.779C9.395,10.407 8.608,10.407 7.98,10.779C7.743,10.92 7.745,11.244 7.94,11.439L8.647,12.146C8.843,12.342 9.159,12.342 9.355,12.146L10.062,11.439Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_0_error.xml b/packages/SettingsLib/res/drawable/ic_wifi_0_error.xml
index db31b9d..3a9bba5 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_0_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_0_error.xml
@@ -1,28 +1,52 @@
+<!--
+ Copyright (C) 2025 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="17dp"
- android:height="13dp"
- android:viewportWidth="17.0"
- android:viewportHeight="13.0">
+ android:width="21.0dp"
+ android:height="15.66dp"
+ android:viewportHeight="13.5"
+ android:viewportWidth="18.1">
+
+ <group>
+ <!-- clip-out the circle which will contain the exclamation point (below this group) -->
+ <clip-path android:pathData="
+ M0,0
+ H18.1
+ V13.5
+ H0
+ Z
+ M15.109,13.5C17.871,13.5 20.109,11.261 20.109,8.5C20.109,5.739 17.871,3.5 15.109,3.5C12.348,3.5 10.109,5.739 10.109,8.5C10.109,11.261 12.348,13.5 15.109,13.5Z" />
+
+ <path
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
+ <path
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
+ <path
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+ </group>
+
<path
- android:pathData="M0.146,4.015C-0.05,3.819 -0.05,3.502 0.153,3.314C4.002,-0.244 9.545,-0.937 14.055,1.234C13.339,1.449 12.792,2.053 12.66,2.801C8.998,1.281 4.65,1.924 1.568,4.73C1.364,4.916 1.048,4.917 0.853,4.722L0.146,4.015Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M12.63,4.435C9.406,2.836 5.424,3.288 2.63,5.792C2.424,5.976 2.425,6.294 2.621,6.49L3.328,7.197C3.523,7.392 3.839,7.39 4.047,7.209C6.484,5.094 10.033,4.942 12.63,6.753V4.435Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M5.095,8.964C4.9,8.769 4.899,8.45 5.111,8.273C7.145,6.576 10.117,6.576 12.151,8.273C12.363,8.45 12.362,8.769 12.166,8.964L11.459,9.672C11.264,9.867 10.949,9.863 10.728,9.698C9.489,8.767 7.773,8.767 6.533,9.698C6.313,9.863 5.998,9.867 5.802,9.672L5.095,8.964Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M9.652,10.779C9.889,10.92 9.887,11.244 9.692,11.439L8.984,12.146C8.789,12.342 8.473,12.342 8.277,12.146L7.57,11.439C7.375,11.244 7.373,10.92 7.61,10.779C8.237,10.407 9.024,10.407 9.652,10.779Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,11.15C14.63,10.598 15.078,10.15 15.63,10.15C16.182,10.15 16.63,10.598 16.63,11.15C16.63,11.703 16.182,12.15 15.63,12.15C15.078,12.15 14.63,11.703 14.63,11.15Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,3.15C14.63,2.874 14.854,2.65 15.13,2.65H16.13C16.406,2.65 16.63,2.874 16.63,3.15V8.15C16.63,8.427 16.406,8.65 16.13,8.65H15.13C14.854,8.65 14.63,8.427 14.63,8.15V3.15Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M15.109,5C14.699,5 14.359,5.34 14.359,5.75L14.359,8.75C14.359,9.16 14.699,9.5 15.109,9.5C15.519,9.5 15.859,9.16 15.859,8.75L15.859,5.75C15.859,5.34 15.519,5 15.109,5ZM15.109,12C15.519,12 15.859,11.66 15.859,11.25C15.859,10.84 15.519,10.5 15.109,10.5C14.699,10.5 14.359,10.84 14.359,11.25C14.359,11.66 14.699,12 15.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_1.xml b/packages/SettingsLib/res/drawable/ic_wifi_1.xml
index e170f1d..9c661f4 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_1.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_1.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2023 The Android Open Source Project
+ Copyright (C) 2025 The Android Open 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,23 +14,23 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="13dp"
- android:viewportWidth="18.0"
- android:viewportHeight="13.0">
+ android:width="17.0dp"
+ android:height="12.58dp"
+ android:viewportHeight="12.0"
+ android:viewportWidth="16.21">
+
<path
- android:pathData="M0.523,3.314C0.32,3.502 0.32,3.819 0.516,4.015L1.223,4.722C1.418,4.917 1.734,4.916 1.938,4.73C5.936,1.09 12.066,1.09 16.064,4.73C16.268,4.916 16.584,4.917 16.779,4.722L17.486,4.015C17.682,3.819 17.682,3.502 17.479,3.314C12.698,-1.105 5.304,-1.105 0.523,3.314Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
<path
- android:pathData="M15.011,6.49C15.207,6.294 15.207,5.976 15.002,5.792C11.592,2.736 6.411,2.736 3,5.792C2.795,5.976 2.795,6.294 2.991,6.49L3.698,7.197C3.893,7.392 4.209,7.39 4.417,7.209C7.042,4.93 10.96,4.93 13.585,7.209C13.793,7.39 14.109,7.392 14.304,7.197L15.011,6.49Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+
<path
- android:pathData="M5.465,8.964C5.27,8.769 5.269,8.45 5.481,8.273C7.515,6.576 10.487,6.576 12.521,8.273C12.733,8.45 12.732,8.769 12.537,8.964L11.83,9.672C11.634,9.867 11.319,9.863 11.099,9.698C9.859,8.767 8.143,8.767 6.904,9.698C6.683,9.863 6.368,9.867 6.173,9.672L5.465,8.964Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
- <path
- android:pathData="M10.062,11.439C10.257,11.244 10.259,10.92 10.022,10.779C9.395,10.407 8.608,10.407 7.98,10.779C7.743,10.92 7.745,11.244 7.94,11.439L8.647,12.146C8.843,12.342 9.159,12.342 9.355,12.146L10.062,11.439Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_1_error.xml b/packages/SettingsLib/res/drawable/ic_wifi_1_error.xml
index a4d6a5c..32a69f5 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_1_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_1_error.xml
@@ -1,27 +1,51 @@
+<!--
+ Copyright (C) 2025 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="17dp"
- android:height="13dp"
- android:viewportWidth="17.0"
- android:viewportHeight="13.0">
+ android:width="21.0dp"
+ android:height="15.66dp"
+ android:viewportHeight="13.5"
+ android:viewportWidth="18.1">
+
+ <group>
+ <!-- clip-out the circle which will contain the exclamation point (below this group) -->
+ <clip-path android:pathData="
+ M0,0
+ H18.1
+ V13.5
+ H0
+ Z
+ M15.109,13.5C17.871,13.5 20.109,11.261 20.109,8.5C20.109,5.739 17.871,3.5 15.109,3.5C12.348,3.5 10.109,5.739 10.109,8.5C10.109,11.261 12.348,13.5 15.109,13.5Z" />
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
+ <path
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
+ <path
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+ </group>
+
<path
- android:pathData="M0.146,4.015C-0.05,3.819 -0.05,3.502 0.153,3.314C4.002,-0.244 9.545,-0.937 14.055,1.234C13.339,1.449 12.792,2.053 12.66,2.801C8.998,1.281 4.65,1.924 1.568,4.73C1.364,4.916 1.048,4.917 0.853,4.722L0.146,4.015Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M12.63,4.435C9.406,2.836 5.424,3.288 2.63,5.792C2.424,5.976 2.425,6.294 2.621,6.49L3.328,7.197C3.523,7.392 3.839,7.39 4.047,7.209C6.484,5.094 10.033,4.942 12.63,6.753V4.435Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M5.095,8.964C4.9,8.769 4.899,8.45 5.111,8.273C7.145,6.576 10.117,6.576 12.151,8.273C12.363,8.45 12.362,8.769 12.166,8.964L11.459,9.672C11.264,9.867 10.949,9.863 10.728,9.698C9.489,8.767 7.773,8.767 6.533,9.698C6.313,9.863 5.998,9.867 5.802,9.672L5.095,8.964Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M9.652,10.779C9.889,10.92 9.887,11.244 9.692,11.439L8.984,12.146C8.789,12.342 8.473,12.342 8.277,12.146L7.57,11.439C7.375,11.244 7.373,10.92 7.61,10.779C8.237,10.407 9.024,10.407 9.652,10.779Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,11.15C14.63,10.598 15.078,10.15 15.63,10.15C16.182,10.15 16.63,10.598 16.63,11.15C16.63,11.703 16.182,12.15 15.63,12.15C15.078,12.15 14.63,11.703 14.63,11.15Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,3.15C14.63,2.874 14.854,2.65 15.13,2.65H16.13C16.406,2.65 16.63,2.874 16.63,3.15V8.15C16.63,8.427 16.406,8.65 16.13,8.65H15.13C14.854,8.65 14.63,8.427 14.63,8.15V3.15Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M15.109,5C14.699,5 14.359,5.34 14.359,5.75L14.359,8.75C14.359,9.16 14.699,9.5 15.109,9.5C15.519,9.5 15.859,9.16 15.859,8.75L15.859,5.75C15.859,5.34 15.519,5 15.109,5ZM15.109,12C15.519,12 15.859,11.66 15.859,11.25C15.859,10.84 15.519,10.5 15.109,10.5C14.699,10.5 14.359,10.84 14.359,11.25C14.359,11.66 14.699,12 15.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_2.xml b/packages/SettingsLib/res/drawable/ic_wifi_2.xml
index fc62267..02c14e1 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_2.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_2.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2023 The Android Open Source Project
+ Copyright (C) 2025 The Android Open 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,22 +14,22 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="13dp"
- android:viewportWidth="18.0"
- android:viewportHeight="13.0">
+ android:width="17.0dp"
+ android:height="12.58dp"
+ android:viewportHeight="12.0"
+ android:viewportWidth="16.21">
+
<path
- android:pathData="M0.523,3.314C0.32,3.502 0.32,3.819 0.516,4.015L1.223,4.722C1.418,4.917 1.734,4.916 1.938,4.73C5.936,1.09 12.066,1.09 16.064,4.73C16.268,4.916 16.584,4.917 16.779,4.722L17.486,4.015C17.682,3.819 17.682,3.502 17.479,3.314C12.698,-1.105 5.304,-1.105 0.523,3.314Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
<path
- android:pathData="M15.011,6.49C15.207,6.294 15.207,5.976 15.002,5.792C11.592,2.736 6.411,2.736 3,5.792C2.795,5.976 2.795,6.294 2.991,6.49L3.698,7.197C3.893,7.392 4.209,7.39 4.417,7.209C7.042,4.93 10.96,4.93 13.585,7.209C13.793,7.39 14.109,7.392 14.304,7.197L15.011,6.49Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+
<path
- android:pathData="M5.465,8.964C5.27,8.769 5.269,8.45 5.481,8.273C7.515,6.576 10.487,6.576 12.521,8.273C12.733,8.45 12.732,8.769 12.537,8.964L11.83,9.672C11.634,9.867 11.319,9.863 11.099,9.698C9.859,8.767 8.143,8.767 6.904,9.698C6.683,9.863 6.368,9.867 6.173,9.672L5.465,8.964Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M10.062,11.439C10.257,11.244 10.259,10.92 10.022,10.779C9.395,10.407 8.608,10.407 7.98,10.779C7.743,10.92 7.745,11.244 7.94,11.439L8.647,12.146C8.843,12.342 9.159,12.342 9.355,12.146L10.062,11.439Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_2_error.xml b/packages/SettingsLib/res/drawable/ic_wifi_2_error.xml
index 65f40ef..da0aa12 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_2_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_2_error.xml
@@ -1,26 +1,50 @@
+<!--
+ Copyright (C) 2025 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="17dp"
- android:height="13dp"
- android:viewportWidth="17.0"
- android:viewportHeight="13.0">
+ android:width="21.0dp"
+ android:height="15.66dp"
+ android:viewportHeight="13.5"
+ android:viewportWidth="18.1">
+
+ <group>
+ <!-- clip-out the circle which will contain the exclamation point (below this group) -->
+ <clip-path android:pathData="
+ M0,0
+ H18.1
+ V13.5
+ H0
+ Z
+ M15.109,13.5C17.871,13.5 20.109,11.261 20.109,8.5C20.109,5.739 17.871,3.5 15.109,3.5C12.348,3.5 10.109,5.739 10.109,8.5C10.109,11.261 12.348,13.5 15.109,13.5Z" />
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
+ <path
+ android:fillAlpha="0.45"
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+ </group>
+
<path
- android:pathData="M0.146,4.015C-0.05,3.819 -0.05,3.502 0.153,3.314C4.002,-0.244 9.545,-0.937 14.055,1.234C13.339,1.449 12.792,2.053 12.66,2.801C8.998,1.281 4.65,1.924 1.568,4.73C1.364,4.916 1.048,4.917 0.853,4.722L0.146,4.015Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M12.63,4.435C9.406,2.836 5.424,3.288 2.63,5.792C2.424,5.976 2.425,6.294 2.621,6.49L3.328,7.197C3.523,7.392 3.839,7.39 4.047,7.209C6.484,5.094 10.033,4.942 12.63,6.753V4.435Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M5.095,8.964C4.9,8.769 4.899,8.45 5.111,8.273C7.145,6.576 10.117,6.576 12.151,8.273C12.363,8.45 12.362,8.769 12.166,8.964L11.459,9.672C11.264,9.867 10.949,9.863 10.728,9.698C9.489,8.767 7.773,8.767 6.533,9.698C6.313,9.863 5.998,9.867 5.802,9.672L5.095,8.964Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M9.652,10.779C9.889,10.92 9.887,11.244 9.692,11.439L8.984,12.146C8.789,12.342 8.473,12.342 8.277,12.146L7.57,11.439C7.375,11.244 7.373,10.92 7.61,10.779C8.237,10.407 9.024,10.407 9.652,10.779Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,11.15C14.63,10.598 15.078,10.15 15.63,10.15C16.182,10.15 16.63,10.598 16.63,11.15C16.63,11.703 16.182,12.15 15.63,12.15C15.078,12.15 14.63,11.703 14.63,11.15Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,3.15C14.63,2.874 14.854,2.65 15.13,2.65H16.13C16.406,2.65 16.63,2.874 16.63,3.15V8.15C16.63,8.427 16.406,8.65 16.13,8.65H15.13C14.854,8.65 14.63,8.427 14.63,8.15V3.15Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M15.109,5C14.699,5 14.359,5.34 14.359,5.75L14.359,8.75C14.359,9.16 14.699,9.5 15.109,9.5C15.519,9.5 15.859,9.16 15.859,8.75L15.859,5.75C15.859,5.34 15.519,5 15.109,5ZM15.109,12C15.519,12 15.859,11.66 15.859,11.25C15.859,10.84 15.519,10.5 15.109,10.5C14.699,10.5 14.359,10.84 14.359,11.25C14.359,11.66 14.699,12 15.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_3.xml b/packages/SettingsLib/res/drawable/ic_wifi_3.xml
index 9079daf..6b183af 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_3.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_3.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2023 The Android Open Source Project
+ Copyright (C) 2025 The Android Open 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,21 +14,21 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="13dp"
- android:viewportWidth="18.0"
- android:viewportHeight="13.0">
+ android:width="17.0dp"
+ android:height="12.58dp"
+ android:viewportHeight="12.0"
+ android:viewportWidth="16.21">
+
<path
- android:pathData="M0.523,3.314C0.32,3.502 0.32,3.819 0.516,4.015L1.223,4.722C1.418,4.917 1.734,4.916 1.938,4.73C5.936,1.09 12.066,1.09 16.064,4.73C16.268,4.916 16.584,4.917 16.779,4.722L17.486,4.015C17.682,3.819 17.682,3.502 17.479,3.314C12.698,-1.105 5.304,-1.105 0.523,3.314Z"
- android:fillAlpha="0.24"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
<path
- android:pathData="M15.011,6.49C15.207,6.294 15.207,5.976 15.002,5.792C11.592,2.736 6.411,2.736 3,5.792C2.795,5.976 2.795,6.294 2.991,6.49L3.698,7.197C3.893,7.392 4.209,7.39 4.417,7.209C7.042,4.93 10.96,4.93 13.585,7.209C13.793,7.39 14.109,7.392 14.304,7.197L15.011,6.49Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+
<path
- android:pathData="M5.465,8.964C5.27,8.769 5.269,8.45 5.481,8.273C7.515,6.576 10.487,6.576 12.521,8.273C12.733,8.45 12.732,8.769 12.537,8.964L11.83,9.672C11.634,9.867 11.319,9.863 11.099,9.698C9.859,8.767 8.143,8.767 6.904,9.698C6.683,9.863 6.368,9.867 6.173,9.672L5.465,8.964Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M10.062,11.439C10.257,11.244 10.259,10.92 10.022,10.779C9.395,10.407 8.608,10.407 7.98,10.779C7.743,10.92 7.745,11.244 7.94,11.439L8.647,12.146C8.843,12.342 9.159,12.342 9.355,12.146L10.062,11.439Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_3_error.xml b/packages/SettingsLib/res/drawable/ic_wifi_3_error.xml
index 940781b..c30affa 100644
--- a/packages/SettingsLib/res/drawable/ic_wifi_3_error.xml
+++ b/packages/SettingsLib/res/drawable/ic_wifi_3_error.xml
@@ -1,25 +1,49 @@
+<!--
+ Copyright (C) 2025 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="17dp"
- android:height="13dp"
- android:viewportWidth="17.0"
- android:viewportHeight="13.0">
+ android:width="21.0dp"
+ android:height="15.66dp"
+ android:viewportHeight="13.5"
+ android:viewportWidth="18.1">
+
+ <group>
+ <!-- clip-out the circle which will contain the exclamation point (below this group) -->
+ <clip-path android:pathData="
+ M0,0
+ H18.1
+ V13.5
+ H0
+ Z
+ M15.109,13.5C17.871,13.5 20.109,11.261 20.109,8.5C20.109,5.739 17.871,3.5 15.109,3.5C12.348,3.5 10.109,5.739 10.109,8.5C10.109,11.261 12.348,13.5 15.109,13.5Z" />
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M8.109,12C8.938,12 9.609,11.328 9.609,10.5C9.609,9.672 8.938,9 8.109,9C7.281,9 6.609,9.672 6.609,10.5C6.609,11.328 7.281,12 8.109,12Z" />
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M12.659,7.45C13.199,6.91 13.149,6.01 12.479,5.64C11.179,4.92 9.689,4.51 8.109,4.51C6.529,4.51 5.029,4.92 3.739,5.64C3.069,6.01 3.019,6.91 3.559,7.45C3.999,7.89 4.699,7.94 5.259,7.66C6.119,7.24 7.089,7 8.109,7C9.129,7 10.099,7.24 10.959,7.66C11.519,7.94 12.219,7.89 12.659,7.45Z" />
+
+ <path
+ android:fillColor="#000"
+ android:pathData="M15.85,4.26C16.36,3.75 16.34,2.91 15.76,2.49C13.61,0.93 10.97,0 8.11,0C5.25,0 2.61,0.92 0.46,2.49C-0.12,2.91 -0.14,3.75 0.37,4.26C0.84,4.73 1.59,4.75 2.13,4.37C3.83,3.19 5.89,2.5 8.11,2.5C10.33,2.5 12.39,3.19 14.09,4.37C14.63,4.75 15.38,4.73 15.85,4.26Z" />
+ </group>
+
<path
- android:pathData="M0.146,4.015C-0.05,3.819 -0.05,3.502 0.153,3.314C4.002,-0.244 9.545,-0.937 14.055,1.234C13.339,1.449 12.792,2.053 12.66,2.801C8.998,1.281 4.65,1.924 1.568,4.73C1.364,4.916 1.048,4.917 0.853,4.722L0.146,4.015Z"
- android:fillAlpha="0.3"
- android:fillColor="#000"/>
- <path
- android:pathData="M12.63,4.435C9.406,2.836 5.424,3.288 2.63,5.792C2.424,5.976 2.425,6.294 2.621,6.49L3.328,7.197C3.523,7.392 3.839,7.39 4.047,7.209C6.484,5.094 10.033,4.942 12.63,6.753V4.435Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M5.095,8.964C4.9,8.769 4.899,8.45 5.111,8.273C7.145,6.576 10.117,6.576 12.151,8.273C12.363,8.45 12.362,8.769 12.166,8.964L11.459,9.672C11.264,9.867 10.949,9.863 10.728,9.698C9.489,8.767 7.773,8.767 6.533,9.698C6.313,9.863 5.998,9.867 5.802,9.672L5.095,8.964Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M9.652,10.779C9.889,10.92 9.887,11.244 9.692,11.439L8.984,12.146C8.789,12.342 8.473,12.342 8.277,12.146L7.57,11.439C7.375,11.244 7.373,10.92 7.61,10.779C8.237,10.407 9.024,10.407 9.652,10.779Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,11.15C14.63,10.598 15.078,10.15 15.63,10.15C16.182,10.15 16.63,10.598 16.63,11.15C16.63,11.703 16.182,12.15 15.63,12.15C15.078,12.15 14.63,11.703 14.63,11.15Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,3.15C14.63,2.874 14.854,2.65 15.13,2.65H16.13C16.406,2.65 16.63,2.874 16.63,3.15V8.15C16.63,8.427 16.406,8.65 16.13,8.65H15.13C14.854,8.65 14.63,8.427 14.63,8.15V3.15Z"
- android:fillColor="#000"/>
+ android:fillColor="#000"
+ android:pathData="M15.109,5C14.699,5 14.359,5.34 14.359,5.75L14.359,8.75C14.359,9.16 14.699,9.5 15.109,9.5C15.519,9.5 15.859,9.16 15.859,8.75L15.859,5.75C15.859,5.34 15.519,5 15.109,5ZM15.109,12C15.519,12 15.859,11.66 15.859,11.25C15.859,10.84 15.519,10.5 15.109,10.5C14.699,10.5 14.359,10.84 14.359,11.25C14.359,11.66 14.699,12 15.109,12Z" />
+
</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_4.xml b/packages/SettingsLib/res/drawable/ic_wifi_4.xml
deleted file mode 100644
index 6185e4a..0000000
--- a/packages/SettingsLib/res/drawable/ic_wifi_4.xml
+++ /dev/null
@@ -1,33 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="13dp"
- android:viewportWidth="18.0"
- android:viewportHeight="13.0">
- <path
- android:pathData="M0.523,3.314C0.32,3.502 0.32,3.819 0.516,4.015L1.223,4.722C1.418,4.917 1.734,4.916 1.938,4.73C5.936,1.09 12.066,1.09 16.064,4.73C16.268,4.916 16.584,4.917 16.779,4.722L17.486,4.015C17.682,3.819 17.682,3.502 17.479,3.314C12.698,-1.105 5.304,-1.105 0.523,3.314Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M15.011,6.49C15.207,6.294 15.207,5.976 15.002,5.792C11.592,2.736 6.411,2.736 3,5.792C2.795,5.976 2.795,6.294 2.991,6.49L3.698,7.197C3.893,7.392 4.209,7.39 4.417,7.209C7.042,4.93 10.96,4.93 13.585,7.209C13.793,7.39 14.109,7.392 14.304,7.197L15.011,6.49Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M5.465,8.964C5.27,8.769 5.269,8.45 5.481,8.273C7.515,6.576 10.487,6.576 12.521,8.273C12.733,8.45 12.732,8.769 12.537,8.964L11.83,9.672C11.634,9.867 11.319,9.863 11.099,9.698C9.859,8.767 8.143,8.767 6.904,9.698C6.683,9.863 6.368,9.867 6.173,9.672L5.465,8.964Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M10.062,11.439C10.257,11.244 10.259,10.92 10.022,10.779C9.395,10.407 8.608,10.407 7.98,10.779C7.743,10.92 7.745,11.244 7.94,11.439L8.647,12.146C8.843,12.342 9.159,12.342 9.355,12.146L10.062,11.439Z"
- android:fillColor="#000"/>
-</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_wifi_4_error.xml b/packages/SettingsLib/res/drawable/ic_wifi_4_error.xml
deleted file mode 100644
index 715aaa0..0000000
--- a/packages/SettingsLib/res/drawable/ic_wifi_4_error.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="17dp"
- android:height="13dp"
- android:viewportWidth="17.0"
- android:viewportHeight="13.0">
- <path
- android:pathData="M0.146,4.015C-0.05,3.819 -0.05,3.502 0.153,3.314C4.002,-0.244 9.545,-0.937 14.055,1.234C13.339,1.449 12.792,2.053 12.66,2.801C8.998,1.281 4.65,1.924 1.568,4.73C1.364,4.916 1.048,4.917 0.853,4.722L0.146,4.015Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M12.63,4.435C9.406,2.836 5.424,3.288 2.63,5.792C2.424,5.976 2.425,6.294 2.621,6.49L3.328,7.197C3.523,7.392 3.839,7.39 4.047,7.209C6.484,5.094 10.033,4.942 12.63,6.753V4.435Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M5.095,8.964C4.9,8.769 4.899,8.45 5.111,8.273C7.145,6.576 10.117,6.576 12.151,8.273C12.363,8.45 12.362,8.769 12.166,8.964L11.459,9.672C11.264,9.867 10.949,9.863 10.728,9.698C9.489,8.767 7.773,8.767 6.533,9.698C6.313,9.863 5.998,9.867 5.802,9.672L5.095,8.964Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M9.652,10.779C9.889,10.92 9.887,11.244 9.692,11.439L8.984,12.146C8.789,12.342 8.473,12.342 8.277,12.146L7.57,11.439C7.375,11.244 7.373,10.92 7.61,10.779C8.237,10.407 9.024,10.407 9.652,10.779Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,11.15C14.63,10.598 15.078,10.15 15.63,10.15C16.182,10.15 16.63,10.598 16.63,11.15C16.63,11.703 16.182,12.15 15.63,12.15C15.078,12.15 14.63,11.703 14.63,11.15Z"
- android:fillColor="#000"/>
- <path
- android:pathData="M14.63,3.15C14.63,2.874 14.854,2.65 15.13,2.65H16.13C16.406,2.65 16.63,2.874 16.63,3.15V8.15C16.63,8.427 16.406,8.65 16.13,8.65H15.13C14.854,8.65 14.63,8.427 14.63,8.15V3.15Z"
- android:fillColor="#000"/>
-</vector>
diff --git a/core/res/res/values-w204dp-round-watch/dimens_watch.xml b/packages/SettingsLib/res/layout/activity_create_new_user.xml
similarity index 67%
rename from core/res/res/values-w204dp-round-watch/dimens_watch.xml
rename to packages/SettingsLib/res/layout/activity_create_new_user.xml
index 3509474..7453b53 100644
--- a/core/res/res/values-w204dp-round-watch/dimens_watch.xml
+++ b/packages/SettingsLib/res/layout/activity_create_new_user.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2025 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<resources>
- <!-- watch's indeterminate progress bar dimens based on the current screen size -->
- <dimen name="loader_horizontal_min_width_watch">70dp</dimen>
- <dimen name="loader_horizontal_min_height_watch">15dp</dimen>
-</resources>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/transparent"
+ android:orientation="vertical">
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index c4ba7eb..89648d1 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Slegs toestelskerm (verstek)"</item>
+ <item msgid="9161645858025071955">"Eksterne skerm"</item>
+ <item msgid="23651860565814477">"Laaste interaksie met statusbalk"</item>
+ <item msgid="7521112827893653392">"Fokusgebaseer"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Wys skakering net op toestelskerm"</item>
+ <item msgid="1955398604822147783">"Wys skakering op enkele eksterne skerm"</item>
+ <item msgid="391477482416751568">"Wys skakering op die skerm waarop die statusbalk die laaste interaksie gehad het"</item>
+ <item msgid="1746820128097981528">"Wys skakering op die laaste gefokusde skerm"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 3a7e452..dbc4e5a 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Kon nie omgewing opdateer nie"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktief (net media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiewe (net media). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Gekoppel (steun oudiodeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Gekoppel (steun oudiodeling). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Gekoppel (steun oudiodeling). Links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Gekoppel (steun oudiodeling). Regs: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Gekoppel (steun oudiodeling)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktief (net media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Steun oudiodeling"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktief (net media), net linkerkant"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktief (net media), net regterkant"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktief (net media), linker- en regterkant"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardeware-versnelde lewering"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitering"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strengmodus geaktiveer"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Flits skerm as apps lang bewerkings uitvoer op die hoofdraad"</string>
<string name="pointer_location" msgid="7516929526199520173">"Wyserligging"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Stel WebView-implementering"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Hierdie keuse is nie meer geldig nie. Probeer weer."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Fotokleurmodus"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Gebruik sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Gedeaktiveer"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index a151f83..4ae2d99b 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"የመሣሪያ ማሳያ ብቻ (ነባሪ)"</item>
+ <item msgid="9161645858025071955">"ውጫዊ ማሳያ"</item>
+ <item msgid="23651860565814477">"የቅርብ ጊዜ የሁኔታ አሞሌ ንክኪ"</item>
+ <item msgid="7521112827893653392">"ትኩረት ላይ የተመሠረተ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"በመሣሪያ ማሳያ ላይ ብቻ ጥላ አሳይ"</item>
+ <item msgid="1955398604822147783">"በነጠላ ውጫዊ ማሳያ ላይ ጥላ አሳይ"</item>
+ <item msgid="391477482416751568">"ለመጨረሻ ጊዜ በሁኔታ አሞሌው መስተጋብር የተፈጠረበት ማሳያ ላይ ጥላ አሳይ"</item>
+ <item msgid="1746820128097981528">"ለመጨረሻ ጊዜ ትኩረት በተደረገበት ማሳያ ላይ ጥላ አሳይ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 25e9c5e..bfe6006 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"በዙሪያ ያሉትን ማዘመን አልተቻለም"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ገቢር (ሚዲያ ብቻ)። <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ገቢር (ሚዲያ ብቻ)። ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ።"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)፣ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል) ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ።"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)። ግራ፦<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)። ቀኝ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ገቢር (ሚዲያ ብቻ)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ድምፅ ማጋራትን ይደግፋል"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ገቢር (ሚዲያ ብቻ)፣ ግራ ብቻ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ገቢር (ሚዲያ ብቻ) ቀኝ ብቻ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ገቢር (ሚዲያ ብቻ)፣ ግራ እና ቀኝ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"የተፋጠነ የሃርድዌር አሰጣጥ"</string>
<string name="media_category" msgid="8122076702526144053">"ማህደረመረጃ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"ቁጥጥር"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"ጥብቅ ሁነታ ነቅቷል"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"መተግበሪያዎች ረጅም ክንውኖች ወደ ዋና ክሮች ሲያካሂዱ ማያላይ ብልጭ አድርግ።"</string>
<string name="pointer_location" msgid="7516929526199520173">"የአመልካች ሥፍራ"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"የWebView ትግበራ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"የWebView ትግበራን ያዘጋጁ"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ይህ ምርጫ ከአሁን በኋላ የሚሰራ አይደለም። እንደገና ይሞክሩ።"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"የስዕል ቀለም ሁነታ"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ይጠቀሙ"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"ተሰናክሏል"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index ebdb0c7..e3c36b8 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"شاشة الجهاز فقط (الإعداد التلقائي)"</item>
+ <item msgid="9161645858025071955">"الشاشة الخارجية"</item>
+ <item msgid="23651860565814477">"آخر لمسة على شريط الحالة"</item>
+ <item msgid="7521112827893653392">"على الشاشة التي يتم التركيز عليها"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"عرض الظل على شاشة الجهاز فقط"</item>
+ <item msgid="1955398604822147783">"عرض الظل على شاشة خارجية واحدة"</item>
+ <item msgid="391477482416751568">"عرض الظل على آخر شاشة تم التفاعل مع شريط الحالة فيها"</item>
+ <item msgid="1746820128097981528">"عرض الظل على آخر شاشة تم التركيز عليها"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 8956c44..64a021d 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"تعذَّر تعديل حالة الأصوات المحيطة"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"البلوتوث نشِط (للوسائط فقط). مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"البلوتوث نشِط (للوسائط فقط)، مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة). مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة). مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة). مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة). مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"البلوتوث مفعَّل (للوسائط فقط)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"تتوفّر ميزة \"مشاركة الصوت\""</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"السماعة اليسرى فقط مشغَّلة (للوسائط فقط)"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"السماعة اليمنى فقط مشغَّلة (للوسائط فقط)"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"السماعتان اليسرى واليمنى مشغَّلتان (للوسائط فقط)"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"عرض تسارع الأجهزة"</string>
<string name="media_category" msgid="8122076702526144053">"الوسائط"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"المراقبة"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"تفعيل الوضع المتشدد"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"وميض الشاشة عند إجراء التطبيقات عمليات طويلة في سلسلة المحادثات الرئيسية"</string>
<string name="pointer_location" msgid="7516929526199520173">"موقع المؤشر"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"تطبيق WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"تعيين تطبيق WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"لم يعد هذا الاختيار صالحًا. أعد المحاولة."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"نمط لون الصورة"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"استخدام sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"غير مفعّل"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index bfacbb2..82ee7f3 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"আশ-পাশ আপডে’ট কৰিব পৰা নগ’ল"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)। বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী।"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে)। বাকী আছে: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে)। সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), কেৱল বাওঁ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), কেৱল সোঁ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), বাওঁ আৰু সোঁ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"হাৰ্ডৱেৰৰদ্বাৰা ত্বৰিত ৰেণ্ডাৰিং"</string>
<string name="media_category" msgid="8122076702526144053">"মিডিয়া"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"নিৰীক্ষণ কৰি থকা হৈছে"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"কঠোৰ ম’ড সক্ষম কৰা হৈছে"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"যেতিয়া এপ্সমূহে মুখ্য থ্ৰেডত দীঘলীয়া কাৰ্যকলাপ চলায়, তেতিয়া স্ক্ৰীন ফ্লাশ্ব কৰক"</string>
<string name="pointer_location" msgid="7516929526199520173">"পইণ্টাৰৰ অৱস্থান"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"ৱেবভিউ প্ৰয়োগ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"ৱেবভিউ প্ৰয়োগ ছেট কৰক"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"বাছনিটো এতিয়া আৰু মান্য় নহয়। আকৌ চেষ্টা কৰক।"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"চিত্ৰৰ ৰং ম’ড"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"এছআৰজিবি ব্যৱহাৰ কৰক"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"নিষ্ক্ৰিয় হৈ আছে"</string>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 52cf498..3b02070 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Yalnız cihaz displeyi (defolt)"</item>
+ <item msgid="9161645858025071955">"Xarici displey"</item>
+ <item msgid="23651860565814477">"Ən son status paneli toxunuşu"</item>
+ <item msgid="7521112827893653392">"Fokus əsaslı"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Kölgəni yalnız cihaz displeyində göstərin"</item>
+ <item msgid="1955398604822147783">"Tək xarici displeydə kölgə göstərilsin"</item>
+ <item msgid="391477482416751568">"Ən son status paneli ilə interaksiya edilmiş displeydə kölgə göstərilsin"</item>
+ <item msgid="1746820128097981528">"Son fokuslanmış displeydə kölgə göstərilsin"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 9013fb5..aa93964 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ətraf mühit güncəllənmədi"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (yalnız media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (yalnız media). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Qoşulub (audio paylaşma dəstəklənir). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Qoşulub (audio paylaşma dəstəklənir). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Qoşulub (audio paylaşma dəstəklənir). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Qoşulub (audio paylaşma dəstəklənir). Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Qoşulub (audio paylaşma dəstəklənir)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (yalnız media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio paylaşma dəstəklənir"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (yalnız media), yalnız sol"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (yalnız media), yalnız sağ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (yalnız media), sol və sağ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Renderinq aparat sürətlənməsi"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitorinq"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Ciddi rejim"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Uzun əməliyyatlar ərzində ekran işıqlandırılsın"</string>
<string name="pointer_location" msgid="7516929526199520173">"Kursor yeri"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView servisi"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView servisini ayarlayın"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Bu seçim artıq etibarlı deyil. Yenidən cəhd edin."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Şəkil rəng rejimi"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB istifadə edin"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Deaktiv"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 7a00b96..7f60500 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ažuriranje okruženja nije uspelo"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo za medije). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo za medije). Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava deljenje zvuka), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Povezano (podržava deljenje zvuka), levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Povezano (podržava deljenje zvuka). Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Povezano (podržava deljenje zvuka). Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Povezano (podržava deljenje zvuka)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivan (samo za medije)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava deljenje zvuka"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivan (samo za medije), samo levo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivan (samo za medije), samo desno"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivan (samo za medije), levo i desno"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardverski ubrzano prikazivanje"</string>
<string name="media_category" msgid="8122076702526144053">"Mediji"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Nadgledanje"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Omogućen je strogi režim"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Ekran treperi kada aplikacije obavljaju duge operacije na glavnoj niti"</string>
<string name="pointer_location" msgid="7516929526199520173">"Lokacija pokazivača"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Primena WebView-a"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Podesite primenu WebView-a"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ovaj izbor više nije važeći. Probajte ponovo."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Režim boja slika"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Koristi sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Onemogućeno je"</string>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 48c3627..e33a71e 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Толькі дысплэй прылады (стандартна)"</item>
+ <item msgid="9161645858025071955">"Знешні дысплэй"</item>
+ <item msgid="23651860565814477">"Апошняе націсканне на панэль стану"</item>
+ <item msgid="7521112827893653392">"У залежнасці ад выкарыстання"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Паказваць шчыток толькі на дысплэі прылады"</item>
+ <item msgid="1955398604822147783">"Паказваць шчыток апавяшчэнняў на адным знешнім дысплэі"</item>
+ <item msgid="391477482416751568">"Паказваць шчыток апавяшчэнняў на дысплэі, на якім адбывалася апошняе ўзаемадзеянне з панэллю стану"</item>
+ <item msgid="1746820128097981528">"Паказваць шчыток апавяшчэнняў на дысплэі, які выкарыстоўваўся апошнім"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 0ad8ac7..50de924 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не ўдалося абнавіць стан навакольных гукаў"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Выкарыстоўваецца (толькі для мультымедыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Выкарыстоўваецца (толькі для мультымедыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (левы навушнік)."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (правы навушнік)."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Падключана (падтрымліваецца абагульванне аўдыя)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Выкарыстоўваецца (толькі для мультымедыя)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Падтрымліваецца абагульванне аўдыя"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Выкарыстоўваецца (толькі для мультымедыя), толькі левы навушнік"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Выкарыстоўваецца (толькі для мультымедыя), толькі правы навушнік"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Выкарыстоўваецца (толькі для мультымедыя), левы і правы навушнікі"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Апаратнае паскарэнне рэндэрынгу"</string>
<string name="media_category" msgid="8122076702526144053">"Медыя"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Маніторынг"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Уключаны строгі рэжым"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Падсвечваць экран падчас доўгіх аперацый"</string>
<string name="pointer_location" msgid="7516929526199520173">"Пазіцыя ўказальніка"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Рэалізацыя WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Наладзіць рэалізацыю WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Гэты варыянт больш не даступны. Паспрабуйце яшчэ раз."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Каляровы рэжым выявы"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Выкарыстоўваць sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Выключана"</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 21dfa06..fabd7d9 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Само на екрана на устройството (по подразбиране)"</item>
+ <item msgid="9161645858025071955">"Външен екран"</item>
+ <item msgid="23651860565814477">"Последно докосване на лентата на състоянието"</item>
+ <item msgid="7521112827893653392">"Въз основа на фокуса"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Показване на падащия панел само на екрана на устройството"</item>
+ <item msgid="1955398604822147783">"Показване на падащия панел на един външен екран"</item>
+ <item msgid="391477482416751568">"Показване на падащия панел на екрана, с чиято лента на състоянието е взаимодействано последно"</item>
+ <item msgid="1746820128097981528">"Показване на падащия панел на екрана, върху който последно е бил поставен фокусът"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 8a87e57..c3c1783 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Данните за околните звуци не бяха актуализирани"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само за мултимедия). Батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само за мултимедия). Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Свързано (поддържа споделяне на звука). Батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Свързано (поддържа споделяне на звука). Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Свързано (поддържа споделяне на звука). За ляво ухо. Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Свързано (поддържа споделяне на звука). За дясно ухо. Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Свързано (поддържа споделяне на звука)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само за мултимедия)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддържа споделяне на звука"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само за мултимедия), само лявата"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (само за мултимедия), само дясната"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (само за мултимедия), лявата и дясната"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Хардуерно ускорено изобразяване"</string>
<string name="media_category" msgid="8122076702526144053">"Мултимедия"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Наблюдение"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Активиран строг режим"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Примигване на екрана при дълги операции в главната нишка"</string>
<string name="pointer_location" msgid="7516929526199520173">"Mестопол. на показалеца"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Внедряване на WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Задаване на внедряването на WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Този избор вече не е валиден. Опитайте отново."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Цветови режим за снимките"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Използване на sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Деактивирано"</string>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index b27264d..27fe258 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"শুধুমাত্র ডিভাইসের ডিসপ্লে (ডিফল্ট)"</item>
+ <item msgid="9161645858025071955">"এক্সটার্নাল ডিসপ্লে"</item>
+ <item msgid="23651860565814477">"লেটেস্ট স্ট্যাটাস বার টাচ"</item>
+ <item msgid="7521112827893653392">"ফোকাস-ভিত্তিক"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"শুধুমাত্র ডিভাইসের ডিসপ্লেতে শেড দেখুন"</item>
+ <item msgid="1955398604822147783">"কোনও একটি বাইরের ডিসপ্লেতে শেড দেখুন"</item>
+ <item msgid="391477482416751568">"সেই ডিসপ্লেতে শেড দেখুন যেখানে যার স্ট্যাটাস বারে শেষ বার ইন্টার্যাকশন করা হয়েছে"</item>
+ <item msgid="1746820128097981528">"সেই ডিসপ্লেতে শেড দেখুন যেখানে শেষবার ফোকাস করা হয়েছে"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 1e7c7a2..93b6521 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"সারাউন্ডিং আপডেট করা যায়নি"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"চালু আছে (শুধুমাত্র মিডিয়া)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"চালু আছে (শুধুমাত্র মিডিয়া), বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি।"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি।"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে)। বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে)। ডানদিকে: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"চালু আছে (শুধুমাত্র মিডিয়া)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিও শেয়ারিংয়ে কাজ করে"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"চালু আছে (শুধুমাত্র মিডিয়া), শুধুমাত্র বাঁদিক"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"চালু আছে (শুধুমাত্র মিডিয়া), শুধুমাত্র ডানদিক"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"চালু আছে (শুধুমাত্র মিডিয়া), বাঁদিক ও ডানদিক"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"হার্ডওয়্যার দ্বারা চালিত রেন্ডারিং"</string>
<string name="media_category" msgid="8122076702526144053">"মিডিয়া"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"পর্যবেক্ষণে রাখা"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"স্ট্রিক্ট মোড চালু আছে"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"মুখ্য থ্রেডে অ্যাপগুলির দীর্ঘ কার্যকলাপের ক্ষেত্রে স্ক্রিন ফ্ল্যাশ করে"</string>
<string name="pointer_location" msgid="7516929526199520173">"পয়েন্টারের লোকেশন"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"ওয়েবভিউ প্রয়োগ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"ওয়েবভিউ প্রয়োগ সেট করুন"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"এই পছন্দটি আর বৈধ নেই৷ আবার চেষ্টা করুন৷"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ছবি রঙ মোড"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ব্যবহার করুন"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"অক্ষম হয়েছে"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 44bbfaf..f8fc6ac 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -291,14 +291,14 @@
<string-array name="shade_display_awareness_entries">
<item msgid="816770658383209617">"Samo zaslon uređaja (zadano)"</item>
<item msgid="9161645858025071955">"Vanjski ekran"</item>
- <item msgid="23651860565814477">"Najnoviji dodir trake statusa"</item>
- <item msgid="7521112827893653392">"Na temelju fokusa"</item>
+ <item msgid="23651860565814477">"Posljednji dodir na statusnu traku"</item>
+ <item msgid="7521112827893653392">"Na osnovu fokusa"</item>
</string-array>
<string-array name="shade_display_awareness_summaries">
<item msgid="2964753205732912921">"Prikaži sjenu samo na ekranu uređaja"</item>
- <item msgid="1955398604822147783">"Prikaži sjenčanje na jednom vanjskom zaslonu"</item>
- <item msgid="391477482416751568">"Prikaži sjenčanje na zaslonu na kojem je posljednje stupljeno u interakciju s trakom statusa"</item>
- <item msgid="1746820128097981528">"Prikaži sjenčanje na posljednjem fokusiranom zaslonu"</item>
+ <item msgid="1955398604822147783">"Prikaži sjenu na jednom vanjskom ekranu"</item>
+ <item msgid="391477482416751568">"Prikaži sjenu na posljednjem ekranu na kojem se stupalo u interakciju sa statusnom trakom"</item>
+ <item msgid="1746820128097981528">"Prikaži sjenu na posljednjem fokusiranom ekranu"</item>
</string-array>
<string-array name="shade_display_awareness_values">
<item msgid="3055776101992426514">"default_display"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 756a326..abb0775 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ažuriranje okruženja nije uspjelo"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo za medijski sadržaj). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo za medijski sadržaj). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava dijeljenje zvuka). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Povezano (podržava dijeljenje zvuka). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Povezano (podržava dijeljenje zvuka). Lijevo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Povezano (podržava dijeljenje zvuka). Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Povezano (podržava dijeljenje zvuka)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo za medijski sadržaj)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava dijeljenje zvuka"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo za medijski sadržaj), samo lijevo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo za medijski sadržaj), samo desno"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo za medijski sadržaj), lijevo i desno"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardverski ubrzano prikazivanje"</string>
<string name="media_category" msgid="8122076702526144053">"Mediji"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Praćenje"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Omogući strogi način rada"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Ekran bljeska kada aplikacije vrše duge operacije u glavnoj niti"</string>
<string name="pointer_location" msgid="7516929526199520173">"Lokacija pokazivača"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Postavljanje WebViewa"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Podesi WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ovaj izbor više ne vrijedi. Pokušajte ponovo."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Način rada boja slika"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Koristi sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Onemogućeno"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index f19551c..8f1f630 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Només a la pantalla del dispositiu (opció predeterminada)"</item>
+ <item msgid="9161645858025071955">"Pantalla externa"</item>
+ <item msgid="23651860565814477">"Darrer toc a la barra d\'estat"</item>
+ <item msgid="7521112827893653392">"Basat en l\'enfocament"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Mostra l\'ombra només a la pantalla del dispositiu"</item>
+ <item msgid="1955398604822147783">"Mostra l\'àrea en una sola pantalla externa"</item>
+ <item msgid="391477482416751568">"Mostra l\'àrea a la pantalla amb què s\'ha interaccionat per darrera vegada a la barra d\'estat"</item>
+ <item msgid="1746820128097981528">"Mostra l\'àrea a la darrera pantalla en què s\'hagi posat el focus"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 0548099..ed49307c 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"No s\'ha pogut actualitzar l\'entorn"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actiu (només contingut multimèdia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actiu (només contingut multimèdia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connectat (admet compartició d\'àudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connectat (admet compartició d\'àudio), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connectat (admet compartició d\'àudio). Esquerre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connectat (admet compartició d\'àudio). Dret: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connectat (admet compartició d\'àudio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actiu (només contingut multimèdia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admet compartició d\'àudio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actiu (només contingut multimèdia), només esquerre"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actiu (només contingut multimèdia), només dret"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actiu (només contingut multimèdia), esquerre i dret"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Renderització accelerada per maquinari"</string>
<string name="media_category" msgid="8122076702526144053">"Multimèdia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Supervisió"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Mode estricte activat"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Il·lumina la pantalla quan les aplicacions facin operacions llargues al fil principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Ubicació del punter"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementació de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Estableix implementació de WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Aquesta opció ja no és vàlida. Torna-ho a provar."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Mode de color de la imatge"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Utilitza sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Desactivat"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index ad1cafd..152cd83 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Pouze zobrazení zařízení (výchozí)"</item>
+ <item msgid="9161645858025071955">"Externí displej"</item>
+ <item msgid="23651860565814477">"Poslední dotknutí se stavového řádku"</item>
+ <item msgid="7521112827893653392">"Výběr"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Zobrazovat panel pouze na displeji zařízení"</item>
+ <item msgid="1955398604822147783">"Zobrazovat panel na jednom externím displeji"</item>
+ <item msgid="391477482416751568">"Zobrazovat panel na displeji, na kterém uživatel naposledy interagoval se stavovým řádkem"</item>
+ <item msgid="1746820128097981528">"Zobrazovat panel na displeji, který byl naposledy vybrán"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index a774a1d..7ea6e43 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Okolí se nepodařilo aktualizovat"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivní (pouze média). Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivní (pouze média), baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Připojeno (podporuje sdílení zvuku), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Připojeno (podporuje sdílení zvuku), baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Připojeno (podporuje sdílení zvuku). Levá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Připojeno (podporuje sdílení zvuku). Pravá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Připojeno (podporuje sdílení zvuku)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivní (pouze média)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje sdílení zvuku"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivní (pouze média), pouze levé"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivní (pouze média), pouze pravé"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivní (pouze média), levé a pravé"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardwarově urychlené vykreslování"</string>
<string name="media_category" msgid="8122076702526144053">"Média"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Sledování"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Přísný režim aktivován"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Rozblikat obrazovku při dlouhých operacích hlavního vlákna"</string>
<string name="pointer_location" msgid="7516929526199520173">"Umístění ukazatele"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementace WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Nastavte implementaci WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Tato volba již není platná. Zkuste to znovu."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Režim barev obrázku"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Použije se barevný prostor sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Vypnuto"</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index ed45775..aff59c2 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Kun på enhedens skærm (standard)"</item>
+ <item msgid="9161645858025071955">"Ekstern skærm"</item>
+ <item msgid="23651860565814477">"Seneste tryk på statusbjælken"</item>
+ <item msgid="7521112827893653392">"Fokusbaseret"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Vis kun skygge på enhedens skærm"</item>
+ <item msgid="1955398604822147783">"Vis skygge på en enkelt ekstern skærm"</item>
+ <item msgid="391477482416751568">"Vis skygge på den skærm, hvor der sidst blev interageret med statusbjælken"</item>
+ <item msgid="1746820128097981528">"Vis skygge på den skærm, der sidst var i fokus"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index d7aa9b1..4aad2a2 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Omgivelserne kunne ikke opdateres"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiveret (kun for medier). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiveret (kun for medier), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Forbundet (understøtter lyddeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Forbundet (understøtter lyddeling), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Forbundet (understøtter lyddeling). Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Forbundet (understøtter lyddeling). Højre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Forbundet (understøtter lyddeling)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiveret (kun for medier)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Understøtter lyddeling"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiveret (kun for medier), kun venstre"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiveret (kun for medier), kun højre"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiveret (kun for medier), venstre og højre"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware-accelereret gengivelse"</string>
<string name="media_category" msgid="8122076702526144053">"Medie"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Overvågning"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Striks tilstand aktiveret"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Blink med skærmen, når apps foretager handlinger på hovedtråd"</string>
<string name="pointer_location" msgid="7516929526199520173">"Markørens lokation"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Konfigurer WebView-implementering"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Dette valg er ikke længere gyldigt. Prøv igen."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Farvetilstand for billeder"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Brug sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Deaktiveret"</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 924718a..6dc8754 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Nur Gerätedisplay (Standard)"</item>
+ <item msgid="9161645858025071955">"Externes Display"</item>
+ <item msgid="23651860565814477">"Letzte Berührung der Statusleiste"</item>
+ <item msgid="7521112827893653392">"Fokusbasiert"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Leiste nur auf dem Display des Geräts anzeigen"</item>
+ <item msgid="1955398604822147783">"Leiste auf einem einzigen externen Display anzeigen"</item>
+ <item msgid="391477482416751568">"Leiste auf dem Display anzeigen, auf dem zuletzt mit der Statusleiste interagiert wurde"</item>
+ <item msgid="1746820128097981528">"Leiste auf dem zuletzt fokussierten Display anzeigen"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 73268c5..55cae96 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Status der Umgebungsgeräusche konnte nicht aktualisiert werden"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (nur Medien). Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (nur Medien). Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Verbunden (unterstützt Audiofreigabe). Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Verbunden (unterstützt Audiofreigabe). Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Verbunden (unterstützt Audiofreigabe). Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Verbunden (unterstützt Audiofreigabe). Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Verbunden (unterstützt Audiofreigabe)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (nur Medien)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Unterstützt Audiofreigabe"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (nur Medien), nur links"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (nur Medien), nur rechts"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (nur Medien), links und rechts"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardwarebeschleunigtes Rendering"</string>
<string name="media_category" msgid="8122076702526144053">"Medien"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoring"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strikter Modus aktiviert"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Bei langen App-Vorgängen im Hauptthread blinkt Bildschirm"</string>
<string name="pointer_location" msgid="7516929526199520173">"Zeigerposition"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-Implementierung"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView-Implementierung festlegen"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Diese Auswahl ist nicht mehr gültig. Bitte versuche es noch einmal."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Farbmodus für Bilder"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB verwenden"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Deaktiviert"</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 41aefc0..33e2390 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Μόνο οθόνη συσκευής (Προεπιλογή)"</item>
+ <item msgid="9161645858025071955">"Εξωτερική οθόνη"</item>
+ <item msgid="23651860565814477">"Τελευταίο άγγιγμα της γραμμής κατάστασης"</item>
+ <item msgid="7521112827893653392">"Με εστίαση"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Εμφάνιση σκίασης μόνο στην οθόνη συσκευής"</item>
+ <item msgid="1955398604822147783">"Εμφάνιση σκίασης σε εξωτερική οθόνη"</item>
+ <item msgid="391477482416751568">"Εμφάνιση σκίασης στην οθόνη στην οποία έγινε η τελευταία αλληλεπίδραση με τη γραμμή κατάστασης"</item>
+ <item msgid="1746820128097981528">"Εμφάνιση σκίασης στην τελευταία οθόνη με εστίαση"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 209b782..6b6b7fb 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Δεν ήταν δυνατή η ενημέρωση των ήχων περιβάλλοντος"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ενεργό (μόνο για μέσα). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ενεργό (μόνο για μέσα). Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). Αριστερά: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). Δεξιά: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ενεργό (μόνο για μέσα)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Υποστηρίζει κοινή χρήση ήχου"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ενεργό (μόνο για μέσα), μόνο αριστερό"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ενεργό (μόνο για μέσα), μόνο δεξί"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ενεργό (μόνο για μέσα), αριστερό και δεξί"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Απόδοση με επιτάχυνση από υλικό εξοπλισμό"</string>
<string name="media_category" msgid="8122076702526144053">"Μέσα"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Παρακολούθηση"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Ενεργ. αυστηρής λειτουργ."</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Αναβ. οθόνη σε εκτέλεση μεγάλων λειτ.σε κύριο νήμα"</string>
<string name="pointer_location" msgid="7516929526199520173">"Θέση δείκτη"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Υλοποίηση WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ορισμός υλοποίησης WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Αυτή η επιλογή δεν είναι πια έγκυρη. Δοκιμάστε ξανά."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Λειτουργία χρώματος εικόνας"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Χρήση sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Απενεργοποιημένο"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 6c7a7ff..b53ad98 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Device display only (default)"</item>
+ <item msgid="9161645858025071955">"External display"</item>
+ <item msgid="23651860565814477">"Latest status bar touch"</item>
+ <item msgid="7521112827893653392">"Focus-based"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Show shade on device display only"</item>
+ <item msgid="1955398604822147783">"Show shade on single external display"</item>
+ <item msgid="391477482416751568">"Show shade on display which last had its status bar interacted with"</item>
+ <item msgid="1746820128097981528">"Show shade on last focused display"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index d965c65..a811960 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Couldn\'t update surroundings"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connected (supports audio sharing). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connected (supports audio sharing). Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connected (supports audio sharing). Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connected (supports audio sharing)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware accelerated rendering"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoring"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strict mode enabled"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Flash screen when apps do long operations on main thread"</string>
<string name="pointer_location" msgid="7516929526199520173">"Pointer location"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Set WebView implementation"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"This choice is no longer valid. Try again."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Picture colour mode"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Use sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Disabled"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 748d7b1..a12b46c 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -113,13 +113,23 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Couldn’t update surroundings"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+ <string name="bluetooth_guest_battery_level" msgid="2820003593899467676">"Guest device. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_guest_battery_level_untethered" msgid="5404013822067644960">"Guest device. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+ <string name="bluetooth_guest_media_only_battery_level" msgid="7928347900623812299">"Guest device (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_guest_media_only_battery_level_untethered" msgid="4458143141394300892">"Guest device (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connected (supports audio sharing). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connected (supports audio sharing). Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connected (supports audio sharing). Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connected (supports audio sharing)"</string>
+ <string name="bluetooth_guest_battery_level_lea_support" msgid="8098327939585013928">"Guest device (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_guest_battery_level_untethered_lea_support" msgid="3701035025565668360">"Guest device (supports audio sharing). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+ <string name="bluetooth_guest_no_battery_level_lea_support" msgid="2977038548753103470">"Guest device (supports audio sharing)"</string>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
+ <string name="bluetooth_guest_no_battery_level" msgid="9122974160381136920">"Guest device"</string>
+ <string name="bluetooth_guest_media_only_no_battery_level" msgid="7666347601796705721">"Guest device (media only)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
+ <string name="bluetooth_guest_saved_device_lea_support" msgid="5621291599518569876">"Guest device. Supports audio sharing"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string>
@@ -376,6 +386,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware accelerated rendering"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoring"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strict mode enabled"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Flash screen when apps do long operations on main thread"</string>
<string name="pointer_location" msgid="7516929526199520173">"Pointer location"</string>
@@ -470,6 +482,9 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Set WebView implementation"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"This choice is no longer valid. Try again."</string>
+ <string name="webview_launch_devtools_title" msgid="8009687433555367112">"WebView DevTools"</string>
+ <string name="webview_launch_devtools_no_package" msgid="3182544553665113721">"WebView package not found."</string>
+ <string name="webview_launch_devtools_no_activity" msgid="4066006313619617140">"Could not launch DevTools."</string>
<string name="picture_color_mode" msgid="1013807330552931903">"Picture color mode"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Use sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Disabled"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 6c7a7ff..b53ad98 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Device display only (default)"</item>
+ <item msgid="9161645858025071955">"External display"</item>
+ <item msgid="23651860565814477">"Latest status bar touch"</item>
+ <item msgid="7521112827893653392">"Focus-based"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Show shade on device display only"</item>
+ <item msgid="1955398604822147783">"Show shade on single external display"</item>
+ <item msgid="391477482416751568">"Show shade on display which last had its status bar interacted with"</item>
+ <item msgid="1746820128097981528">"Show shade on last focused display"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index d965c65..a811960 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Couldn\'t update surroundings"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connected (supports audio sharing). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connected (supports audio sharing). Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connected (supports audio sharing). Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connected (supports audio sharing)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware accelerated rendering"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoring"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strict mode enabled"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Flash screen when apps do long operations on main thread"</string>
<string name="pointer_location" msgid="7516929526199520173">"Pointer location"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Set WebView implementation"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"This choice is no longer valid. Try again."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Picture colour mode"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Use sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Disabled"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 6c7a7ff..b53ad98 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Device display only (default)"</item>
+ <item msgid="9161645858025071955">"External display"</item>
+ <item msgid="23651860565814477">"Latest status bar touch"</item>
+ <item msgid="7521112827893653392">"Focus-based"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Show shade on device display only"</item>
+ <item msgid="1955398604822147783">"Show shade on single external display"</item>
+ <item msgid="391477482416751568">"Show shade on display which last had its status bar interacted with"</item>
+ <item msgid="1746820128097981528">"Show shade on last focused display"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index d965c65..a811960 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Couldn\'t update surroundings"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connected (supports audio sharing). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connected (supports audio sharing). Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connected (supports audio sharing). Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connected (supports audio sharing)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware accelerated rendering"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoring"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strict mode enabled"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Flash screen when apps do long operations on main thread"</string>
<string name="pointer_location" msgid="7516929526199520173">"Pointer location"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Set WebView implementation"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"This choice is no longer valid. Try again."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Picture colour mode"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Use sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Disabled"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 5894975..2f1b14d 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Solo en la pantalla del dispositivo (predeterminado)"</item>
+ <item msgid="9161645858025071955">"Pantalla externa"</item>
+ <item msgid="23651860565814477">"Última interacción con la barra de estado"</item>
+ <item msgid="7521112827893653392">"Basado en el enfoque"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Mostrar sobra solo en la pantalla del dispositivo"</item>
+ <item msgid="1955398604822147783">"Mostrar panel en una sola pantalla externa"</item>
+ <item msgid="391477482416751568">"Mostrar el panel de la última pantalla en la que se interactuó con su barra de estado"</item>
+ <item msgid="1746820128097981528">"Mostrar el panel en la última pantalla enfocada"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index acd6790..6c3c98a 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"No se pudo actualizar el sonido envolvente"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activado (solo para contenido multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (solo para contenido multimedia); I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (admite el uso compartido de audio); <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (admite el uso compartido de audio); I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (admite el uso compartido de audio). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (admite el uso compartido de audio). Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (admite el uso compartido de audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo para contenido multimedia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admite el uso compartido de audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo para contenido multimedia); solo izquierdo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (solo para contenido multimedia); solo derecho"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (solo para contenido multimedia); izquierdo y derecho"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Renderización acelerada por hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Multimedia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Supervisión"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modo estricto"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Parpadear si aplicaciones tardan en proceso principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Ubicación del puntero"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Configurar la implementación de WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opción ya no es válida. Vuelve a intentarlo."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modo de color de la imagen"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Usa sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Inhabilitado"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 1e8c661..9031cc3 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Solo en la pantalla del dispositivo (predeterminado)"</item>
+ <item msgid="9161645858025071955">"Pantalla externa"</item>
+ <item msgid="23651860565814477">"Toque más reciente en la barra de estado"</item>
+ <item msgid="7521112827893653392">"Basado en el enfoque"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Mostrar el panel solo en la pantalla del dispositivo"</item>
+ <item msgid="1955398604822147783">"Mostrar el panel en una sola pantalla externa"</item>
+ <item msgid="391477482416751568">"Mostrar el panel en la pantalla en la que se haya interactuado por última vez con la barra de estado"</item>
+ <item msgid="1746820128097981528">"Mostrar el panel en la última pantalla enfocada"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 00b987c..b91c9b4 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"No se han podido actualizar los alrededores"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activo (solo multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (solo multimedia). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (permite compartir audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (admite Compartir audio). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (admite Compartir audio). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (admite Compartir audio). Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (admite Compartir audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo multimedia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Permite compartir audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo multimedia), solo el izquierdo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (solo multimedia), solo el derecho"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (solo multimedia), izquierdo y derecho"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Renderización acelerada por hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Multimedia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Supervisión"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modo Estricto habilitado"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Hace parpadear la pantalla si las aplicaciones tardan mucho en el subproceso principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Ubicación del puntero"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Establecer implementación de WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opción ya no está disponible. Vuelve a intentarlo."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modo de color de imagen"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Utiliza sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Inhabilitado"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index b442ed3..8c5d7fe 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ümbritsevate helide seadeid ei saanud värskendada"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiivne (ainult meedia). Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiivne (ainult meedia). Aku: V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ühendatud (toetab heli jagamist). Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ühendatud (toetab heli jagamist). Aku: V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ühendatud (toetab heli jagamist). Vasak: aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ühendatud (toetab heli jagamist). Parem: aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ühendatud (toetab heli jagamist)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivne (ainult meedia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Toetab heli jagamist"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivne (ainult meedia), ainult vasak"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiivne (ainult meedia), ainult parem"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiivne (ainult meedia), vasak ja parem"</string>
@@ -129,7 +149,7 @@
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sisendseade"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Juurdepääs internetile"</string>
<string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Luba juurdepääs kontaktidele ja kõneajale"</string>
- <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Teavet kasutatakse kõne teadaannete ja muu jaoks"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Teavet kasutatakse kõne teadaannete ja muu jaoks."</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneti-ühenduse jagamine"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Tekstsõnumid"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Juurdepääs SIM-ile"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Riistvarakiirendusega renderdamine"</string>
<string name="media_category" msgid="8122076702526144053">"Meedia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Jälgimine"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Range režiim on lubatud"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Ekraan vilgub, kui rakendused teevad pealõimes pikki toiminguid"</string>
<string name="pointer_location" msgid="7516929526199520173">"Kursori asukoht"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView\' rakendamine"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView\' rakendamise seadistamine"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"See valik ei kehti enam. Proovige uuesti."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Pildi värvirežiim"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB kasutamine"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Keelatud"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index a1528c2..616b12f 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Gailuaren pantailan soilik (lehenetsia)"</item>
+ <item msgid="9161645858025071955">"Kanpoko pantailan"</item>
+ <item msgid="23651860565814477">"Egoera-barraren azken ukitzea"</item>
+ <item msgid="7521112827893653392">"Fokuaren arabera"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Erakutsi itzalak gailuaren pantailan soilik"</item>
+ <item msgid="1955398604822147783">"Erakutsi itzala kanpoko pantaila bakar batean"</item>
+ <item msgid="391477482416751568">"Erakutsi itzala egoera-barran interakzio bat izan duen azken pantailan"</item>
+ <item msgid="1746820128097981528">"Erakutsi itzala fokuratutako azken pantailan"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 1c422b6..a1e4664 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ezin izan da eguneratu ingurunea"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktibo (multimedia-edukia soilik). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktibo (multimedia-edukia soilik). L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Konektatuta (audioa partekatzeko eginbidea onartzen du). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Konektatuta (audioa partekatzeko eginbidea onartzen du). L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Konektatuta (audioa partekatzeko eginbidea onartzen du). Ezkerreko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Konektatuta (audioa partekatzeko eginbidea onartzen du). Eskuineko aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Konektatuta (audioa partekatzeko eginbidea onartzen du)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (multimedia-edukia soilik)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audioa partekatzeko eginbidea onartzen du"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (multimedia-edukia soilik); ezkerreko aldea soilik"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktibo (multimedia-edukia soilik); eskuineko aldea soilik"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktibo (multimedia-edukia soilik); ezkerreko eta eskuineko aldeak"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware bidez azeleratutako errendatzea"</string>
<string name="media_category" msgid="8122076702526144053">"Multimedia-edukia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Kontrola"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modu zorrotza gaituta"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Distirarazi hari nagusian eragiketa luzeak egitean"</string>
<string name="pointer_location" msgid="7516929526199520173">"Erakuslearen kokapena"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ezarri WebView inplementazioa"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Jada ez dago erabilgarri aukera hori. Saiatu berriro."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Irudiaren kolore modua"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Erabili sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Desgaituta"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index d7face8..8421726 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"۲"</item>
<item msgid="4779928470672877922">"۳"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"فقط نمایشگر دستگاه (پیشفرض)"</item>
+ <item msgid="9161645858025071955">"نمایشگر خارجی"</item>
+ <item msgid="23651860565814477">"آخرین لمس نوار وضعیت"</item>
+ <item msgid="7521112827893653392">"کانونیمحور"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"نمایش سایه فقط در نمایشگر دستگاه"</item>
+ <item msgid="1955398604822147783">"نمایش سایه در یک نمایشگر خارجی"</item>
+ <item msgid="391477482416751568">"نمایش سایه در نمایشگری که کاربر آخرین بار با نوار وضعیت آن تعامل داشته است"</item>
+ <item msgid="1746820128097981528">"نمایش سایه در آخرین نمایشگر کانونیشده"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"نمایشگر_پیشفرض"</item>
+ <item msgid="774789415968826925">"هر_نمایشگر_خارجی"</item>
+ <item msgid="7880769915418638436">"آخرین_لمس_نوار_وضعیت"</item>
+ <item msgid="4313165186636015195">"نمایشگر_کانونیشده"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index b1f76fb..c939180 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"پیرامون بهروز نشد"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"فعال (فقط رسانه). باتری: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"فعال (فقط رسانه). باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"متصل (از اشتراک صدا پشتیبانی میکند)، باتری: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"متصل (از اشتراک صدا پشتیبانی میکند)، باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"متصل (از اشتراک صدا پشتیبانی میکند). باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"متصل (از اشتراک صدا پشتیبانی میکند). باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"متصل (از اشتراک صدا پشتیبانی میکند)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (فقط رسانه)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"از اشتراک صدا پشتیبانی میکند"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (فقط رسانه)، فقط چپ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"فعال (فقط رسانه)، فقط راست"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"فعال (فقط رسانه)، چپ و راست"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"پردازش سختافزاری سریع"</string>
<string name="media_category" msgid="8122076702526144053">"رسانه"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"نظارت"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"حالت شدید فعال شد"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"چشمک زدن صفحه هنگام انجام عملیات طولانی توسط برنامهها در رشته اصلی"</string>
<string name="pointer_location" msgid="7516929526199520173">"محل اشارهگر"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"اجرای وبنما"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"تنظیم اجرای وبنما"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"این انتخاب دیگر معتبر نیست. دوباره امتحان کنید."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"حالت رنگ عکس"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"استفاده از sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"غیر فعال"</string>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index a10dfbe..9779c6a 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Vain laitteen näyttö (oletus)"</item>
+ <item msgid="9161645858025071955">"Ulkoinen näyttö"</item>
+ <item msgid="23651860565814477">"Viimeisin tilapalkin kosketus"</item>
+ <item msgid="7521112827893653392">"Kohdistusperustainen"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Näytä ilmoitusalue vain laitteen näytöllä"</item>
+ <item msgid="1955398604822147783">"Näytä ilmoitusalue yhdellä ulkoisella näytöllä"</item>
+ <item msgid="391477482416751568">"Näytä ilmoitusalue näytöllä, jolla tilapalkkiin on viimeksi reagoitu"</item>
+ <item msgid="1746820128097981528">"Näytä ilmoitusalue viimeksi kohdistetulla näytöllä"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index b59aa30..d222882 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ympäristön päivittäminen epäonnistui"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiivinen (vain media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiivinen (vain media). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, O: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Yhdistetty (tukee audionjakoa). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Yhdistetty (tukee audionjakoa). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> virtaa, O: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Yhdistetty (tukee audionjakoa). Vasen: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Yhdistetty (tukee audionjakoa). Oikea: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Yhdistetty (tukee audionjakoa)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivinen (vain media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Tukee audionjakoa"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivinen (vain media), vain vasen"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiivinen (vain media), vain oikea"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiivinen (vain media), vasen ja oikea"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Laitteistokiihdytetty hahmonnus"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Valvonta"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Tiukka tila käytössä"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Vilkuta näyttöä sovellusten tehdessä pitkiä toimia"</string>
<string name="pointer_location" msgid="7516929526199520173">"Osoittimen sijainti"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-käyttöönotto"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Määritä WebView-käyttöönotto"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Tämä valinta ei ole enää saatavilla. Yritä uudestaan."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Kuvien värit"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Ota sRGB käyttöön"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Poistettu käytöstä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 9eec65d..f5be655 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Écran de l\'appareil seulement (par défaut)"</item>
+ <item msgid="9161645858025071955">"Écran externe"</item>
+ <item msgid="23651860565814477">"Dernière barre d\'état tactile"</item>
+ <item msgid="7521112827893653392">"Affichage mis en évidence"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Afficher le volet sur l\'écran de l\'appareil seulement"</item>
+ <item msgid="1955398604822147783">"Afficher le volet sur un seul écran externe"</item>
+ <item msgid="391477482416751568">"Afficher le volet sur l\'écran avec lequel la barre d\'état a interagi en dernier"</item>
+ <item msgid="1746820128097981528">"Afficher le volet sur le dernier affichage mis en évidence"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 99ba8b0..b03e6cb 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Impossible de mettre à jour les sons de l\'environnement"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actif (contenu multimédia uniquement). Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actif (contenu multimédia uniquement). G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connecté (prise en charge du partage audio). Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connecté (prise en charge du partage audio). G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connecté (prise en charge du partage audio). Gauche : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connecté (prise en charge du partage audio). Droite : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connecté (prise en charge du partage audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actif (contenu multimédia uniquement)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Prise en charge du partage audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actif (contenu multimédia uniquement), côté gauche seulement"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actif (contenu multimédia uniquement), côté droit seulement"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actif (contenu multimédia uniquement), côtés gauche et droit"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Accélération matérielle"</string>
<string name="media_category" msgid="8122076702526144053">"Médias"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Surveillance"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Mode Strict activé"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Afficher un cadre rouge si le fil principal reste occupé"</string>
<string name="pointer_location" msgid="7516929526199520173">"Emplacement du curseur"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Définir la mise en œuvre WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ce choix n\'est plus valide. Réessayez."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Mode couleur des images"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Utiliser sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Désactivé"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 3787509..3cf68b2 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Écran de l\'appareil uniquement (par défaut)"</item>
+ <item msgid="9161645858025071955">"Écran externe"</item>
+ <item msgid="23651860565814477">"Dernière interaction avec la barre d\'état"</item>
+ <item msgid="7521112827893653392">"Basé sur la sélection"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Afficher le volet sur l\'écran de l\'appareil uniquement"</item>
+ <item msgid="1955398604822147783">"Afficher le volet sur un seul écran externe"</item>
+ <item msgid="391477482416751568">"Afficher le volet sur l\'écran avec lequel la barre d\'état a été utilisée en dernier lieu"</item>
+ <item msgid="1746820128097981528">"Afficher le volet sur le dernier écran avec lequel l\'utilisateur a interagi"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ba77d87..4440126 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Impossible de mettre à jour le mode Sons environnants"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actif (multimédia uniquement). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actif (multimédia uniquement). Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connecté (compatible avec le partage audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connecté (compatible avec le partage audio). Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connecté (compatible avec le partage audio). Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connecté (compatible avec le partage audio). Droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connecté (compatible avec le partage audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activé (multimédia uniquement)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible avec le partage audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activé (multimédia uniquement), gauche uniquement"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activé (multimédia uniquement), droit uniquement"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activé (multimédia uniquement), gauche et droit"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Rendu accéléré par le matériel"</string>
<string name="media_category" msgid="8122076702526144053">"Multimédia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Suivi"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Mode Strict activé"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Faire clignoter l\'écran si le thread principal reste occupé"</string>
<string name="pointer_location" msgid="7516929526199520173">"Emplacement du curseur"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implémentation WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Définir la mise en œuvre WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ce choix n\'est plus valide. Réessayez."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Mode de couleur des images"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Utiliser sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Désactivé"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 9307ba7..76441f9 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Só pantalla do dispositivo (opción predeterminada)"</item>
+ <item msgid="9161645858025071955">"Pantalla externa"</item>
+ <item msgid="23651860565814477">"Último toque na barra de estado"</item>
+ <item msgid="7521112827893653392">"En función do enfoque"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Mostrar panel despregable só na pantalla do dispositivo"</item>
+ <item msgid="1955398604822147783">"Mostrar panel despregable nunha única pantalla externa"</item>
+ <item msgid="391477482416751568">"Mostrar panel despregable na pantalla na que tivo lugar a última interacción coa barra de estado"</item>
+ <item msgid="1746820128097981528">"Mostrar panel despregable na última pantalla enfocada"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"pantalla_predeterminada"</item>
+ <item msgid="774789415968826925">"calquera_pantalla_externa"</item>
+ <item msgid="7880769915418638436">"último_toque_barra_estado"</item>
+ <item msgid="4313165186636015195">"pantalla_enfocada"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 3d5a9bd..536b918 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Non se puido actualizar o ambiente"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activo (só contido multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (só contido multimedia). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (compatible con audio compartido). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (compatible con audio compartido). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (compatible con audio compartido). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (compatible con audio compartido). Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (compatible con audio compartido)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (só contido multimedia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible con audio compartido"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (só contido multimedia), só esquerdo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (só contido multimedia), só dereito"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (só contido multimedia), esquerdo e dereito"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Procesamento acelerado mediante hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Multimedia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Supervisión"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modo estrito activado"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"A pantalla ilumínase se as aplicacións tardan moito no proceso principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Localización do punteiro"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Definir implementación de WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opción xa non é válida. Téntao de novo."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modo de cor da imaxe"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Utiliza sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Desactivado"</string>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 6026663b..8d9ef2b 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"માત્ર ડિવાઇસનું ડિસ્પ્લે (ડિફૉલ્ટ)"</item>
+ <item msgid="9161645858025071955">"બાહ્ય ડિસ્પ્લે"</item>
+ <item msgid="23651860565814477">"નવીનતમ સ્ટેટસ બાર ટચ"</item>
+ <item msgid="7521112827893653392">"ફોકસ-આધારિત"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"માત્ર ડિવાઇસના ડિસ્પ્લે પર શેડ બતાવો"</item>
+ <item msgid="1955398604822147783">"માત્ર એક જ બાહ્ય ડિસ્પ્લે પર શેડ બતાવો"</item>
+ <item msgid="391477482416751568">"તે ડિસ્પ્લે પર શેડ બતાવો જેની સાથે તેના સ્ટેટસ બારે છેલ્લે ક્રિયાપ્રતિક્રિયા કરી હતી"</item>
+ <item msgid="1746820128097981528">"છેલ્લે ફોકસ કરેલા ડિસ્પ્લે પર શેડ બતાવો"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 57ecad8..1b4bad3 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"આસપાસના અવાજો અપડેટ કરી શક્યા નથી"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"સક્રિય (માત્ર મીડિયા માટે). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"સક્રિય (માત્ર મીડિયા માટે). ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"કનેક્ટેડ (ઑડિયો શેરિંગને સપોર્ટ કરે છે). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"કનેક્ટેડ (ઑડિયો શેરિંગને સપોર્ટ કરે છે). ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"કનેક્ટેડ (ઑડિયો શેરિંગને સપોર્ટ કરે છે). ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"કનેક્ટેડ (ઑડિયો શેરિંગને સપોર્ટ કરે છે). જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"કનેક્ટેડ (ઑડિયો શેરિંગને સપોર્ટ કરે છે)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"સક્રિય છે (માત્ર મીડિયા માટે)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ઑડિયો શેરિંગને સપોર્ટ કરે છે"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"સક્રિય છે (માત્ર મીડિયા માટે), માત્ર ડાબી બાજુ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"સક્રિય છે (માત્ર મીડિયા માટે), માત્ર જમણી બાજુ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"સક્રિય છે (માત્ર મીડિયા માટે), ડાબી અને જમણી બાજુ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"હાર્ડવેર પ્રવેગક રેન્ડરિંગ"</string>
<string name="media_category" msgid="8122076702526144053">"મીડિયા"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"નિરિક્ષણ કરી રહ્યું છે"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"સ્ટ્રિક્ટ મોડ ચાલુ કરેલો છે"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"જ્યારે મુખ્ય થ્રેડ પર ઍપ લાંબી કામગીરીઓ કરે ત્યારે સ્ક્રીનને ફ્લેશ કરો"</string>
<string name="pointer_location" msgid="7516929526199520173">"પૉઇન્ટર લોકેશન"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView અમલીકરણ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView અમલીકરણ સેટ કરો"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"આ વિકલ્પ હવે માન્ય નથી. ફરી પ્રયાસ કરો."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ચિત્ર રંગ મોડ"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB નો ઉપયોગ કરો"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"બંધ"</string>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 67de2ae..9c138d2 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"सिर्फ़ डिवाइस का डिसप्ले (डिफ़ॉल्ट)"</item>
+ <item msgid="9161645858025071955">"बाहरी डिसप्ले पर"</item>
+ <item msgid="23651860565814477">"हाल ही में स्टेटस बार को टच किया गया"</item>
+ <item msgid="7521112827893653392">"फ़ोकस के हिसाब से"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"सिर्फ़ डिवाइस के डिसप्ले पर शेड दिखाएं"</item>
+ <item msgid="1955398604822147783">"किसी एक बाहरी डिसप्ले पर शेड दिखाएं"</item>
+ <item msgid="391477482416751568">"उस डिसप्ले पर शेड दिखाएं जिसकी स्टेटस बार के साथ पिछली बार इंटरैक्शन किया गया था"</item>
+ <item msgid="1746820128097981528">"उस डिसप्ले पर शेड दिखाएं जिस पर आखिरी बार फ़ोकस किया गया था"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index c1f4fe2..55d425f 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"वॉल्यूम को मैनेज करने की सेटिंग नहीं बदली जा सकी"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"चालू है (सिर्फ़ मीडिया के लिए). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"चालू है (सिर्फ़ मीडिया के लिए). बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बैटरी."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है). बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बैटरी."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है). बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है). दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"कनेक्ट है (ऑडियो शेयर करने की सुविधा काम करती है)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"चालू है (सिर्फ़ मीडिया के लिए)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडियो शेयर करने की सुविधा काम करती है"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"चालू है (सिर्फ़ मीडिया के लिए), सिर्फ़ बाएं कान की मशीन"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"चालू है (सिर्फ़ मीडिया के लिए), सिर्फ़ दाएं कान की मशीन"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"चालू है (सिर्फ़ मीडिया के लिए), बाएं और दाएं कान की मशीन"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेयर ऐक्सेलरेटेड रेंडरिंग"</string>
<string name="media_category" msgid="8122076702526144053">"मीडिया"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"निगरानी"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड चालू रखें"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"थ्रेड पर लंबा प्रोसेस होने पर स्क्रीन फ़्लैश करें"</string>
<string name="pointer_location" msgid="7516929526199520173">"पॉइंटर की जगह"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"वेबव्यू लागू करें"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"वेबव्यू सेट करें"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"यह चुनाव अब मान्य नहीं है. दोबारा कोशिश करें."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"चित्र रंग मोड"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB का उपयोग करें"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"बंद"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 131195e..97f2df6 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ažuriranje okruženja nije uspjelo"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo medijski sadržaji). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo medijski sadržaji), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava zajedničko slušanje). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Povezano (podržava zajedničko slušanje), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Povezano (podržava zajedničko slušanje). Lijeva strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Povezano (podržava zajedničko slušanje). Desna strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Povezano (podržava zajedničko slušanje)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo medijski sadržaji)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava zajedničko slušanje"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo medijski sadržaji), samo lijeva"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo medijski sadržaji), samo desna"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo medijski sadržaji), lijeva i desna"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardverski ubrzano renderiranje"</string>
<string name="media_category" msgid="8122076702526144053">"Mediji"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Nadzor"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Omogućen strogi način"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Zaslon bljeska kada operacije aplikacija u glavnoj niti dugo traju"</string>
<string name="pointer_location" msgid="7516929526199520173">"Mjesto pokazivača"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacija WebViewa"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Postavi implementaciju WebViewa"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Taj izbor više nije važeći. Pokušajte ponovo."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Način boje slike"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Upotrijebi sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Onemogućeno"</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index d8d42f9..677b821 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Csak az eszköz kijelzője (alapértelmezett)"</item>
+ <item msgid="9161645858025071955">"Külső kijelző"</item>
+ <item msgid="23651860565814477">"Az állapotsor legutóbbi érintése"</item>
+ <item msgid="7521112827893653392">"Fókusz alapján"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Felület megjelenítése csak az eszköz kijelzőjén"</item>
+ <item msgid="1955398604822147783">"Felület megjelenítése egyetlen külső kijelzőn"</item>
+ <item msgid="391477482416751568">"Felület megjelenítése azon a kijelzőn, amelyen utoljára végeztek műveletet az állapotsorral"</item>
+ <item msgid="1746820128097981528">"Felület megjelenítése az utoljára fókuszban lévő kijelzőn"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index fa32155..5e97cff 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nem sikerült módosítani a környezetet"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktív (csak médiatartalom lejátszása esetén). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktív (csak médiatartalom lejátszása esetén). Akkumulátorok töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (bal) és <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (jobb)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátorok töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (bal) és <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (jobb)."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (bal)."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (jobb)."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Csatlakoztatva (támogatja a hang megosztását)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktív (csak médiatartalom lejátszása)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Támogatja a hang megosztását"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktív (csak médiatartalom lejátszása), csak a bal"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktív (csak médiatartalom lejátszása), csak a jobb"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktív (csak médiatartalom lejátszása), bal és jobb"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardveres gyorsítású megjelenítés"</string>
<string name="media_category" msgid="8122076702526144053">"Média"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Figyelés"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Szigorú mód engedélyezve"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Képernyővillogás a fő szál hosszú műveleteinél"</string>
<string name="pointer_location" msgid="7516929526199520173">"Mutató helye"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-megvalósítás"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView-megvalósítás beállítása"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ez a választás már nem érvényes. Próbálkozzon újra."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Kép színe mód"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB használata"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Letiltva"</string>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index b2133fb..f71d1fc 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Միայն սարքի էկրանը (կանխադրված)"</item>
+ <item msgid="9161645858025071955">"Արտաքին էկրան"</item>
+ <item msgid="23651860565814477">"Կարգավիճակի գոտու հետ վերջին փոխազդումը"</item>
+ <item msgid="7521112827893653392">"Ֆոկուսի հիման վրա"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Ցույց տալ երանգը միայն սարքի էկրանին"</item>
+ <item msgid="1955398604822147783">"Ցույց տալ երանգը մեկ արտաքին էկրանին"</item>
+ <item msgid="391477482416751568">"Ցույց տալ երանգն էկրանին, որի կարգավիճակի գոտու հետ վերջերս օգտատերը փոխազդել է"</item>
+ <item msgid="1746820128097981528">"Ցույց տալ երանգը վերջին ֆոկուսավորված էկրանին"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index fa87813..d342717 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Չհաջողվեց թարմացնել շրջակայքի կարգավիճակը"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ակտիվ է (միայն մեդիա)։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ակտիվ է (միայն մեդիա)։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>։"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>։"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Միացված է (աջակցում է աուդիոյի փոխանցում)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ակտիվ է (միայն մեդիա)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Աջակցում է աուդիոյի փոխանցում"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ակտիվ է (միայն մեդիա), միայն ձախ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ակտիվ է (միայն մեդիա), միայն աջ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ակտիվ է (միայն մեդիա), աջ և ձախ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Սարքաշարի արագացված նյութավորում"</string>
<string name="media_category" msgid="8122076702526144053">"Մեդիա"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Մշտադիտարկում"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Խիստ ռեժիմն ակտիվացված է"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Լուսավորել էկրանը` ծրագրի գլխավոր շղթայի վրա երկար աշխատելիս"</string>
<string name="pointer_location" msgid="7516929526199520173">"Նշորդի տեղադրությունը"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ծառայություն"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ընտրեք WebView-ի իրականացումը"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Այս ընտրանքն այլևս վավեր չէ: Փորձեք նորից:"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Նկարի գունային ռեժիմ"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Օգտագործել sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Կասեցված է"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index fa2fa9e..a4bb2f4 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Hanya layar perangkat (Default)"</item>
+ <item msgid="9161645858025071955">"Layar eksternal"</item>
+ <item msgid="23651860565814477">"Sentuhan status bar terbaru"</item>
+ <item msgid="7521112827893653392">"Berbasis fokus"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Tampilkan shade hanya di layar perangkat"</item>
+ <item msgid="1955398604822147783">"Tampilkan menu di satu layar eksternal"</item>
+ <item msgid="391477482416751568">"Tampilkan menu di layar yang terakhir kali berinteraksi dengan status bar-nya"</item>
+ <item msgid="1746820128097981528">"Tampilkan menu di layar yang terakhir difokuskan"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 1ff4b29..649ee0bb 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Tidak dapat memperbarui suara sekitar"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktif (hanya media). Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktif (hanya media). Baterai L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Terhubung (mendukung berbagi audio). Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Terhubung (mendukung berbagi audio). Baterai L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Terhubung (mendukung berbagi audio). Kiri: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Terhubung (mendukung berbagi audio). Kanan: Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Terhubung (mendukung berbagi audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (hanya media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mendukung berbagi audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (hanya media), hanya kiri"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktif (hanya media), hanya kanan"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktif (hanya media), kiri dan kanan"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Render yang dipercepat hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Pemantauan"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Mode ketat diaktifkan"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Buat layar berkedip saat aplikasi berlama-lama menjalankan operasi di thread utama"</string>
<string name="pointer_location" msgid="7516929526199520173">"Lokasi kursor"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Penerapan WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Setel penerapan WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Pilihan ini tidak valid lagi. Coba lagi."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Mode warna gambar"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Gunakan sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Dinonaktifkan"</string>
@@ -634,7 +662,7 @@
<string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil dibatasi"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"Tambahkan pengguna baru?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"Anda dapat menggunakan perangkat ini bersama orang lain dengan membuat pengguna tambahan. Setiap pengguna memiliki ruang sendiri, yang dapat disesuaikan dengan aplikasi, wallpaper, dan lainnya. Pengguna juga dapat menyesuaikan setelan perangkat seperti Wi-Fi yang dapat memengaruhi semua pengguna lain.\n\nSaat Anda menambahkan pengguna baru, pengguna tersebut perlu menyiapkan ruangnya.\n\nPengguna mana pun dapat mengupdate aplikasi untuk semua pengguna lainnya. Layanan dan setelan aksesibilitas mungkin tidak ditransfer ke pengguna baru."</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"Saat Anda menambahkan pengguna baru, orang tersebut harus menyiapkan ruangnya sendiri.\n\nPengguna mana pun dapat meng-update aplikasi untuk semua pengguna lain."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Saat Anda menambahkan pengguna baru, orang tersebut harus menyiapkan ruangnya sendiri.\n\nPengguna mana pun dapat mengupdate aplikasi untuk semua pengguna lain."</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"Jadikan pengguna ini sebagai admin?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"Admin memiliki hak istimewa khusus yang tidak dimiliki pengguna lain. Admin dapat mengelola semua pengguna, mengupdate atau mereset perangkat ini, mengubah setelan, melihat semua aplikasi terinstal, dan memberi atau mencabut hak istimewa admin untuk pengguna lain."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Jadikan admin"</string>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 851a7a49..27846cc 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Aðeins skjár tækis (sjálfgefið)"</item>
+ <item msgid="9161645858025071955">"Ytri skjár"</item>
+ <item msgid="23651860565814477">"Síðasta snerting stöðustiku"</item>
+ <item msgid="7521112827893653392">"Byggt á fókus"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Aðeins skyggja skjá tækis"</item>
+ <item msgid="1955398604822147783">"Skyggja stakan ytri skjá"</item>
+ <item msgid="391477482416751568">"Skyggja skjá þar sem stöðustika var síðast notuð"</item>
+ <item msgid="1746820128097981528">"Skyggja síðasta skjá í fókus"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 804ea63..d361157 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ekki var hægt að uppfæra umhverfi"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Virkt (eingöngu margmiðlunarefni). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Virkt (eingöngu margmiðlunarefni), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlöðuhleðsla."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Tengt (styður hljóðdeilingu), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Tengt (styður hljóðdeilingu), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlöðuhleðsla."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Tengt (styður hljóðdeilingu). Vinstri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Tengt (styður hljóðdeilingu). Hægri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Tengt (styður hljóðdeilingu)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Virkt (eingöngu margmiðlunarefni)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Styður hljóðdeilingu"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Virkt (eingöngu margmiðlunarefni), eingöngu vinstri"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Virkt (eingöngu margmiðlunarefni), eingöngu hægri"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Virkt (eingöngu margmiðlunarefni), vinstri og hægri"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Myndþýðing með vélbúnaðarhröðun"</string>
<string name="media_category" msgid="8122076702526144053">"Margmiðlun"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Eftirlit"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Kveikt á strangri stillingu"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Blikka skjá ef forrit gera tímafreka hluti á aðalþræði"</string>
<string name="pointer_location" msgid="7516929526199520173">"Staðsetning bendils"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Innleiðing WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Stilla innleiðingu WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Þetta val er ekki lengur gilt. Reyndu aftur."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Litastilling mynda"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Nota sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Óvirkt"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 09ec5cc..98e415b 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Impossibile aggiornare audio ambientale"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Attivo (solo contenuti multimediali). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Attivo (solo contenuti multimediali). S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connesso (supporta la condivisione audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connesso (supporta la condivisione audio). S: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> di batteria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> di batteria."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connesso (supporta la condivisione audio). Sinistro: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connesso (supporta la condivisione audio). Destro: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connesso (supporta la condivisione audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Attivo (solo contenuti multimediali)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supporta la condivisione audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Attivo (solo contenuti multimediali), solo sinistro"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Attivo (solo contenuti multimediali), solo destro"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Attivo (solo contenuti multimediali), sinistro e destro"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Rendering con accelerazione hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Contenuti multimediali"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoraggio"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Attiva StrictMode"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Fai lampeggiare lo schermo per operazioni lunghe sul thread principale"</string>
<string name="pointer_location" msgid="7516929526199520173">"Posizione puntatore"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementazione di WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Imposta l\'implementazione di WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"La selezione non è più valida. Riprova."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modalità colori immagini"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Usa sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Disattivato"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 9d176c0..744e502 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"מסך המכשיר בלבד (ברירת המחדל)"</item>
+ <item msgid="9161645858025071955">"מסך חיצוני"</item>
+ <item msgid="23651860565814477">"אינטראקציה אחרונה עם שורת הסטטוס"</item>
+ <item msgid="7521112827893653392">"לפי התמקדות"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"הצגת הצללה במסך המכשיר בלבד"</item>
+ <item msgid="1955398604822147783">"הצגת לוח ההתראות במסך חיצוני אחד"</item>
+ <item msgid="391477482416751568">"הצגת לוח ההתראות במסך שבו הייתה האינטראקציה האחרונה עם שורת הסטטוס"</item>
+ <item msgid="1746820128097981528">"הצגת לוח ההתראות במסך האחרון שבו המשתמש התמקד"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 361dd18..b341c4d 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"לא ניתן לעדכן את עוצמת הרעשים בסביבה"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"פעיל (מדיה בלבד). סוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"פעיל (מדיה בלבד). סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"מחובר (תמיכה בשיתוף אודיו). סוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"מחובר (תמיכה בשיתוף אודיו). סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"מחובר (תמיכה בשיתוף אודיו). סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"מחובר (תמיכה בשיתוף אודיו). סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"מחובר (תמיכה בשיתוף אודיו)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"פעיל (מדיה בלבד)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"תמיכה בשיתוף אודיו"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"פעיל (מדיה בלבד), שמאל בלבד"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"פעיל (מדיה בלבד), ימין בלבד"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"פעיל (מדיה בלבד), שמאל וימין"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"עיבוד מואץ של חומרה"</string>
<string name="media_category" msgid="8122076702526144053">"מדיה"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"מעקב"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"מצב קפדני מופעל"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"המסך יהבהב כשאפליקציות יבצעו פעולות ארוכות ב-thread הראשי"</string>
<string name="pointer_location" msgid="7516929526199520173">"מיקום מצביע"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"יישום WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"הגדרת יישום WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"אפשרות זו כבר אינה תקפה. אפשר לנסות שוב."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"מצב צבע התמונה"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"שימוש ב-sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"מושבת"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 1170cd1..2e36d6a 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"周囲の音を更新できませんでした"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"有効(メディアのみ)。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"有効(メディアのみ)。左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"接続済み(音声の共有をサポート)。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"接続済み(音声の共有をサポート)。左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"接続済み(音声の共有をサポート)。左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"接続済み(音声の共有をサポート)。右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"接続済み(音声の共有をサポート)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"有効(メディアのみ)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"音声の共有をサポートしています"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"有効(メディアのみ)、左のみ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"有効(メディアのみ)、右のみ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"有効(メディアのみ)、左右"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ハードウェアアクセラレーテッドレンダリング"</string>
<string name="media_category" msgid="8122076702526144053">"メディア"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"モニタリング"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"厳格モードを有効にする"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"メインスレッドの処理が長引く場合は画面を点滅させる"</string>
<string name="pointer_location" msgid="7516929526199520173">"ポインタの位置"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView の実装"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView の実装の設定"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"この選択は無効になりました。もう一度お試しください。"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"画像の色モード"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGBを使用"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"無効"</string>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 8ee3338..3ecf9d8 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"მხოლოდ მოწყობილობის ეკრანი (ნაგულისხმევი)"</item>
+ <item msgid="9161645858025071955">"გარე ეკრანი"</item>
+ <item msgid="23651860565814477">"სტატუსის ზოლის ბოლო შეხება"</item>
+ <item msgid="7521112827893653392">"ფოკუსის მიხედვით"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"ჩრდილის ჩვენება მხოლოდ მოწყობილობის ეკრანზე"</item>
+ <item msgid="1955398604822147783">"ჩრდილის ჩვენება ერთ გარე ეკრანზე"</item>
+ <item msgid="391477482416751568">"ეკრანზე ჩრდილის ჩვენება, რომლის სტატუსის ზოლთანაც მოხდა ბოლო ინტერაქცია"</item>
+ <item msgid="1746820128097981528">"ჩრდილის ჩვენება ბოლო ფოკუსირებულ ეკრანზე"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"ფოკუსირებული_ეკრანი"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 6503795..e627b79 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"გარემოცვის განახლება ვერ მოხერხდა"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"აქტიური (მხოლოდ მედია). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>%% ბატარეა."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"აქტიური (მხოლოდ მედია), მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, მარჯვენა:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ბატარეა."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია). ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია). მარცხენა: ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, მარჯვენა: ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია). მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია). მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"აქტიური (მხოლოდ მედია)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"აუდიოს გაზიარება მხარდაჭერილია"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"აქტიური (მხოლოდ მედია), მხოლოდ მარცხენა"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"აქტიური (მხოლოდ მედია), მხოლოდ მარჯვენა"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"აქტიური (მხოლოდ მედია), მარცხენა და მარჯვენა"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"აპარატურით დაჩქარებული გამოსახულება"</string>
<string name="media_category" msgid="8122076702526144053">"მედია"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"მონიტორინგი"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"მკაცრი რეჟიმი ჩართულია"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"ეკრანის აციმციმება, როცა აპები ახორციელებენ ხანგრძლივ ოპერაციებს მთავარ ნაკადზე"</string>
<string name="pointer_location" msgid="7516929526199520173">"მაჩვენებლის მდებარეობა"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView რეალიზაცია"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView რეალიზაციის დაყენება"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"თქვენი არჩევანი აღარ მოქმედებს. ცადეთ ხელახლა."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"გამოსახულების ფერების რეჟიმი"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB-ს გამოყენება"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"გამორთულია"</string>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 6aa5f2b..e2510a7 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Тек құрылғы дисплейі (әдепкі)"</item>
+ <item msgid="9161645858025071955">"Сыртқы дисплей"</item>
+ <item msgid="23651860565814477">"Соңғы күй жолағын түрту"</item>
+ <item msgid="7521112827893653392">"Назарға негізделген"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Құрылғы дисплейінде ғана реңк көрсету"</item>
+ <item msgid="1955398604822147783">"Жалғыз сыртқы дисплейде көлеңкені көрсету"</item>
+ <item msgid="391477482416751568">"Күй жолағы соңғы рет қолданылған дисплейде көлеңкені көрсету"</item>
+ <item msgid="1746820128097981528">"Соңғы рет назарда болған дисплейде көлеңкені көрсету"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 9082a56..a85e624 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Айналаны жаңарту мүмкін болмады."</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Істеп тұр (тек мультимедиа). Батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Істеп тұр (тек мультимедиа). Сол жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Жалғанып тұр (аудио бөлісу мүмкіндігі бар). Батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Қосылды (аудио бөлісуге мүмкіндік береді). Сол жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Қосылды (аудио бөлісуге мүмкіндік береді). Сол жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Қосылды (аудио бөлісуге мүмкіндік береді). Оң жақ: батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Жалғанды (аудио бөлісу мүмкіндігі бар)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Істеп тұр (тек мультимедиа)."</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио бөлісуге мүмкіндік береді."</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Тек сол жақ істеп тұр (мультимедиа ғана)."</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Тек оң жақ істеп тұр (мультимедиа ғана)."</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Сол және оң жақ істеп тұр (мультимедиа ғана)."</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Бейнелеуді аппаратпен жеделдету"</string>
<string name="media_category" msgid="8122076702526144053">"Mультимeдиа"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Бақылау"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Қатаң режим қосылған"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Қолданбалар ұзақ операцияларды орындағанда экранды жыпылықтату"</string>
<string name="pointer_location" msgid="7516929526199520173">"Меңзер орны"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView қызметі"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView ендіруін орнату"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Бұл таңдау енді жарамды емес. Әрекетті қайталаңыз."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Сурет түс режимі"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB пайдалану"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Өшірулі"</string>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index e9a21e8..07e64a5 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"ផ្ទាំងអេក្រង់ឧបករណ៍តែប៉ុណ្ណោះ (លំនាំដើម)"</item>
+ <item msgid="9161645858025071955">"ផ្ទាំងអេក្រង់ខាងក្រៅ"</item>
+ <item msgid="23651860565814477">"ការចុចរបារស្ថានភាពចុងក្រោយបំផុត"</item>
+ <item msgid="7521112827893653392">"ផ្អែកលើការផ្ដោត"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"បង្ហាញផ្ទាំងនៅលើផ្ទាំងអេក្រង់ឧបករណ៍តែប៉ុណ្ណោះ"</item>
+ <item msgid="1955398604822147783">"បង្ហាញផ្ទាំងនៅលើផ្ទាំងអេក្រង់ខាងក្រៅតែមួយ"</item>
+ <item msgid="391477482416751568">"បង្ហាញផ្ទាំងនៅលើផ្ទាំងអេក្រង់ដែលមានការធ្វើអន្តរកម្មចុងក្រោយលើរបារស្ថានភាពរបស់វា"</item>
+ <item msgid="1746820128097981528">"បង្ហាញផ្ទាំងនៅលើផ្ទាំងអេក្រង់ដែលបានផ្ដោតចុងក្រោយ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 3cc214e..d2d5893 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"មិនអាចប្ដូរមជ្ឈដ្ឋានជុំវិញបានទេ"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)។ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)។ ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>។"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា)។ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា)។ ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>។"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា)។ ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា)។ ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"អាចប្រើការស្ដាប់សំឡេងរួមគ្នា"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) តែខាងឆ្វេងប៉ុណ្ណោះ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) តែខាងស្ដាំប៉ុណ្ណោះ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) ឆ្វេង និងស្ដាំ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ការបំប្លែងដែលពន្លឿនដោយប្រើហាតវែរ"</string>
<string name="media_category" msgid="8122076702526144053">"មេឌៀ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"តាមដាន"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"បានបើកមុខងារតឹងរ៉ឹង"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"បញ្ចេញពន្លឺអេក្រង់ពេលកម្មវិធីធ្វើប្រតិបត្តិការយូរលើសែស្រឡាយមេ"</string>
<string name="pointer_location" msgid="7516929526199520173">"ទីតាំងទ្រនិច"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"ការអនុវត្ត WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"កំណត់ការប្រតិបត្តិ WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ជម្រើសនេះលែងមានសុពលភាពទៀតហើយ ព្យាយាមម្តងទៀត"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"របៀបនៃពណ៌រូបភាព"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"ប្រើ sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"បានបិទ"</string>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index dc9c7e0..de2269a 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"ಸಾಧನದ ಡಿಸ್ಪ್ಲೇ ಮಾತ್ರ (ಡೀಫಾಲ್ಟ್)"</item>
+ <item msgid="9161645858025071955">"ಬಾಹ್ಯ ಡಿಸ್ಪ್ಲೇ"</item>
+ <item msgid="23651860565814477">"ಇತ್ತೀಚಿನ ಸ್ಥಿತಿ ಪಟ್ಟಿಯ ಸ್ಪರ್ಶ"</item>
+ <item msgid="7521112827893653392">"ಫೋಕಸ್-ಆಧಾರಿತ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"ಸಾಧನದ ಡಿಸ್ಪ್ಲೇನಲ್ಲಿ ಮಾತ್ರ ಶೇಡ್ ತೋರಿಸಿ"</item>
+ <item msgid="1955398604822147783">"ಒಂದೇ ಬಾಹ್ಯ ಡಿಸ್ಪ್ಲೇನಲ್ಲಿ ಶೇಡ್ ಅನ್ನು ತೋರಿಸಿ"</item>
+ <item msgid="391477482416751568">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಕೊನೆಯದಾಗಿ ಸಂವಹನ ನಡೆಸಿದ ಶೇಡ್ ಅನ್ನು ಡಿಸ್ಪ್ಲೇ ಮೇಲೆ ತೋರಿಸಿ"</item>
+ <item msgid="1746820128097981528">"ಕೊನೆಯ ಕೇಂದ್ರೀಕೃತ ಡಿಸ್ಪ್ಲೇನಲ್ಲಿ ಶೇಡ್ ಅನ್ನು ತೋರಿಸಿ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index d2b2176..87f2cdf 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ಆ್ಯಂಬಿಯೆಂಟ್ ಸ್ಥಿತಿಯನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ). ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ). ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ). ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ). ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಎಡ ಭಾಗದ ಮಾತ್ರ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಬಲ ಭಾಗದ ಮಾತ್ರ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಎಡ ಮತ್ತು ಬಲ ಭಾಗದ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ಹಾರ್ಡ್ವೇರ್ ವೇಗವರ್ಧಿತ ರೆಂಡರಿಂಗ್"</string>
<string name="media_category" msgid="8122076702526144053">"ಮಾಧ್ಯಮ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"ಪರಿವೀಕ್ಷಣೆ ಮಾಡುವಿಕೆ"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"ಸ್ಟ್ರಿಕ್ಟ್ ಮೋಡ್ ಸಕ್ರಿಯ"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮುಖ್ಯ ಥ್ರೆಡ್ನಲ್ಲಿ ದೀರ್ಘ ಕಾರ್ಯಾಚರಣೆ ನಿರ್ವಹಿಸಿದಾಗ ಪರದೆಯನ್ನು ಫ್ಲ್ಯಾಶ್ ಮಾಡು"</string>
<string name="pointer_location" msgid="7516929526199520173">"ಪಾಯಿಂಟರ್ ಸ್ಥಳ"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ಹೊಂದಿಸಿ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ಸೆಟ್ ಮಾಡಿ"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ಈ ಆಯ್ಕೆಯು ಇನ್ನು ಮುಂದೆ ಮಾನ್ಯವಾಗಿರುವುದಿಲ್ಲ. ಮತ್ತೊಮ್ಮೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ಚಿತ್ರ ಬಣ್ಣದ ಮೋಡ್"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ಬಳಸಿ"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 1477497..3cc5af0 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"기기 디스플레이만(기본값)"</item>
+ <item msgid="9161645858025071955">"외부 디스플레이"</item>
+ <item msgid="23651860565814477">"최근 상태 표시줄 터치"</item>
+ <item msgid="7521112827893653392">"포커스 기반"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"기기 디스플레이에만 음영 표시"</item>
+ <item msgid="1955398604822147783">"단일 외부 디스플레이에 음영 표시"</item>
+ <item msgid="391477482416751568">"마지막으로 상호작용한 상태 표시줄이 있는 디스플레이에 음영 표시"</item>
+ <item msgid="1746820128097981528">"마지막으로 포커스된 디스플레이에 음영 표시"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index bece637..669d8ef 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"주변 소리를 업데이트할 수 없음"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"사용 중입니다(미디어 전용). 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"사용 중입니다(미디어 전용). 배터리는 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>입니다."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"연결되었습니다(오디오 공유 지원). 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"연결되었습니다(오디오 공유 지원). 배터리는 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>입니다."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"연결되었습니다(오디오 공유 지원). 왼쪽 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"연결되었습니다(오디오 공유 지원). 오른쪽 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"연결됨(오디오 공유 지원)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"사용 중(미디어 전용)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"오디오 공유 지원"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"사용 중(미디어 전용), 왼쪽만"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"사용 중(미디어 전용), 오른쪽만"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"사용 중(미디어 전용), 왼쪽 및 오른쪽"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"하드웨어 가속 렌더링"</string>
<string name="media_category" msgid="8122076702526144053">"미디어"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"모니터링"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"엄격 모드 사용"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"앱이 기본 스레드에서 오래 작업하면 화면 깜박이기"</string>
<string name="pointer_location" msgid="7516929526199520173">"포인터 위치"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 구현"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView 구현 설정"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"선택이 더 이상 유효하지 않습니다. 다시 시도하세요."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"사진 색상 모드"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB 사용"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"사용 중지됨"</string>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 54d9ecd..5e40443 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Түзмөктүн экраны гана (демейки)"</item>
+ <item msgid="9161645858025071955">"Тышкы экран"</item>
+ <item msgid="23651860565814477">"Абал тилкесине акыркы жолу тийүү"</item>
+ <item msgid="7521112827893653392">"Акыркы аракетке негизделген"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Көлөкөнү түзмөктүн экранында гана көрсөтүү"</item>
+ <item msgid="1955398604822147783">"Көлөкөнү бир тышкы экранда көрсөтүү"</item>
+ <item msgid="391477482416751568">"Көлөкөнү колдонуучу абал тилкеси менен акыркы жолу аракеттешкен экранда көрсөтүү"</item>
+ <item msgid="1746820128097981528">"Көлөкөнү акыркы активдүү экранда көрсөтүү"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index b6baf38..c69325b 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Айланадагы абал жаңыртылган жок"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Жигердүү (медиа үчүн гана). Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Жигердүү (медиа үчүн гана). Батарея: L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Туташып турат (чогуу уксаңыз болот). Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Туташып турат (чогуу уксаңыз болот). Батарея: L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Туташып турат (чогуу уксаңыз болот). Сол кулак – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Туташып турат (чогуу уксаңыз болот). Оң кулак – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Туташып турат (чогуу уксаңыз болот)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активдүү (медиа үчүн гана)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Чогуу уксаңыз болот"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активдүү (медиа үчүн гана), сол кулакчын гана"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активдүү (медиа үчүн гана), оң кулакчын гана"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активдүү (медиа үчүн гана), сол жана оң кулакчын"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Визуалдаштырууну аппарат менен ылдамдатуу"</string>
<string name="media_category" msgid="8122076702526144053">"Медиа"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Мониторинг"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Катаал режим иштетилди"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Узак операцияларда экран күйүп-өчүп турат"</string>
<string name="pointer_location" msgid="7516929526199520173">"Көрсөткүчтүн турган жери"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView кызматы"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView аткарылышын коюу"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Тандалган нерсе жараксыз болуп калган. Кайталап көрүңүз."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Сүрөт түсү режими"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB колдонуңуз"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Өчүк"</string>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index ccf645b..cf0a783 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"ຈໍສະແດງຜົນຂອງອຸປະກອນເທົ່ານັ້ນ (ຄ່າເລີ່ມຕົ້ນ)"</item>
+ <item msgid="9161645858025071955">"ຈໍສະແດງຜົນພາຍນອກ"</item>
+ <item msgid="23651860565814477">"ການສຳຜັດແຖບສະຖານະຫຼ້າສຸດ"</item>
+ <item msgid="7521112827893653392">"ອີງຕາມການໂຟກັສ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"ສະແດງເສດສີໃນຈໍສະແດງຜົນຂອງອຸປະກອນເທົ່ານັ້ນ"</item>
+ <item msgid="1955398604822147783">"ສະແດງເສດສີໃນຈໍສະແດງຜົນພາຍນອກເຄື່ອງດຽວ"</item>
+ <item msgid="391477482416751568">"ສະແດງເສດສີໃນຈໍສະແດງຜົນທີ່ມີການໂຕ້ຕອບກັບແຖບສະຖານະຫຼ້າສຸດ"</item>
+ <item msgid="1746820128097981528">"ສະແດງເສດສີໃນຈໍສະແດງຜົນທີ່ໂຟກັສຫຼ້າສຸດ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 3046b4f..d1f1344 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ບໍ່ສາມາດອັບເດດສຽງແວດລ້ອມໄດ້"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ). ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ). ຊ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ຂ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ). ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ). ຊ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ຂ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ). ຊ້າຍ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ). ຂວາ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ຮອງຮັບການແບ່ງປັນສຽງ"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ້າຍເທົ່ານັ້ນ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຂວາເທົ່ານັ້ນ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ້າຍ ແລະ ຂວາ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ການສະແດງຜົນໂດຍໃຊ້ຮາດແວຊ່ວຍ"</string>
<string name="media_category" msgid="8122076702526144053">"ມີເດຍ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"ກຳລັງກວດສອບ"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"ເປີດໃຊ້ໂໝດເຄັ່ງຄັດ"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"ກະພິບໜ້າຈໍເມື່ອມີແອັບເຮັດວຽກດົນເກີນໄປໃນເທຣດຫຼັກ"</string>
<string name="pointer_location" msgid="7516929526199520173">"ຕຳແໜ່ງໂຕຊີ້"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"ຕັ້ງການຈັດຕັ້ງປະຕິບັດ WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ບໍ່ສາມາດໃຊ້ການເລືອກນີ້ໄດ້ອີກຕໍ່ໄປແລ້ວ. ກະລຸນາລອງໃໝ່."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ໂໝດສີຮູບ"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"ໃຊ້ sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"ປິດນຳໃຊ້ແລ້ວ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index f81caa8..7f94010 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nepavyko atnaujinti aplinkos"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktyvus (tik medija). Akumuliatorius lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktyvus (tik medija), akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Prijungta (palaikomas garso įrašų bendrinimas). Akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Prijungta (palaikomas garso įrašų bendrinimas), akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Prijungta (palaikomas garso įrašų bendrinimas). Akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Prijungta (palaikomas garso įrašų bendrinimas). Akumuliatoriaus lygis dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Prijungta (palaikomas garso įrašų bendrinimas)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktyvus (tik medija)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Palaikomas garso įrašų bendrinimas"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktyvus (tik medija), tik kairė"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktyvus (tik medija), tik dešinė"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktyvus (tik medija), kairė ir dešinė"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Aparatinės įrangos paspartintas pateikimas"</string>
<string name="media_category" msgid="8122076702526144053">"Medija"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Stebėjimas"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Įgal. griežtas režimas"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Ekr. blyksės, kai pr. atl. ilgus proc. pgr. gijoje"</string>
<string name="pointer_location" msgid="7516929526199520173">"Žymiklio vieta"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"„WebView“ diegimas"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"„WebView“ diegimo nustatymas"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Šios parinkties nebegalima pasirinkti. Bandykite dar kartą."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Nuotraukos spalvos režimas"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Naudoti sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Išjungtas"</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 6d293be..da4ae31f 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Tikai ierīces displejs (noklusējums)"</item>
+ <item msgid="9161645858025071955">"Ārējais displejs"</item>
+ <item msgid="23651860565814477">"Pēdējais pieskāriens statusa joslai"</item>
+ <item msgid="7521112827893653392">"Saskaņā ar fokusu"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Rādīt ēnu tikai ierīces displejā"</item>
+ <item msgid="1955398604822147783">"Rādīt ēnu vienā ārējā displejā"</item>
+ <item msgid="391477482416751568">"Rādīt ēnu tajā displejā, kura statusa joslā pēdējoreiz tika veikta darbība"</item>
+ <item msgid="1746820128097981528">"Rādīt ēnu pēdējā fokusētajā displejā"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 987857b..50a56d4 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nevarēja atjaunināt apkārtnes skaņas"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktīvs (tikai multividei). Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktīvs (tikai multividei). Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Izveidots savienojums (atbalsta audio kopīgošanu)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktīvs (tikai multividei)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Atbalsta audio kopīgošanu"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktīvs (tikai multivide), tikai kreisās puses aparāts"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktīvs (tikai multivide), tikai labās puses aparāts"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktīvs (tikai multivide), kreisās un labās puses aparāts"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Aparatūras paātrinātā atveidošana"</string>
<string name="media_category" msgid="8122076702526144053">"Multivide"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Pārraudzība"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Precīzais rež. ir iespēj."</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Zibsnīt ekrānu, ja liet. ilgi darbojas galv. pav."</string>
<string name="pointer_location" msgid="7516929526199520173">"Rādītāja atrašanās vieta"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ieviešana"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Iestatīt WebView ieviešanu"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Šī iespēja vairs nav derīga. Mēģiniet vēlreiz."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Attēla krāsu režīms"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Izmantot sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Atspējota"</string>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 0490f28..4dce6bc 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Само на екранот на уредот (стандардно)"</item>
+ <item msgid="9161645858025071955">"Надворешен екран"</item>
+ <item msgid="23651860565814477">"Последен допир на статусната лента"</item>
+ <item msgid="7521112827893653392">"Засновано на фокус"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Прикажувај сенка само на екранот на уредот"</item>
+ <item msgid="1955398604822147783">"Прикажувај сенка на еден надворешен екран"</item>
+ <item msgid="391477482416751568">"Прикажувај сенка на екранот што последен имал интеракција со статусната лента"</item>
+ <item msgid="1746820128097981528">"Прикажувај сенка на последниот фокусиран екран"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"стандарден_екран"</item>
+ <item msgid="774789415968826925">"кој_било_надворешен_екран"</item>
+ <item msgid="7880769915418638436">"последен_допир_на_статусната_лента"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index fa65437..e86a6ce 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не можеше да се ажурира опкружувањето"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само аудиовизуелни содржини). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само аудиовизуелни содржини). Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Поврзано (поддржува споделување аудио). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Поврзано (поддржува споделување аудио). Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Поврзано (поддржува споделување аудио). Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Поврзано (поддржува споделување аудио). Десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Поврзано (поддржува споделување аудио)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само аудиовизуелни содржини)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддржува споделување аудио"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само аудиовизуелни содржини), само лево"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (само аудиовизуелни содржини), само десно"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (само аудиовизуелни содржини), лево и десно"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Хардверско забрзување"</string>
<string name="media_category" msgid="8122076702526144053">"Аудиовизуелни содржини"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Следење"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Овозможен е строг режим"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Трепкај со екранот при долги операции на главна нишка"</string>
<string name="pointer_location" msgid="7516929526199520173">"Локација на покажувач"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Примена на WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Поставете воведување WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Овој избор веќе не важи. Обидете се повторно."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Режим на боја на слика"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Користи sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Оневозможено"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 3e59d9f..f7ab232 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"സറൗണ്ടിംഗ്സ് അപ്ഡേറ്റ് ചെയ്യാനായില്ല"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"സജീവം (മീഡിയ മാത്രം). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"സജീവം (മീഡിയ മാത്രം). ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു). ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു). ഇടത് വശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു). വലത് വശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"സജീവം (മീഡിയ മാത്രം)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്ത് മാത്രം"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"സജീവം (മീഡിയ മാത്രം), വലതുവശത്ത് മാത്രം"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്തെയും വലതുവശത്തെയും"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ഹാർഡ്വെയർ ത്വരിതപ്പെടുത്തിയ റെൻഡറിംഗ്"</string>
<string name="media_category" msgid="8122076702526144053">"മീഡിയ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"മോണിറ്ററിംഗ്"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"ഫോഴ്സ്മോഡ് സജീവമാക്കി"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"പ്രധാന ത്രെഡിൽ ആപ്പുകൾ ദൈർഘ്യമേറിയ പ്രവർത്തനങ്ങൾ നടത്തുമ്പോൾ സ്ക്രീൻ ഫ്ലാഷ് ചെയ്യുക"</string>
<string name="pointer_location" msgid="7516929526199520173">"പോയിന്റർ ലൊക്കേഷൻ"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView നടപ്പാക്കൽ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView നടപ്പാക്കൽ സജ്ജമാക്കുക"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ഈ തിരഞ്ഞെടുപ്പിന് തുടർന്നങ്ങോട്ട് സാധുതയില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ചിത്ര വർണ്ണ മോഡ്"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ഉപയോഗിക്കുക"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"പ്രവർത്തനരഹിതമാക്കി"</string>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index ca103af..121371d 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Зөвхөн төхөөрөмжийн дэлгэц (өгөгдмөл)"</item>
+ <item msgid="9161645858025071955">"Гаднын дэлгэц"</item>
+ <item msgid="23651860565814477">"Статус самбарын сүүлийн үеийн хүрэлт"</item>
+ <item msgid="7521112827893653392">"Төвлөрөлд тулгуурласан"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Зөвхөн төхөөрөмж дээрх дэлгэцэд сүүдрийг харуулах"</item>
+ <item msgid="1955398604822147783">"Нэг гаднын дэлгэц дээр сүүдэр харуулах"</item>
+ <item msgid="391477482416751568">"Статус самбартай нь сүүлд харилцан үйлдэл хийсэн дэлгэц дээр сүүдэр харуулах"</item>
+ <item msgid="1746820128097981528">"Сүүлд төвлөрсөн дэлгэц дээр сүүдэр харуулах"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index e8e9e0c..4dc754e 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Орчин тойрныг шинэчилж чадсангүй"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Идэвхтэй (зөвхөн медиа). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Идэвхтэй (зөвхөн медиа). З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Холбогдсон (аудио хуваалцахыг дэмждэг). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Холбогдсон (аудио хуваалцахыг дэмждэг). З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Холбогдсон (аудио хуваалцахыг дэмждэг). Зүүн: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Холбогдсон (аудио хуваалцахыг дэмждэг). Баруун: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Холбогдсон (аудио хуваалцахыг дэмждэг)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Идэвхтэй (зөвхөн медиа)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио хуваалцахыг дэмждэг"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Идэвхтэй (зөвхөн медиа), зөвхөн зүүн"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Идэвхтэй (зөвхөн медиа), зөвхөн баруун"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Идэвхтэй (зөвхөн медиа), зүүн болон баруун"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Техник хангамжийн хурдасгасан үзүүлэлт"</string>
<string name="media_category" msgid="8122076702526144053">"Медиа"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Мониторинг"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Хатуу горимыг идэвхжүүлсэн"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Аппууд үндсэн хэлхээс дээр удаан хугацаанд үйлдлүүд хийх үед дэлгэцийг анивчуулах"</string>
<string name="pointer_location" msgid="7516929526199520173">"Чиглүүлэгчийн байршил"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView хэрэгжилт"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView хэрэгжилтийг тохируулах"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Энэ сонголт хүчингүй байна. Дахин оролдоно уу."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"\"Зургийн өнгө\" горим"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB-г ашиглах"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Идэвхгүй болсон"</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 1437a2c..eba95ae 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"फक्त डिव्हाइस डिस्प्ले (डीफॉल्ट)"</item>
+ <item msgid="9161645858025071955">"बाह्य डिस्प्ले"</item>
+ <item msgid="23651860565814477">"नवीनतम स्टेटस बार स्पर्श"</item>
+ <item msgid="7521112827893653392">"फोकसवर आधारित"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"फक्त डिव्हाइस डिस्प्लेवर शेड दाखवा"</item>
+ <item msgid="1955398604822147783">"एकल बाह्य डिस्प्लेवर शेड दाखवा"</item>
+ <item msgid="391477482416751568">"त्याच्या स्टेटस बारशी शेवटचा संवाद साधला आहे अशा डिस्प्लेवर शेड दाखवा"</item>
+ <item msgid="1746820128097981528">"शेवटच्या फोकस केलेल्या डिस्प्लेवर शेड दाखवा"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index f1f5cab..eef39c4 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"जवळपासचे आवाज अपडेट करता आले नाहीत"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"अॅक्टिव्ह आहे (फक्त मीडिया). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ॲक्टिव्ह आहे (फक्त मीडिया). डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बॅटरी, उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते). डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते). डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते). उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"अॅक्टिव्ह आहे (फक्त मीडिया)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडिओ शेअरिंगला सपोर्ट करते"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"अॅक्टिव्ह आहे (फक्त मीडिया), फक्त डावे"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"अॅक्टिव्ह आहे (फक्त मीडिया), फक्त उजवे"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"अॅक्टिव्ह आहे (फक्त मीडिया), डावे आणि उजवे"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेअर अॅक्सिलरेटेड रेंडरिंग"</string>
<string name="media_category" msgid="8122076702526144053">"मीडिया"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"परीक्षण"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"कठोर मोड सुरू"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"मुख्य थ्रेडवर अॅप्स मोठी कार्ये करतात तेव्हा स्क्रीन फ्लॅश करा"</string>
<string name="pointer_location" msgid="7516929526199520173">"पॉइंटर स्थान"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"वेबदृश्य अंमलबजावणी"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"वेबदृश्य अंमलबजावणी सेट करा"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ही निवड यापुढे वैध असणार नाही. पुन्हा प्रयत्न करा."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"चित्र रंग मोड"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB वापरा"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"बंद केले"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 412100c..ca4649c 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Tidak dapat mengemaskinikan persekitaran"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktif (media sahaja). Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktif (media sahaja), L: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Disambungkan (menyokong perkongsian audio). Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Disambungkan (menyokong perkongsian audio). L: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Disambungkan (menyokong perkongsian audio). Kiri: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Disambungkan (menyokong perkongsian audio). Kanan: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Disambungkan (menyokong perkongsian audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (media sahaja)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Menyokong perkongsian audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (media sahaja), kiri sahaja"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktif (media sahaja), kanan sahaja"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktif (media sahaja), kiri dan kanan"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Pemaparan dipercepat perkakasan"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Memantau"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Mod tegas didayakan"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Kelip skrin apabila apl beroperasi lama pada urutan utama"</string>
<string name="pointer_location" msgid="7516929526199520173">"Lokasi penuding"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Pelaksanaan WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Tetapkan pelaksanaan WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Pilihan ini tidak lagi sah. Cuba lagi."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Mod warna gambar"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Gunakan sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Dilumpuhkan"</string>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index aef22b2..91ce12a 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"စက်ဖန်သားပြင် သီးသန့် (မူရင်း)"</item>
+ <item msgid="9161645858025071955">"ပြင်ပဖန်သားပြင်"</item>
+ <item msgid="23651860565814477">"နောက်ဆုံး အခြေအနေပြဘား တို့ထိမှု"</item>
+ <item msgid="7521112827893653392">"ပြသမှုအခြေပြု"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"စက်ဖန်သားပြင်တွင်သာ အရိပ်ပြပါ"</item>
+ <item msgid="1955398604822147783">"ပြင်ပဖန်သားပြင်တစ်ခုတွင် အရိပ်ကိုပြပါ"</item>
+ <item msgid="391477482416751568">"အခြေအနေပြဘား နောက်ဆုံးပြန်လှန်တုံ့ပြန်ထားသော ဖန်သားပြင်တွင် အရိပ်ကိုပြပါ"</item>
+ <item msgid="1746820128097981528">"နောက်ဆုံးပြထားသော ဖန်သားပြင်တွင် အရိပ်ကိုပြပါ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"မူရင်းဖန်သားပြင်"</item>
+ <item msgid="774789415968826925">"မည်သည့်ပြင်ပဖန်သားပြင်မဆို"</item>
+ <item msgid="7880769915418638436">"အခြေအနေပြဘား နောက်ဆုံးထိတွေ့မှု"</item>
+ <item msgid="4313165186636015195">"ပြသထားသောဖန်သားပြင်"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index cf493cf..1225e4c 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ဝန်းကျင်အသံ အပ်ဒိတ်လုပ်၍ မရလိုက်ပါ"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"အသုံးပြုနေသည် (မီဒီယာသီးသန့်)။ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"အသုံးပြုနေသည် (မီဒီယာသီးသန့်)။ ဘက်ထရီ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>။"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ဘက်ထရီ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>။"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ဘယ်- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ညာ- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"သုံးနေသည် (မီဒီယာသီးသန့်)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ဘယ်သီးသန့်"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ညာသီးသန့်"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ဘယ်နှင့် ညာ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ဟာ့ဒ်ဝဲ အရှိန်မြှင့် ပုံဖော်ခြင်း"</string>
<string name="media_category" msgid="8122076702526144053">"မီဒီယာ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"စောင့်ကြည့်စစ်ဆေးခြင်း"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"တင်းကြပ်သောစနစ် ဖွင့်ရန်"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"အက်ပ်လုပ်ဆောင်မှု ရှည်ကြာလျှင် စကရင်ပြန်စသည်"</string>
<string name="pointer_location" msgid="7516929526199520173">"မြား၏တည်နေရာ"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView အကောင်အထည်ဖော်မှု"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView အကောင်အထည်ဖော်မှု သတ်မှတ်ပါ"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ဤရွေးချယ်မှု မှန်ကန်မှု မရှိတော့ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ဓာတ်ပုံအရောင်မုဒ်"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ကို အသုံးပြုပါ"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"ပိတ်ထားသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 88f193c..c0106c4 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Bare enhetsskjermen (standard)"</item>
+ <item msgid="9161645858025071955">"Ekstern skjerm"</item>
+ <item msgid="23651860565814477">"Siste trykk på statusfeltet"</item>
+ <item msgid="7521112827893653392">"Fokusbasert"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Vis skyggen bare på enhetsskjermen"</item>
+ <item msgid="1955398604822147783">"Vis skyggen på én ekstern skjerm"</item>
+ <item msgid="391477482416751568">"Vis skyggen på skjermen hvor det ble trykket på statusfeltet sist"</item>
+ <item msgid="1746820128097981528">"Vis skyggen på den sist fokuserte skjermen"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"Standardskjerm"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 045318a..7c9b10f 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Kunne ikke oppdatere omgivelsene"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (bare medieinnhold) <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (bare medieinnhold). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Tilkoblet (støtter lyddeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Tilkoblet (støtter lyddeling). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Tilkoblet (støtter lyddeling). Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Tilkoblet (støtter lyddeling). Høyre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Tilkoblet (støtter lyddeling)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (bare medieinnhold)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Støtter lyddeling"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (bare medieinnhold), bare venstre"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (bare medieinnhold), bare høyre"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (bare medieinnhold), høyre og venstre"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Maskinvareakselerert gjengivelse"</string>
<string name="media_category" msgid="8122076702526144053">"Medier"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Overvåking"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Slå på streng modus"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Skjermblink ved lange apphandlinger på hovedtråd"</string>
<string name="pointer_location" msgid="7516929526199520173">"Pekerplassering"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Angi WebView-implementering"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Dette valget er ikke gyldig lenger. Prøv på nytt."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Fargemodus for bilder"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Bruk sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Slått av"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 1989994..23d6343 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"२"</item>
<item msgid="4779928470672877922">"३"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"डिभाइसको डिस्प्ले मात्र (डिफल्ट)"</item>
+ <item msgid="9161645858025071955">"बाह्य डिस्प्ले"</item>
+ <item msgid="23651860565814477">"पछिल्लो पटक स्ट्याटस बारमा टच गरिएको"</item>
+ <item msgid="7521112827893653392">"फोकसमा आधारित"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"यो सेड डिभाइसकै डिस्प्लेमा मात्र देखाउनुहोस्"</item>
+ <item msgid="1955398604822147783">"एउटा बाह्य डिस्प्लेमा सेड देखाउनुहोस्"</item>
+ <item msgid="391477482416751568">"पछिल्लो पटक जुन डिस्प्लेको स्ट्याटस बारमा टच गरिएको थियो सो डिस्प्लेमा सेड देखाउनुहोस्"</item>
+ <item msgid="1746820128097981528">"पछिल्लो पटक फोकस गरिएको डिस्प्लेमा सेड देखाउनुहोस्"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d637a4b..e2e7a8f 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"वरपरका आवाजसम्बन्धी सेटिङ अपडेट गर्न सकिएन"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"सक्रिय छ (मिडिया मात्र)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"सक्रिय छ (मिडिया मात्र)। बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री।"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ)। बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ)। बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ)। दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"सक्रिय छ (मिडिया मात्र)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"अडियो सेयर गर्न मिल्छ"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"सक्रिय छ (मिडिया मात्र), बायाँ मात्र"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"सक्रिय छ (मिडिया मात्र), दायाँ मात्र"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"सक्रिय छ (मिडिया मात्र), बायाँ र दायाँ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेयरले बढाएको रेन्डरिङ"</string>
<string name="media_category" msgid="8122076702526144053">"मिडिया"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"अनुगमन गरिँदै छ"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड अन गर्नुहोस्"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"एपले मुख्य थ्रेडमा लामा गतिविधि गर्दा स्क्रिन फ्ल्यास गर्नुहोस्"</string>
<string name="pointer_location" msgid="7516929526199520173">"पोइन्टरको स्थान"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView कार्यान्वयन सेट गर्नुहोस्"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"यो छनोट अब मान्य छैन। फेरि प्रयास गर्नुहोस्।"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"चित्र रङ्ग मोड"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB प्रयोग गर्नुहोस्"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"अफ गरिएको छ"</string>
@@ -657,8 +685,8 @@
<string name="add_guest_failed" msgid="8074548434469843443">"नयाँ अतिथि बनाउन सकिएन"</string>
<string name="user_nickname" msgid="262624187455825083">"उपनाम"</string>
<string name="edit_user_info_message" msgid="6677556031419002895">"यो डिभाइस प्रयोग गर्ने सबै जना तपाईंले छनौट गर्ने नाम र फोटो देख्न सक्ने छन्।"</string>
- <string name="user_add_user" msgid="7876449291500212468">"प्रयोगकर्ता कनेक्ट गर्नुहोस्"</string>
- <string name="guest_new_guest" msgid="3482026122932643557">"अतिथि कनेक्ट गर्नुहोस्"</string>
+ <string name="user_add_user" msgid="7876449291500212468">"प्रयोगकर्ता थप्नुहोस्"</string>
+ <string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अथिति हटाउनुहोस्"</string>
<string name="guest_reset_guest" msgid="6110013010356013758">"अतिथि सत्र रिसेट गर्नुहोस्"</string>
<string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"अतिथिका रूपमा ब्राउज गर्ने सेसन रिसेट गर्ने हो?"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index 12c9551..669326a 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Alleen apparaatscherm (standaard)"</item>
+ <item msgid="9161645858025071955">"Extern scherm"</item>
+ <item msgid="23651860565814477">"Laatste aanraking van statusbalk"</item>
+ <item msgid="7521112827893653392">"Op focus gebaseerd"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Alleen paneel tonen op apparaatscherm"</item>
+ <item msgid="1955398604822147783">"Venster tonen op één extern scherm"</item>
+ <item msgid="391477482416751568">"Venster tonen op scherm waarop de laatst interactie met de statusbalk was"</item>
+ <item msgid="1746820128097981528">"Venster tonen op laatste gefocuste scherm"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 481479e..6dfcc7b 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Kan omgeving niet updaten"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actief (alleen media). Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actief (alleen media), L: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Verbonden (ondersteunt audio delen), batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Verbonden (ondersteunt audio delen), L: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Verbonden (ondersteunt audio delen). Links: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Verbonden (ondersteunt audio delen). Rechts: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Verbonden (ondersteunt audio delen)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actief (alleen media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ondersteunt audio delen"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actief (alleen media), alleen links"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actief (alleen media), alleen rechts"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actief (alleen media), links en rechts"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Rendering met hardwareversnelling"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Controle"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strikte modus staat aan"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Knipperend scherm bij lange bewerkingen door apps"</string>
<string name="pointer_location" msgid="7516929526199520173">"Cursorlocatie"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementatie"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView-implementatie instellen"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Deze keuze is niet meer geldig. Probeer het opnieuw."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Kleurenmodus voor afbeeldingen"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB gebruiken"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Uitgezet"</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 9782303..3b906c4 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"କେବଳ ଡିଭାଇସ ଡିସପ୍ଲେ (ଡିଫଲ୍ଟ)"</item>
+ <item msgid="9161645858025071955">"ଏକ୍ସଟର୍ନଲ ଡିସପ୍ଲେ"</item>
+ <item msgid="23651860565814477">"ନବୀନତମ ଷ୍ଟାଟସ ବାର ଟଚ"</item>
+ <item msgid="7521112827893653392">"ଫୋକସ-ଆଧାରିତ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"କେବଳ ଡିଭାଇସରେ ଡିସପ୍ଲେ ସେଡ ଦେଖାନ୍ତୁ"</item>
+ <item msgid="1955398604822147783">"ସିଙ୍ଗଲ ଏକ୍ସଟର୍ନଲ ଡିସପ୍ଲେରେ ସେଡ ଦେଖାନ୍ତୁ"</item>
+ <item msgid="391477482416751568">"ଡିସପ୍ଲେରେ ଏପରି ସେଡ ଦେଖାନ୍ତୁ ଯାହା ସହିତ ଏହାର ଷ୍ଟାଟସ ବାର ଶେଷ ଥର ପାଇଁ ଇଣ୍ଟରାକ୍ଟ ହୋଇଛି"</item>
+ <item msgid="1746820128097981528">"ଫୋକସ କରାଯାଇଥିବା ଗତ ଡିସପ୍ଲେରେ ସେଡ ଦେଖାନ୍ତୁ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index bcde4e9..44c819c 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ପରିପାର୍ଶ୍ୱକୁ ଅପଡେଟ କରାଯାଇପାରିଲା ନାହିଁ"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ।"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସପୋର୍ଟ କରେ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ।"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସପୋର୍ଟ କରେ)। ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ଅଡିଓ ସେୟାରିଂକୁ ସପୋର୍ଟ କରେ"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), କେବଳ ବାମ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), କେବଳ ଡାହାଣ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), ବାମ ଏବଂ ଡାହାଣ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ହାର୍ଡୱେର୍ ଆକ୍ସଲରେଟେଡ୍ ରେଣ୍ଡରିଙ୍ଗ"</string>
<string name="media_category" msgid="8122076702526144053">"ମିଡିଆ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"ମନିଟରିଙ୍ଗ"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"କଡ଼ା ମୋଡ୍ ସକ୍ଷମ କରାଯାଇଛି"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"ମୁଖ୍ୟ ଥ୍ରେଡ୍ରେ ଆପ୍ ଦୀର୍ଘ ସମୟ କାର୍ଯ୍ୟ କଲେ ସ୍କ୍ରୀନ୍ ଫ୍ଲାଶ୍ କରନ୍ତୁ"</string>
<string name="pointer_location" msgid="7516929526199520173">"ପଏଣ୍ଟର୍ ଲୋକେସନ୍"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"ୱେବ୍ଭ୍ୟୁ ପ୍ରୟୋଗ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView କାର୍ଯ୍ୟକାରିତାକୁ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ଏହି ପସନ୍ଦ ଆଉ ମାନ୍ୟ ନାହିଁ। ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ପିକ୍ଚର୍ ରଙ୍ଗ ମୋଡ୍"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"ଅକ୍ଷମ ହୋଇଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index afb85ca..115214f 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"ਸਿਰਫ਼ ਡੀਵਾਈਸ ਦੀ ਡਿਸਪਲੇ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
+ <item msgid="9161645858025071955">"ਬਾਹਰੀ ਡਿਸਪਲੇ"</item>
+ <item msgid="23651860565814477">"ਨਵੀਨਤਮ ਸਥਿਤੀ ਪੱਟੀ ਸਪਰਸ਼"</item>
+ <item msgid="7521112827893653392">"ਫੋਕਸ-ਆਧਾਰਿਤ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"ਸਿਰਫ਼ ਡੀਵਾਈਸ ਦੀ ਡਿਸਪਲੇ \'ਤੇ ਸ਼ੇਡ ਦਿਖਾਓ"</item>
+ <item msgid="1955398604822147783">"ਇਕਹਿਰੇ ਬਾਹਰੀ ਡਿਸਪਲੇ \'ਤੇ ਸ਼ੇਡ ਦਿਖਾਓ"</item>
+ <item msgid="391477482416751568">"ਉਸ ਡਿਸਪਲੇ \'ਤੇ ਸ਼ੇਡ ਦਿਖਾਓ ਜਿਸ ਦੀ ਸਥਿਤੀ ਪੱਟੀ ਨਾਲ ਅਖੀਰ ਵਾਰ ਅੰਤਰਕਿਰਿਆ ਕੀਤੀ ਗਈ ਸੀ"</item>
+ <item msgid="1746820128097981528">"ਆਖਰੀ ਵਾਰ ਫੋਕਸ ਕੀਤੇ ਗਏ ਡਿਸਪਲੇ \'ਤੇ ਸ਼ੇਡ ਦਿਖਾਓ"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 821c84e..731c195 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ਆਲੇ-ਦੁਆਲੇ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ।"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ।"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਸਿਰਫ਼ ਖੱਬਾ"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਸਿਰਫ਼ ਸੱਜਾ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਖੱਬਾ ਅਤੇ ਸੱਜਾ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਟਿਡ ਰੈਂਡਰਿੰਗ"</string>
<string name="media_category" msgid="8122076702526144053">"ਮੀਡੀਆ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"ਨਿਰੀਖਣ ਕਰਨਾ"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"ਸਟ੍ਰਿਕਟ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"ਐਪਾਂ ਵੱਲੋਂ ਮੁੱਖ ਥ੍ਰੈੱਡ \'ਤੇ ਲੰਬੀਆਂ ਕਾਰਵਾਈਆਂ ਕਰਨ \'ਤੇ ਸਕ੍ਰੀਨ ਫਲੈਸ਼ ਕਰੋ"</string>
<string name="pointer_location" msgid="7516929526199520173">"ਪੁਆਇੰਟਰ ਟਿਕਾਣਾ"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲੀਕਰਨ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView ਅਮਲੀਕਰਨ ਸੈੱਟ ਕਰੋ"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ਇਹ ਚੋਣ ਹੁਣ ਵੈਧ ਨਹੀਂ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"ਤਸਵੀਰ ਰੰਗ ਮੋਡ"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ਵਰਤੋਂ ਕਰੋ"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"ਬੰਦ ਹੈ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 59791c0..6daf1b2 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Tylko wyświetlanie na urządzeniu (domyślnie)"</item>
+ <item msgid="9161645858025071955">"Wyświetlacz zewnętrzny"</item>
+ <item msgid="23651860565814477">"Ostatnie dotknięcie paska stanu"</item>
+ <item msgid="7521112827893653392">"Na podstawie aktywnego wyświetlacza"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Pokaż cień tylko na wyświetlaczu urządzenia"</item>
+ <item msgid="1955398604822147783">"Pokazuj cień na pojedynczym wyświetlaczu zewnętrznym"</item>
+ <item msgid="391477482416751568">"Pokazuj cień na wyświetlaczu, na którym ostatnio nastąpiła interakcja z paskiem stanu"</item>
+ <item msgid="1746820128097981528">"Pokazuj cień na ostatnim aktywnym wyświetlaczu"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 9f6eb4c..b9adae2 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nie udało się zaktualizować otoczenia"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktywne (tylko multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktywne (tylko multimedia), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Połączone (obsługa udostępniania dźwięku), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Połączone (obsługa udostępniania dźwięku), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Połączone (obsługa udostępniania dźwięku). Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Połączone (obsługa udostępniania dźwięku). Prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Połączone (obsługa udostępniania dźwięku)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktywne (tylko multimedia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Obsługa udostępniania dźwięku"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktywne (tylko multimedia), tylko lewa"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktywne (tylko multimedia), tylko prawa"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktywne (tylko multimedia), lewa i prawa"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Sprzętowa akceleracja renderowania"</string>
<string name="media_category" msgid="8122076702526144053">"Multimedia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitorowanie"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Tryb ścisły włączony"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Miganie ekranu podczas długich operacji w wątku głównym"</string>
<string name="pointer_location" msgid="7516929526199520173">"Lokalizacja wskaźnika"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacja WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ustaw implementację WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ta opcja nie jest już obsługiwana. Spróbuj ponownie."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Tryb kolorów obrazu"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Użyj sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Wyłączone"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 72f25be..5b3bb06 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Não foi possível atualizar o som ambiente"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas mídia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas mídia). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (aceita compartilhamento de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (aceita compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (aceita compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (aceita compartilhamento de áudio). Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (aceita compartilhamento de áudio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas mídia), somente direito"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas mídia), esquerdo e direito"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Renderização acelerada por hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Mídia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoramento"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modo restrito ativado"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Piscar tela se apps demorarem no processo principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Localização do cursor"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Configurar implementação do WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opção não é mais válida. Tente novamente."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modo de cor da imagem"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Usar sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Desativado"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index d09caad..e6b343a 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Não foi possível atualizar o ambiente"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas para multimédia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas para multimédia). E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ligado (suporta partilha de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ligado (suporta partilha de áudio). E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ligado (suporta a partilha de áudio). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ligado (suporta a partilha de áudio). Direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ligado (suporta a partilha de áudio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas para multimédia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Suporta partilha de áudio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas para multimédia), apenas esquerdo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas para multimédia), apenas direito"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas para multimédia), esquerdo e direito"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Conversão acelerada de hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Multimédia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitorização"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modo rigoroso ativado"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Piscar ecrã se app fazem oper. prolong. no tópico princ."</string>
<string name="pointer_location" msgid="7516929526199520173">"Localização do ponteiro"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Definir implementação WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opção já não é válida. Tente novamente."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modo de cor da imagem"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Usar sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Desativado"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 72f25be..5b3bb06 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Não foi possível atualizar o som ambiente"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas mídia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas mídia). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (aceita compartilhamento de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectado (aceita compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectado (aceita compartilhamento de áudio). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectado (aceita compartilhamento de áudio). Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectado (aceita compartilhamento de áudio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas mídia), somente direito"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas mídia), esquerdo e direito"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Renderização acelerada por hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Mídia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoramento"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modo restrito ativado"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Piscar tela se apps demorarem no processo principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Localização do cursor"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Configurar implementação do WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opção não é mais válida. Tente novamente."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modo de cor da imagem"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Usar sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Desativado"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 8bfeb70..edaf788 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Numai pe ecranul dispozitivului (prestabilit)"</item>
+ <item msgid="9161645858025071955">"Ecran extern"</item>
+ <item msgid="23651860565814477">"Cea mai recentă atingere a barei de stare"</item>
+ <item msgid="7521112827893653392">"În funcție de focalizare"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Afișează umbra doar pe ecranul dispozitivului"</item>
+ <item msgid="1955398604822147783">"Afișează umbra pe un singur ecran extern"</item>
+ <item msgid="391477482416751568">"Afișează umbra pe ecranul pe care s-a interacționat ultima dată cu bara de stare"</item>
+ <item msgid="1746820128097981528">"Afișează umbra pe ultimul ecran focalizat"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 26fdce8..13c9032 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nu s-a putut actualiza zona din jur"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activ (numai pentru conținut media). Nivelul bateriei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activ (numai pentru conținut media): nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectat (acceptă permiterea accesului la audio). Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Conectat (acceptă permiterea accesului la audio), nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Conectat (acceptă permiterea accesului la audio). Nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Conectat (acceptă permiterea accesului la audio). Nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Conectat (acceptă permiterea accesului la audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activ (numai pentru conținut media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Acceptă permiterea accesului la audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activ (numai pentru conținut media), numai stânga"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activ (numai pentru conținut media), numai dreapta"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activ (numai pentru conținut media), stânga și dreapta"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Redare accelerată hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitorizare"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Modul Strict activat"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Iluminare intermitentă la operații lungi pe firul principal"</string>
<string name="pointer_location" msgid="7516929526199520173">"Locația indicatorului"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementare WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Setează implementarea WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Această opțiune nu mai este validă. Încearcă din nou."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modul de culori pentru imagini"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Folosește sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Dezactivat"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 52b2549..a31168e 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Только экран устройства (по умолчанию)"</item>
+ <item msgid="9161645858025071955">"Внешний дисплей"</item>
+ <item msgid="23651860565814477">"Последнее нажатие на строку состояния"</item>
+ <item msgid="7521112827893653392">"Последняя активность"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Показывать тень только на экране устройства"</item>
+ <item msgid="1955398604822147783">"Показывать панель уведомлений на единственном внешнем дисплее"</item>
+ <item msgid="391477482416751568">"Показывать панель уведомлений на дисплее, со строкой состояния которого пользователь взаимодействовал в последний раз"</item>
+ <item msgid="1746820128097981528">"Показывать панель уведомлений на дисплее, на который пользователь перешел в последний раз"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index bf92e20..831623d 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не удалось отрегулировать окружающие звуки."</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (Л)."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (П)."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Подключено (поддерживается отправка аудио)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Используется (только для медиа)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддерживается отправка аудио"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Используется (только для медиа), только левый"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Используется (только для медиа), правый наушник"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Используется (только для медиа), левый и правый наушники"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Аппаратное ускорение отрисовки"</string>
<string name="media_category" msgid="8122076702526144053">"Мультимедиа"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Мониторинг"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Строгий режим"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Подсвечивать экран во время длительных операций"</string>
<string name="pointer_location" msgid="7516929526199520173">"Место касания"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Сервис WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Настройки сервиса WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Вариант недействителен. Повторите попытку."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Цветовой режим"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Использовать sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Отключено"</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index 66f1ba7..f9e9ae1 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"උපාංග සංදර්ශකය පමණි (පෙරනිමි)"</item>
+ <item msgid="9161645858025071955">"බාහිර සංදර්ශකය"</item>
+ <item msgid="23651860565814477">"නවතම තත්ත්ව තීරු ස්පර්ශය"</item>
+ <item msgid="7521112827893653392">"නාභිගත කිරීම-පාදක"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"උපාංග සංදර්ශකයේ පමණක් සෙවන පෙන්වන්න"</item>
+ <item msgid="1955398604822147783">"තනි බාහිර සංදර්ශකය මත වැස්ම පෙන්වන්න"</item>
+ <item msgid="391477482416751568">"තත්ත්ව තීරුව අවසන් වරට අන්තර්ක්රියා කළ වැස්ම දර්ශනයේ පෙන්වන්න."</item>
+ <item msgid="1746820128097981528">"අවසන් වරට නාභිගත කළ සංදර්ශකයේ වැස්ම පෙන්වන්න"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"නාභිගත කළ_සංදර්ශකය"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 94e1ed4..dcfb914 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"වටපිටාව යාවත්කාලීන කළ නොහැකි විය"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ක්රියාත්මකයි (මාධ්ය පමණයි). බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ක්රියාත්මකයි (මාධ්ය පමණයි), බැටරිය ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීමට සහය දක්වයි). බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීමට සහය දක්වයි). බැටරිය ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීමට සහය දක්වයි). වම: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීමට සහය දක්වයි). දකුණ: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීමට සහය දක්වයි)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"සක්රිය (මාධ්ය පමණි)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ශ්රව්ය බෙදා ගැනීම සහය දක්වයි"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"සක්රිය (මාධ්ය පමණි), වම පමණි"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"සක්රිය (මාධ්ය පමණි), දකුණ පමණි"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"සක්රිය (මාධ්ය පමණි), වම සහ දකුණ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"දෘඩාංග වේගය වැඩි කළ පිරිනැමීම"</string>
<string name="media_category" msgid="8122076702526144053">"මාධ්ය"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"නිරීක්ෂණය"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"තදබල ආකාරය සබල කිරීම"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"මූලික පොටේ යෙදුම්, දිගු මෙහෙයුම් කරන විට තිරය ෆ්ලෑෂ් කරන්න"</string>
<string name="pointer_location" msgid="7516929526199520173">"සූචක පිහිටීම"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ක්රියාත්මක කිරීම"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView ක්රියාත්මක කිරීම සකසන්න"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"මෙම තෝරා ගැනීම තව දුරටත් වලංගු නැත. නැවත උත්සාහ කරන්න."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"පින්තූර වර්ණ ප්රකාරය"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB භාවිතා කරන්න"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"අබලයි"</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index f8363cd..2d39d3a 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Iba obrazovka zariadenia (predvolené)"</item>
+ <item msgid="9161645858025071955">"Externá obrazovka"</item>
+ <item msgid="23651860565814477">"Posledné klepnutie na stavový riadok"</item>
+ <item msgid="7521112827893653392">"Na základe označenia"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Zobraziť panel iba na obrazovke zariadenia"</item>
+ <item msgid="1955398604822147783">"Zobraziť panel na jednej externej obrazovke"</item>
+ <item msgid="391477482416751568">"Zobraziť panel na obrazovke, na ktorej došlo naposledy k interakcii so stavovým riadkom"</item>
+ <item msgid="1746820128097981528">"Zobraziť panel na poslednej označenej obrazovke"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 6170ac5..86e8274 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Okolie sa nepodarilo aktualizovať"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktívne (iba médiá). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktívne (iba médiá). Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batérie, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Pripojené (podporuje zdieľanie zvuku). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Pripojené (podporuje zdieľanie zvuku). Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Pripojené (podporuje zdieľanie zvuku). Ľavá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Pripojené (podporuje zdieľanie zvuku). Pravá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Pripojené (podporuje zdieľanie zvuku)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktívne (iba médiá)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje zdieľanie zvuku"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktívne (iba médiá), iba ľavá strana"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktívne (iba médiá), iba pravá strana"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktívne (iba médiá), ľavá aj pravá strana"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardvérom zrýchlené vykresľovanie"</string>
<string name="media_category" msgid="8122076702526144053">"Médiá"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitorovanie"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Povoliť prísny režim"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Blikať pri dlhých operáciách hlavného vlákna"</string>
<string name="pointer_location" msgid="7516929526199520173">"Umiestnenie kurzora"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementácia WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Nastaviť implementáciu WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Táto voľba už nie je platná. Skúste to znova."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Farebný režim obrázka"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Použije sa sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Vypnuté"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 2a128ef..498224a 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Prikaz samo v napravi (privzeto)"</item>
+ <item msgid="9161645858025071955">"Zunanji zaslon"</item>
+ <item msgid="23651860565814477">"Zadnji dotik vrstice stanja"</item>
+ <item msgid="7521112827893653392">"Na podlagi fokusa"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Prikaz podokna samo na zaslonu naprave"</item>
+ <item msgid="1955398604822147783">"Prikaz podokna na enem zunanjem zaslonu"</item>
+ <item msgid="391477482416751568">"Prikaz podokna na zaslonu, na katerem je bila izvedena zadnja interakcija z vrstico stanja"</item>
+ <item msgid="1746820128097981528">"Prikaz podokna na zadnjem zaslonu s fokusom"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 39b61d9..28ae8e1 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Okolice ni bilo mogoče posodobiti"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo predstavnost). Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo predstavnost), baterija – L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podpira deljenje zvoka), baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Povezano (podpira deljenje zvoka), baterija – L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Povezano (podpira deljenje zvoka). Levo – baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Povezano (podpira deljenje zvoka). Desno – baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Povezano (podpira deljenje zvoka)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo predstavnost)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podpira deljenje zvoka"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo predstavnost), samo levo"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo predstavnost), samo desno"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo predstavnost), levo in desno"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Upodabljanje s strojnim pospeševanjem"</string>
<string name="media_category" msgid="8122076702526144053">"Predstavnost"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Spremljanje"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strog način je omogočen"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Osveži zaslon pri dolgih postopkih v glavni niti."</string>
<string name="pointer_location" msgid="7516929526199520173">"Mesto kazalca"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Izvedba spletnega pogleda"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Nastavitev izvedbe spletnega pogleda"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ta izbira ni več veljavna. Poskusite znova."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Način barv slike"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Uporaba sRGB-ja"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Onemogočeno"</string>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 3b0994a..98429ce 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Vetëm ekrani i pajisjes (parazgjedhja)"</item>
+ <item msgid="9161645858025071955">"Ekrani i jashtëm"</item>
+ <item msgid="23651860565814477">"Prekja e fundit e shiritit të statusit"</item>
+ <item msgid="7521112827893653392">"Bazuar te fokusi"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Shfaq hijen vetëm në ekranin e pajisjes"</item>
+ <item msgid="1955398604822147783">"Shfaq panelin në një ekran të vetëm të jashtëm"</item>
+ <item msgid="391477482416751568">"Shfaq panelin në ekranin me shiritin e statusit të të cilit është ndërvepruar së fundi"</item>
+ <item msgid="1746820128097981528">"Shfaq panelin në ekranin e fokusuar së fundi"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2d2c02b..4e6ec9f 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ambienti rrethues nuk mund të përditësohej"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (vetëm për media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (vetëm për media). Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Lidhur (mbështet ndarjen e audios). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Lidhur (mbështet ndarjen e audios). Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Lidhur (mbështet ndarjen e audios). Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Lidhur (mbështet ndarjen e audios). Djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Lidhur (mbështet ndarjen e audios)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (vetëm për media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mbështet ndarjen e audios"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (vetëm për media), vetëm majtas"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (vetëm për media), vetëm djathtas"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (vetëm për media), majtas dhe djathtas"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Interpretimi i përshpejtuar i harduerit"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitorimi"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Aktivizo modalitetin e rreptë"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Ndriço ekranin kur aplikacionet kryejnë operacione të gjata teksa bashkëveprojnë"</string>
<string name="pointer_location" msgid="7516929526199520173">"Vendndodhja e treguesit"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Zbatimi i WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Cakto zbatimin e WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Kjo zgjedhje nuk është më e vlefshme. Provo përsëri."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Modalitti i ngjyrave të figurës"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Përdor sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Çaktivizuar"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index c053094..96924b9 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ажурирање окружења није успело"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само за медије). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само за медије). Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Повезано (подржава дељење звука), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Повезано (подржава дељење звука), лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Повезано (подржава дељење звука). Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Повезано (подржава дељење звука). Десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Повезано (подржава дељење звука)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активан (само за медије)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Подржава дељење звука"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активан (само за медије), само лево"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активан (само за медије), само десно"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активан (само за медије), лево и десно"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Хардверски убрзано приказивање"</string>
<string name="media_category" msgid="8122076702526144053">"Медији"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Надгледање"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Омогућен је строги режим"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Екран трепери када апликације обављају дуге операције на главној нити"</string>
<string name="pointer_location" msgid="7516929526199520173">"Локација показивача"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Примена WebView-а"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Подесите примену WebView-а"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Овај избор више није важећи. Пробајте поново."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Режим боја слика"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Користи sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Онемогућено је"</string>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 8a77fdd..1a8c9d8 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -295,7 +295,7 @@
<item msgid="7521112827893653392">"Fokusbaserad"</item>
</string-array>
<string-array name="shade_display_awareness_summaries">
- <item msgid="2964753205732912921">"Visa endast skugga på enhetens skärm"</item>
+ <item msgid="2964753205732912921">"Visa panelen endast på enhetens skärm"</item>
<item msgid="1955398604822147783">"Visa skugga på en enda extern skärm"</item>
<item msgid="391477482416751568">"Visa skugga på skärmen där statusfältet senast interagerades med"</item>
<item msgid="1746820128097981528">"Visa skugga på skärmen som sist var i fokus"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e0897cb..3c7aff6 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Det gick inte att uppdatera omgivningsläget"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (endast media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (endast media). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ansluten (ljuddelning stöds). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ansluten (ljuddelning stöds). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ansluten (ljuddelning stöds). Vänster: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ansluten (ljuddelning stöds). Höger: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ansluten (ljuddelning stöds)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (endast media)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ljuddelning stöds"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (endast media), endast vänster"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (endast media), endast höger"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (endast media), vänster och höger"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hårdvaruaccelererad rendering"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Övervakning"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Strikt läge aktiverat"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Tänd skärm när app gör omfattande åtgärd på huvudtråd"</string>
<string name="pointer_location" msgid="7516929526199520173">"Pekarens plats"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ange WebView-implementering"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Det här alternativet är inte längre giltigt. Försök igen."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Färgläge för bilder"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Använd sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Inaktiverad"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 652c358..2ec6256 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Kwenye skrini ya kifaa pekee (Chaguomsingi)"</item>
+ <item msgid="9161645858025071955">"Skrini ya nje"</item>
+ <item msgid="23651860565814477">"Matumizi ya hivi majuzi zaidi ya sehemu ya arifa"</item>
+ <item msgid="7521112827893653392">"Inayoangaziwa"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Onyesha kiwango kwenye skrini ya kifaa pekee"</item>
+ <item msgid="1955398604822147783">"Onyesha kiwango kwenye skrini moja ya nje"</item>
+ <item msgid="391477482416751568">"Onyesha kiwango kwenye skrini ambayo sehemu yake ya arifa ilitumiwa hivi majuzi"</item>
+ <item msgid="1746820128097981528">"Onyesha kiwango kwenye skrini iliyoangaziwa mwisho kabisa"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f12597f..4f520b4 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Imeshindwa kusasisha mazingira"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Inatumika (maudhui pekee). Chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Inatumika (maudhui pekee), Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Chaji imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Imeunganishwa (inaweza kusikiliza pamoja)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Inatumika (maudhui pekee)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Inaweza kutumia kipengele cha kusikiliza pamoja"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Inatumika (maudhui pekee), kushoto pekee"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Inatumika (maudhui pekee), kulia pekee"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Inatumika (maudhui pekee), kushoto na kulia"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Utekelezaji wa maunzi ulioharakishwa"</string>
<string name="media_category" msgid="8122076702526144053">"Maudhui"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Ufuatiliaji"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Hali makinifu imewashwa"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Fanya skrini imemeteke programu zinapoendeleza shughuli ndefu kwenye skrini kuu"</string>
<string name="pointer_location" msgid="7516929526199520173">"Mahali pa kiashiria"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Utekelezaji wa WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Weka utekelezaji wa WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Chaguo hili halipo tena. Jaribu tena."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Hali ya rangi ya picha"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Tumia sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Imezimwa"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 503cd8f..f42e476 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"சாதனக் காட்சி மட்டும் (இயல்பு)"</item>
+ <item msgid="9161645858025071955">"வெளிப்புறக் காட்சி"</item>
+ <item msgid="23651860565814477">"சமீபத்திய நிலைப் பட்டித் தொடுகை"</item>
+ <item msgid="7521112827893653392">"ஃபோகஸ் அடிப்படையிலானது"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"சாதனக் காட்சியில் மட்டும் ஷேடைக் காட்டும்"</item>
+ <item msgid="1955398604822147783">"ஒற்றை வெளிப்புறக் காட்சியில் ஷேடைக் காட்டும்"</item>
+ <item msgid="391477482416751568">"கடைசியாக நிலைப் பட்டி தொடர்புகொண்ட ஷேடைக் காட்சியில் காட்டும்"</item>
+ <item msgid="1746820128097981528">"கடைசியாக ஃபோகஸ் செய்யப்பட்ட காட்சியில் ஷேடைக் காட்டும்"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 1bd2c34..aa34584 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"சுற்றுப்புறங்களைப் புதுப்பிக்க முடியவில்லை"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"செயலிலுள்ளது (மீடியா மட்டும்). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"செயலிலுள்ளது (மீடியா மட்டும்). இடது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, வலது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). இடது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, வலது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). இடது: - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). வலது: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"செயலிலுள்ளது (மீடியா மட்டும்)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ஆடியோ பகிர்வை ஆதரிக்கிறது"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"செயலிலுள்ளது (மீடியா மட்டும்), இடதுபுறம் மட்டும்"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"செயலிலுள்ளது (மீடியா மட்டும்), வலதுபுறம் மட்டும்"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"செயலிலுள்ளது (மீடியா மட்டும்), இடதுபுறம் மற்றும் வலதுபுறம்"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"வன்பொருள் முடுக்கத்துடன் கூடிய காட்சியாக்கம்"</string>
<string name="media_category" msgid="8122076702526144053">"மீடியா"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"கண்காணித்தல்"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"நிலையான பயன்முறை இயக்கப்பட்டது"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"முக்கியத் தொடரிழையில் நீண்ட நேரம் செயல்படும்போது திரையைக் காட்சிப்படுத்தும்"</string>
<string name="pointer_location" msgid="7516929526199520173">"குறிப்பான் இடம்"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView செயல்படுத்தல்"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView செயல்படுத்தலை அமை"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"இனி இந்தத் தேர்வைப் பயன்படுத்த முடியாது. மீண்டும் முயலவும்."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"படத்தின் வண்ணப் பயன்முறை"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGBஐப் பயன்படுத்தும்"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"முடக்கப்பட்டது"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index f72e4cd..a4e50d0 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"పరికర డిస్ప్లేలో మాత్రమే (ఆటోమేటిక్ సెట్టింగ్)"</item>
+ <item msgid="9161645858025071955">"ఎక్స్టర్నల్ డిస్ప్లే"</item>
+ <item msgid="23651860565814477">"తాకి ఉపయోగించగల లేటెస్ట్ స్టేటస్ బార్"</item>
+ <item msgid="7521112827893653392">"యాక్టివ్గా ఉన్నవి"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"షేడ్ను పరికర డిస్ప్లేలో మాత్రమే చూపండి"</item>
+ <item msgid="1955398604822147783">"ఒక ఎక్స్టర్నల్ డిస్ప్లేలో షేడ్ను చూపండి"</item>
+ <item msgid="391477482416751568">"స్టేటస్ బార్తో చివరిగా ఇంటరాక్ట్ అయిన షేడ్ను డిస్ప్లేలో చూపండి"</item>
+ <item msgid="1746820128097981528">"చివరగా యాక్టివ్గా ఉన్న డిస్ప్లేలో షేడ్ను చూపండి"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 010344f..cded034 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"పరిసరాలను అప్డేట్ చేయడం సాధ్యం కాలేదు"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"యాక్టివ్ (మీడియా మాత్రమే). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"యాక్టివ్ (మీడియా మాత్రమే). ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది). ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది). ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"కనెక్ట్ అయింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది). కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"యాక్టివ్ (మీడియా మాత్రమే)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ వైపు మాత్రమే"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"యాక్టివ్ (మీడియా మాత్రమే), కుడివైపు మాత్రమే"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ, కుడివైపు మాత్రమే"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"హార్డ్వేర్ యాగ్జిలరేషన్ ఆధారిత రెండరింగ్"</string>
<string name="media_category" msgid="8122076702526144053">"మీడియా"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"పర్యవేక్షణ"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"స్ట్రిక్ట్ మోడ్ ఎనేబుల్డ్"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"యాప్లు ప్రధాన థ్రెడ్లో సుదీర్ఘ చర్యలు చేసేటప్పుడు స్క్రీన్ను ఫ్లాష్ చేయండి"</string>
<string name="pointer_location" msgid="7516929526199520173">"పాయింటర్ లొకేషన్"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"వెబ్ వీక్షణ అమలు"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"వెబ్ వీక్షణ అమలుని సెట్ చేయండి"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ఈ ఎంపిక ఇప్పుడు లేదు. మళ్లీ ట్రై చేయండి."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"చిత్రం రంగు మోడ్"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ఉపయోగిస్తుంది"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"డిజేబుల్ చేయబడింది"</string>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index adb274d..ad0f6bc 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"จอแสดงผลของอุปกรณ์เท่านั้น (ค่าเริ่มต้น)"</item>
+ <item msgid="9161645858025071955">"จอแสดงผลภายนอก"</item>
+ <item msgid="23651860565814477">"การแตะแถบสถานะล่าสุด"</item>
+ <item msgid="7521112827893653392">"Focus-based"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"แสดงเฉดสีในจอแสดงผลของอุปกรณ์เท่านั้น"</item>
+ <item msgid="1955398604822147783">"แสดงเฉดสีในจอแสดงผลภายนอกเครื่องเดียว"</item>
+ <item msgid="391477482416751568">"แสดงเฉดสีในจอแสดงผลที่มีการโต้ตอบกับแถบสถานะล่าสุด"</item>
+ <item msgid="1746820128097981528">"แสดงเฉดสีในจอแสดงผลที่โฟกัสล่าสุด"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 9b4d408..eaf256d 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"อัปเดตเสียงแวดล้อมไม่ได้"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ใช้งานอยู่ (สื่อเท่านั้น) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ใช้งานอยู่ (สื่อเท่านั้น) แบตเตอรี่ข้างซ้าย: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ข้างขวา: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) แบตเตอรี่ข้างซ้าย: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ข้างขวา: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) ซ้าย: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) ขวา: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ใช้งานอยู่ (สื่อเท่านั้น)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"รองรับการแชร์เสียง"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ใช้งานอยู่ (สื่อเท่านั้น), ซ้ายเท่านั้น"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ใช้งานอยู่ (สื่อเท่านั้น), ขวาเท่านั้น"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ใช้งานอยู่ (สื่อเท่านั้น), ซ้ายและขวา"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"การแสดงผลที่มีการเร่งด้วยฮาร์ดแวร์"</string>
<string name="media_category" msgid="8122076702526144053">"สื่อ"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"การตรวจสอบ"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"เปิดใช้งานโหมดเข้มงวด"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"กะพริบหน้าจอเมื่อแอปทำงานในเทรดหลักนาน"</string>
<string name="pointer_location" msgid="7516929526199520173">"ตำแหน่งของตัวชี้"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"การใช้งาน WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"ตั้งค่าการใช้งาน WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ตัวเลือกนี้ใช้ไม่ได้อีกต่อไป โปรดลองอีกครั้ง"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"โหมดสีของรูปภาพ"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"ใช้ sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"ปิดใช้"</string>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 0153375a..b1dd61a 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Display ng device lang (Default)"</item>
+ <item msgid="9161645858025071955">"External na display"</item>
+ <item msgid="23651860565814477">"Pinakahuling pagpindot sa status bar"</item>
+ <item msgid="7521112827893653392">"Focus-based"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Ipakita ang shade sa display ng device lang"</item>
+ <item msgid="1955398604822147783">"Ipakita ang shade sa isang external na display"</item>
+ <item msgid="391477482416751568">"Ipakita ang shade sa display kung saan may kamakailang nakipag-ugnayan sa status bar nito"</item>
+ <item msgid="1746820128097981528">"Ipakita ang shade sa pinakahuling na-focus na display"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 4cd2f5f..b6d8d19 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Hindi ma-update ang paligid"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktibo (media lang). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktibo (media lang). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Nakakonekta (sinusuportahan ang pag-share ng audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Nakakonekta (sinusuportahan ang pag-share ng audio). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Nakakonekta (sinusuportahan ang pag-share ng audio). Kaliwa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Nakakonekta (sinusuportahan ang pag-share ng audio). Kanan: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Nakakonekta (sinusuportahan ang pag-share ng audio)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (media lang)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Sinusuportahan ang pag-share ng audio"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (media lang), kaliwa lang"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktibo (media lang), kanan lang"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktibo (media lang), kaliwa at kanan"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Pag-render na pinapabilis ng hardware"</string>
<string name="media_category" msgid="8122076702526144053">"Media"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Pagsubaybay"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Enabled ang strict mode"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"I-flash ang screen pag may long ops ang app sa main thread"</string>
<string name="pointer_location" msgid="7516929526199520173">"Lokasyon ng pointer"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Pagpapatupad sa WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Itakda ang pagpapatupad sa WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Wala nang bisa ang napiling ito. Subukang muli."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Mode ng kulay ng larawan"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Gamitin ang sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Naka-disable"</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 6fbbb12..04697f2 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Yalnızca cihaz ekranı (Varsayılan)"</item>
+ <item msgid="9161645858025071955">"Harici ekran"</item>
+ <item msgid="23651860565814477">"Durum çubuğuyla yapılan en son etkileşim"</item>
+ <item msgid="7521112827893653392">"Odaklanmaya dayalı"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Gölgeyi yalnızca cihaz ekranında göster"</item>
+ <item msgid="1955398604822147783">"Gölgeyi tek bir harici ekranda göster"</item>
+ <item msgid="391477482416751568">"Gölgeyi, durum çubuğuyla en son etkileşim yapılan ekranda göster"</item>
+ <item msgid="1746820128097981528">"Gölgeyi en son odaklanılan ekranda göster"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index c993223..c4cbaf6 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Çevredeki sesler güncellenemedi"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Etkin (yalnızca medya). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Etkin (yalnızca medya). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Bağlı (ses paylaşımını destekler). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Bağlı (ses paylaşımını destekler). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Bağlı (ses paylaşımını destekler). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Bağlı (ses paylaşımını destekler). Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Bağlı (ses paylaşımını destekler)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Etkin (yalnızca medya)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ses paylaşımını destekler"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Etkin (yalnızca medya), yalnızca sol"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Etkin (yalnızca medya), yalnızca sağ"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Etkin (yalnızca medya), sol ve sağ"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Donanım hızlandırmalı oluşturma"</string>
<string name="media_category" msgid="8122076702526144053">"Medya"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"İzleme"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Yüksek düzey modu etkin"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Uygulamalar ana iş parçacığında uzun işlem yaparken ekranı yanıp söndür"</string>
<string name="pointer_location" msgid="7516929526199520173">"İşaretçi konumu"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Web Görünümü kullanımı"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Web Görünümü kullanımını ayarla"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Bu seçenek artık geçerli değil. Tekrar deneyin."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Resim renk modu"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB\'yi kullan"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Devre dışı"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index a371c9c..569d6f3 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Лише екран пристрою (за умовчанням)"</item>
+ <item msgid="9161645858025071955">"Зовнішній дисплей"</item>
+ <item msgid="23651860565814477">"Останнє натискання рядка стану"</item>
+ <item msgid="7521112827893653392">"На основі фокусування"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Показувати панель лише на екрані пристрою"</item>
+ <item msgid="1955398604822147783">"Показувати панель на одному зовнішньому дисплеї"</item>
+ <item msgid="391477482416751568">"Показувати панель на дисплеї, де відбулася остання взаємодія з рядком стану"</item>
+ <item msgid="1746820128097981528">"Показувати панель на останньому активному дисплеї"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index fd1ade6..ecff572 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не вдалось оновити стан оточення"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активне з’єднання (лише для мультимедіа). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активне з’єднання (лише для мультимедіа). Рівень заряду: лівий <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Підключено (підтримує надсилання аудіо). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Підключено (підтримує надсилання аудіо). Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Підключено (підтримує надсилання аудіо). Лівий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Підключено (підтримує надсилання аудіо). Правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Підключено (підтримує надсилання аудіо)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (лише для мультимедіа)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Підтримує надсилання аудіо"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (лише для мультимедіа); лише лівий"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (лише для мультимедіа); лише правий"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (лише для мультимедіа); лівий і правий"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Апаратне прискорення"</string>
<string name="media_category" msgid="8122076702526144053">"Медіа"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Моніторинг"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Строгий режим увімкнено"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Підсвічувати екран під час довгострокових операцій"</string>
<string name="pointer_location" msgid="7516929526199520173">"Розташування курсора"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Застосування WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Налаштувати застосування WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Ця опція більше не дійсна. Повторіть спробу."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Режим кольору"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Використовувати sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Вимкнено"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 13ffeb1..3407114 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"اطراف کو اپ ڈیٹ نہیں کیا جا سکا"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"فعال (صرف میڈیا)۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"فعال (صرف میڈیا)۔ L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری۔"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)۔ L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)۔ بائيں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)۔ دائيں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (صرف میڈیا)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"آڈیو کے اشتراک کو سپورٹ کرتا ہے"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (صرف میڈیا)، صرف بائیں"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"فعال (صرف میڈیا)، صرف دائیں"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"فعال (صرف میڈیا)، بائیں اور دائیں"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"ہارڈ ویئر کے ذریعے تیز کردہ رینڈرنگ"</string>
<string name="media_category" msgid="8122076702526144053">"میڈیا"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"مانیٹر کرنا"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"سخت وضع فعال ہے"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"ایپس کے اصل تھریڈ پر طویل اعمال انجام دیتے وقت اسکرین کو فلیش کریں"</string>
<string name="pointer_location" msgid="7516929526199520173">"پوائنٹر مقام"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView کا نفاذ"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView کا نفاذ سیٹ کریں"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"یہ انتخاب اب درست نہیں رہا۔ دوبارہ کوشش کریں۔"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"تصویری رنگ موڈ"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB استعمال کریں"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"غیر فعال"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 04bd7fcc..bff7993 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Atrof-muhit yangilanmadi"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Faol (faqat media uchun) Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Faol (faqat media uchun), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ulangan (audio yuborish mumkin). Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (chap)."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ulangan (audio yuborish mumkin). Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> (oʻng)."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ulangan (audio yuborish mumkin)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Faol (faqat media uchun)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio yuborishi mumkin"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Faol (faqat media uchun), faqat chap"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Faol (faqat media uchun), faqat oʻng"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Faol (faqat media uchun), chap va oʻng"</string>
@@ -250,11 +270,11 @@
<string name="enable_adb" msgid="8072776357237289039">"USB orqali nosozliklarni aniqlash"</string>
<string name="enable_adb_summary" msgid="3711526030096574316">"USB orqali kompyuterga ulanganda tuzatish rejimi yoqilsin"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"USB orqali nosozliklarni tuzatishni taqiqlash"</string>
- <string name="enable_adb_wireless" msgid="6973226350963971018">"Wi-Fi orqali debagging"</string>
+ <string name="enable_adb_wireless" msgid="6973226350963971018">"Wi-Fi orqali debaging"</string>
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi tarmoqqa ulanganda nosozliklarni aniqlash rejimi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Xato"</string>
- <string name="adb_wireless_settings" msgid="2295017847215680229">"Wi-Fi orqali debagging"</string>
- <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Mavjud qurilmalarni koʻrish va ulardan foydalanish uchun Wi-Fi orqali debagging funksiyasini yoqing"</string>
+ <string name="adb_wireless_settings" msgid="2295017847215680229">"Wi-Fi orqali debaging"</string>
+ <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Mavjud qurilmalarni koʻrish va ulardan foydalanish uchun Wi-Fi orqali debaging funksiyasini yoqing"</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Qurilmani QR kod orqali ulash"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR kod skaneri yordamida yangi qurilmalarni ulang"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Qurilmani ulanish kodi orqali ulash"</string>
@@ -345,8 +365,8 @@
<string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Modem rejimida apparatli tezlatishdan foydalanish (mavjud bo‘lsa)."</string>
<string name="adb_warning_title" msgid="7708653449506485728">"USB orqali nosozliklarni tuzatishga ruxsat berilsinmi?"</string>
<string name="adb_warning_message" msgid="8145270656419669221">"USB orqali nosozliklarni aniqlash faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal maʼlumotlarini o‘qish uchun foydalaniladi."</string>
- <string name="adbwifi_warning_title" msgid="727104571653031865">"Wi-Fi orqali debagging uchun ruxsat berilsinmi?"</string>
- <string name="adbwifi_warning_message" msgid="8005936574322702388">"Wi-Fi orqali debagging faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter oʻrtasida koʻchirish, ilovalarni bildirishnomasiz oʻrnatish va jurnal maʼlumotlarini oʻqish uchun foydalaniladi."</string>
+ <string name="adbwifi_warning_title" msgid="727104571653031865">"Wi-Fi orqali debaging uchun ruxsat berilsinmi?"</string>
+ <string name="adbwifi_warning_message" msgid="8005936574322702388">"Wi-Fi orqali debaging faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter oʻrtasida koʻchirish, ilovalarni bildirishnomasiz oʻrnatish va jurnal maʼlumotlarini oʻqish uchun foydalaniladi."</string>
<string name="adb_keys_warning_message" msgid="2968555274488101220">"USB orqali nosozliklarni tuzatishga berilgan ruxsat siz hisobingizga kirgan barcha kompyuterlar uchun bekor qilinsinmi?"</string>
<string name="dev_settings_warning_title" msgid="8251234890169074553">"Dasturlash sozlamalariga ruxsat berilsinmi?"</string>
<string name="dev_settings_warning_message" msgid="37741686486073668">"Bu sozlamalar faqat dasturlash maqsadlariga mo‘ljallangan. Shuning uchun, ular qurilmangizga va undagi ilovalariga shikast yetkazib, noto‘g‘ri ishlashiga sabab bo‘lishi mumkin."</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Vizualizatsiyani apparatli tezlatish"</string>
<string name="media_category" msgid="8122076702526144053">"Multimedia"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoring"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Qat’iy rejim yoqilgan"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Uzun amallar vaqtida ekranni miltillatish"</string>
<string name="pointer_location" msgid="7516929526199520173">"Kursor joylashuvi"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ta’minotchisi"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView ta’minotchisini sozlash"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Bu variant endi yaroqsiz. Qaytadan urining."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Rang rejimi"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB ranglaridan foydalanish"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Oʻchiq"</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 8e4cf53..daddccc 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Chỉ hiển thị trên thiết bị (Mặc định)"</item>
+ <item msgid="9161645858025071955">"Màn hình ngoài"</item>
+ <item msgid="23651860565814477">"Lần gần đây nhất chạm vào thanh trạng thái"</item>
+ <item msgid="7521112827893653392">"Theo tiêu điểm"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Chỉ hiện ngăn thông báo trên màn hình thiết bị"</item>
+ <item msgid="1955398604822147783">"Hiện ngăn trên một màn hình ngoài"</item>
+ <item msgid="391477482416751568">"Hiện ngăn trên màn hình mà gần đây nhất người dùng đã tương tác với thanh trạng thái của màn hình đó"</item>
+ <item msgid="1746820128097981528">"Hiện ngăn trên màn hình mà gần đây nhất người dùng đã đặt tiêu điểm"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 2763c01..cb0a875a 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Không cập nhật được âm lượng xung quanh"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Đang hoạt động (chỉ phát nội dung đa phương tiện). Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Đang hoạt động (chỉ phát nội dung đa phương tiện). Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pin. Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pin."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pin. Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pin."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh)."</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Đang hoạt động (chỉ phát nội dung đa phương tiện)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Hỗ trợ tính năng chia sẻ âm thanh"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Đang hoạt động (chỉ phát nội dung đa phương tiện), chỉ dùng tai nghe bên trái"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Đang hoạt động (chỉ phát nội dung đa phương tiện), chỉ dùng tai nghe bên phải"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Đang hoạt động (chỉ phát nội dung đa phương tiện), đang dùng cả tai nghe bên trái và phải"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Kết xuất có tăng tốc phần cứng"</string>
<string name="media_category" msgid="8122076702526144053">"Phương tiện"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Giám sát"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Luôn bật chế độ nghiêm ngặt"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Màn hình nháy khi ứng dụng thực hiện các hoạt động dài trên luồng chính"</string>
<string name="pointer_location" msgid="7516929526199520173">"Vị trí con trỏ"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Triển khai WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Đặt triển khai WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Lựa chọn này không còn hợp lệ nữa. Hãy thử lại."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Chế độ màu của ảnh"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Sử dụng sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Đã tắt"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 5c82865..204bccf 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"仅设备显示屏(默认)"</item>
+ <item msgid="9161645858025071955">"外接显示屏"</item>
+ <item msgid="23651860565814477">"最近一次触摸状态栏"</item>
+ <item msgid="7521112827893653392">"基于焦点"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"仅在设备显示屏上显示通知栏"</item>
+ <item msgid="1955398604822147783">"在单个外接显示屏上显示通知栏"</item>
+ <item msgid="391477482416751568">"在上次与状态栏互动的显示屏上显示通知栏"</item>
+ <item msgid="1746820128097981528">"在最近一次获得焦点的显示屏上显示通知栏"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 934c525..f13f7d9 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"无法更新周围声音"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"使用中(仅限媒体)。电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"使用中(仅限媒体)。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已连接(支持音频分享)。电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"已连接(支持音频分享)。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"已连接(支持音频分享)。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"已连接(支持音频分享)。右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"已连接(支持音频分享)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"使用中(仅限媒体)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支持音频分享"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"使用中(仅限媒体),仅左侧"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"使用中(仅限媒体),仅右侧"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"使用中(仅限媒体),左侧和右侧"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"硬件加速渲染"</string>
<string name="media_category" msgid="8122076702526144053">"媒体"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"监控"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"启用严格模式"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"应用在主线程上执行长时间操作时闪烁屏幕"</string>
<string name="pointer_location" msgid="7516929526199520173">"指针位置"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 实现"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"设置 WebView 实现"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"此选项已失效,请重试。"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"图片颜色模式"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"使用 sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"已停用"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 2e06059..f70b02d 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"只限裝置顯示屏 (預設)"</item>
+ <item msgid="9161645858025071955">"外部顯示屏"</item>
+ <item msgid="23651860565814477">"最近一次觸碰狀態列"</item>
+ <item msgid="7521112827893653392">"突顯"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"只在裝置顯示屏上顯示陰影"</item>
+ <item msgid="1955398604822147783">"在單一外接螢幕顯示通知欄"</item>
+ <item msgid="391477482416751568">"在上次使用狀態列的螢幕上顯示通知欄"</item>
+ <item msgid="1746820128097981528">"在最新使用的螢幕顯示通知欄"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 037f531..14976e0 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"無法更新環境聲音"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"啟用 (只限媒體)。<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"啟用 (只限媒體),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量。"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已連線 (支援音訊分享功能),<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"已連線 (支援音訊分享功能),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量。"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"已連線 (支援音訊分享功能)。左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"已連線 (支援音訊分享功能)。右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"已連線 (支援音訊分享功能)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (只限媒體)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享功能"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (只限媒體)"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"右側啟用 (只限媒體)"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"右側同時啟用 (只限媒體)"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"硬件加速轉譯"</string>
<string name="media_category" msgid="8122076702526144053">"媒體"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"監控"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"嚴格模式已啟用"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"當應用程式在主執行緒中進行長時間作業時,讓螢幕閃爍"</string>
<string name="pointer_location" msgid="7516929526199520173">"指標位置"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 設置"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"設定 WebView 設置"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"此選擇已失效,請再試一次。"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"相片顏色模式"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"使用 sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"已停用"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 5b48ad4..6ac8ff5 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"僅裝置螢幕 (預設)"</item>
+ <item msgid="9161645858025071955">"外接螢幕"</item>
+ <item msgid="23651860565814477">"最近一次觸碰狀態列"</item>
+ <item msgid="7521112827893653392">"使用中的螢幕"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"只在裝置螢幕顯示通知欄"</item>
+ <item msgid="1955398604822147783">"在單一外接螢幕顯示通知欄"</item>
+ <item msgid="391477482416751568">"在上次使用狀態列的螢幕上顯示通知欄"</item>
+ <item msgid="1746820128097981528">"在最新使用的螢幕顯示通知欄"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"預設螢幕"</item>
+ <item msgid="774789415968826925">"任何外接螢幕"</item>
+ <item msgid="7880769915418638436">"最新觸控狀態列"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 0ef65e6..b65cb4f 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"無法更新環境狀態"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"已啟用 (僅限媒體)。電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"已啟用 (僅限媒體)。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已連線 (支援音訊分享)。電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"已連線 (支援音訊分享)。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"已連線 (支援音訊分享)。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"已連線 (支援音訊分享)。右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"已連線 (支援音訊分享)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (僅限媒體)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (僅限媒體)"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"右側啟用 (僅限媒體)"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"左右側同時啟用 (僅限媒體)"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"硬體加速轉譯"</string>
<string name="media_category" msgid="8122076702526144053">"媒體"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"監控"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"嚴格模式已啟用"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"當應用程式在主執行緒中進行長時間作業時,讓螢幕閃爍"</string>
<string name="pointer_location" msgid="7516929526199520173">"指標位置"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 實作"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"設定 WebView 實作"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"這個選項已失效,請再試一次。"</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"螢幕色彩模式"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"使用 sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"已停用"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 1a61f8b..25f9592 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -288,10 +288,22 @@
<item msgid="3753634915787796632">"2"</item>
<item msgid="4779928470672877922">"3"</item>
</string-array>
- <!-- no translation found for shade_display_awareness_entries:2 (23651860565814477) -->
- <!-- no translation found for shade_display_awareness_entries:3 (7521112827893653392) -->
- <!-- no translation found for shade_display_awareness_summaries:1 (1955398604822147783) -->
- <!-- no translation found for shade_display_awareness_summaries:2 (391477482416751568) -->
- <!-- no translation found for shade_display_awareness_summaries:3 (1746820128097981528) -->
- <!-- no translation found for shade_display_awareness_values:3 (4313165186636015195) -->
+ <string-array name="shade_display_awareness_entries">
+ <item msgid="816770658383209617">"Ukuboniswa kwedivayisi kuphela (Okuzenzakalelayo)"</item>
+ <item msgid="9161645858025071955">"Ukubonisa Kwangaphandle"</item>
+ <item msgid="23651860565814477">"Thinta ibha yesimo yamuva"</item>
+ <item msgid="7521112827893653392">"Kusekelwe ekugxileni"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_summaries">
+ <item msgid="2964753205732912921">"Bonisa umthunzi esibonisini sedivayisi kuphela"</item>
+ <item msgid="1955398604822147783">"Bonisa umthunzi esibonisini esisodwa sangaphandle"</item>
+ <item msgid="391477482416751568">"Bonisa umthunzi esibonisini kokudlule ebesinesimo sebha okuxhunyanwe naso"</item>
+ <item msgid="1746820128097981528">"Bonisa umthunzi esibonisini sokugcina okugxilwe kuso"</item>
+ </string-array>
+ <string-array name="shade_display_awareness_values">
+ <item msgid="3055776101992426514">"default_display"</item>
+ <item msgid="774789415968826925">"any_external_display"</item>
+ <item msgid="7880769915418638436">"status_bar_latest_touch"</item>
+ <item msgid="4313165186636015195">"focused_display"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index de62628..859c153 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -113,13 +113,33 @@
<string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ayikwazanga ukubuyekeza izindawo ezizungezile"</string>
<string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Iyasebenza (imidiya kuphela). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
<string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Iyasebenza (imidiya kuphela). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri."</string>
+ <!-- no translation found for bluetooth_guest_battery_level (2820003593899467676) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered (5404013822067644960) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level (7928347900623812299) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_battery_level_untethered (4458143141394300892) -->
+ <skip />
<string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
<string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri."</string>
<string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe). Kwesokudla: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
<string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe). Kwesokudla: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
<string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe)"</string>
+ <!-- no translation found for bluetooth_guest_battery_level_lea_support (8098327939585013928) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_battery_level_untethered_lea_support (3701035025565668360) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_no_battery_level_lea_support (2977038548753103470) -->
+ <skip />
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Kuyasebenza (imidiya kuphela)"</string>
+ <!-- no translation found for bluetooth_guest_no_battery_level (9122974160381136920) -->
+ <skip />
+ <!-- no translation found for bluetooth_guest_media_only_no_battery_level (7666347601796705721) -->
+ <skip />
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Isekela ukwabelana ngokuqoshiwe"</string>
+ <!-- no translation found for bluetooth_guest_saved_device_lea_support (5621291599518569876) -->
+ <skip />
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Iyasebenza (imidiya kuphela), ngakwesokunxele kuphela"</string>
<string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Kuyasebenza (imidiya kuphela), ngakwesokudla kuphela"</string>
<string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Kuyasebenza (imidiya kuphela), ngakwesokunxele nakwesokudla"</string>
@@ -376,6 +396,8 @@
<string name="debug_hw_drawing_category" msgid="5830815169336975162">"Ukunikezelwa okusheshisiwe kwezingxenyekazi zekhompyutha"</string>
<string name="media_category" msgid="8122076702526144053">"Imidiya"</string>
<string name="debug_monitoring_category" msgid="1597387133765424994">"Ukwengamela"</string>
+ <!-- no translation found for window_management_category (2015535427098365170) -->
+ <skip />
<string name="strict_mode" msgid="889864762140862437">"Imodi eqinile ivumelwe"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Ukuphazimisa isikrini uma izinhlelo zokusebenza ziyenza umsebenzi ngesikhathi eside kuchungechunge olukhulu"</string>
<string name="pointer_location" msgid="7516929526199520173">"Isikhombi sendawo"</string>
@@ -470,6 +492,12 @@
<string name="select_webview_provider_title" msgid="3917815648099445503">"Ukufakwa ke-WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Sesba ukufakwa kwe-WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Lokhu kukhetha akusavumelekile. Zama futhi."</string>
+ <!-- no translation found for webview_launch_devtools_title (8009687433555367112) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_package (3182544553665113721) -->
+ <skip />
+ <!-- no translation found for webview_launch_devtools_no_activity (4066006313619617140) -->
+ <skip />
<string name="picture_color_mode" msgid="1013807330552931903">"Imodi yombala wesithombe"</string>
<string name="picture_color_mode_desc" msgid="151780973768136200">"Sebenzisa i-sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="403424372812399228">"Kukhutshaziwe"</string>
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 3326b60..7ab096f 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -116,4 +116,13 @@
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
<item name="android:textSize">16dp</item>
</style>
+
+ <style name="Theme.Transparent" parent="@android:style/Theme.DeviceDefault.Settings">
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowContentOverlay">@null</item>
+ </style>
+
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 4110d53..ba72709 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -585,7 +585,8 @@
legacy, true);
} catch (RemoteException ignored) {
}
- } catch (NameNotFoundException | IOException e) {
+ } catch (
+ IllegalArgumentException | NameNotFoundException | IOException e) {
Log.w(TAG, "Failed to query stats: " + e);
try {
mBackgroundHandler.mStatsObserver.onGetStatsCompleted(
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 522a436..31948e4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -23,6 +23,7 @@
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.input.InputManager;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
@@ -34,6 +35,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import android.view.InputDevice;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
@@ -1054,7 +1056,7 @@
/** Get develop option value for audio sharing preview. */
@WorkerThread
- private static boolean getAudioSharingPreviewValue(@Nullable ContentResolver contentResolver) {
+ public static boolean getAudioSharingPreviewValue(@Nullable ContentResolver contentResolver) {
if (contentResolver == null) return false;
return Settings.Global.getInt(
contentResolver,
@@ -1193,4 +1195,53 @@
}
device.setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS, fastPairCustomizedMeta.getBytes());
}
+
+ /**
+ * Returns the {@link InputDevice} of the given bluetooth address if the device is a input
+ * device.
+ *
+ * @param address The address of the bluetooth device
+ * @return The {@link InputDevice} of the given address if applicable
+ */
+ @Nullable
+ public static InputDevice getInputDevice(Context context, String address) {
+ InputManager im = context.getSystemService(InputManager.class);
+
+ if (im != null) {
+ for (int deviceId : im.getInputDeviceIds()) {
+ String btAddress = im.getInputDeviceBluetoothAddress(deviceId);
+
+ if (btAddress != null && btAddress.equals(address)) {
+ return im.getInputDevice(deviceId);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Identifies whether a device is a stylus using the associated {@link InputDevice} or
+ * {@link CachedBluetoothDevice}.
+ * InputDevices are only available when the device is USI or Bluetooth-connected, whereas
+ * CachedBluetoothDevices are available for Bluetooth devices when connected or paired,
+ * so to handle all cases, both are needed.
+ *
+ * @param inputDevice The associated input device of the stylus
+ * @param cachedBluetoothDevice The associated bluetooth device of the stylus
+ */
+ public static boolean isDeviceStylus(@Nullable InputDevice inputDevice,
+ @Nullable CachedBluetoothDevice cachedBluetoothDevice) {
+ if (inputDevice != null && inputDevice.supportsSource(InputDevice.SOURCE_STYLUS)) {
+ return true;
+ }
+
+ if (cachedBluetoothDevice != null) {
+ BluetoothDevice bluetoothDevice = cachedBluetoothDevice.getDevice();
+ String deviceType = BluetoothUtils.getStringMetaData(bluetoothDevice,
+ BluetoothDevice.METADATA_DEVICE_TYPE);
+ return TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_STYLUS);
+ }
+
+ return false;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index 572444e..bf86911 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -30,13 +30,11 @@
import androidx.annotation.ChecksSdkIntAtLeast;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.settingslib.flags.Flags;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -387,7 +385,7 @@
preferredMainDevice.refresh();
hasChanged = true;
}
- syncAudioSharingStatusIfNeeded(preferredMainDevice);
+ syncAudioSharingSourceIfNeeded(preferredMainDevice);
}
if (hasChanged) {
log("addMemberDevicesIntoMainDevice: After changed, CachedBluetoothDevice list: "
@@ -401,16 +399,13 @@
return userManager != null && userManager.isManagedProfile();
}
- private void syncAudioSharingStatusIfNeeded(CachedBluetoothDevice mainDevice) {
+ private void syncAudioSharingSourceIfNeeded(CachedBluetoothDevice mainDevice) {
boolean isAudioSharingEnabled = BluetoothUtils.isAudioSharingUIAvailable(mContext);
- if (isAudioSharingEnabled && mainDevice != null) {
+ if (isAudioSharingEnabled) {
if (isWorkProfile()) {
- log("addMemberDevicesIntoMainDevice: skip sync audio sharing status, work profile");
+ log("addMemberDevicesIntoMainDevice: skip sync source for work profile");
return;
}
- Set<CachedBluetoothDevice> deviceSet = new HashSet<>();
- deviceSet.add(mainDevice);
- deviceSet.addAll(mainDevice.getMemberDevice());
boolean hasBroadcastSource = BluetoothUtils.isBroadcasting(mBtManager)
&& BluetoothUtils.hasConnectedBroadcastSource(
mainDevice, mBtManager);
@@ -424,6 +419,9 @@
if (metadata != null && assistant != null) {
log("addMemberDevicesIntoMainDevice: sync audio sharing source after "
+ "combining the top level devices.");
+ Set<CachedBluetoothDevice> deviceSet = new HashSet<>();
+ deviceSet.add(mainDevice);
+ deviceSet.addAll(mainDevice.getMemberDevice());
Set<BluetoothDevice> sinksToSync = deviceSet.stream()
.map(CachedBluetoothDevice::getDevice)
.filter(device ->
@@ -437,24 +435,8 @@
}
}
}
- if (Flags.enableTemporaryBondDevicesUi()) {
- log("addMemberDevicesIntoMainDevice: sync temp bond metadata for audio sharing "
- + "sinks after combining the top level devices.");
- Set<BluetoothDevice> sinksToSync = deviceSet.stream()
- .map(CachedBluetoothDevice::getDevice).filter(Objects::nonNull).collect(
- Collectors.toSet());
- if (sinksToSync.stream().anyMatch(BluetoothUtils::isTemporaryBondDevice)) {
- for (BluetoothDevice device : sinksToSync) {
- if (!BluetoothUtils.isTemporaryBondDevice(device)) {
- log("addMemberDevicesIntoMainDevice: sync temp bond metadata for "
- + device.getAnonymizedAddress());
- BluetoothUtils.setTemporaryBondMetadata(device);
- }
- }
- }
- }
} else {
- log("addMemberDevicesIntoMainDevice: skip sync audio sharing status, flag disabled");
+ log("addMemberDevicesIntoMainDevice: skip sync source, flag disabled");
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
index 8415642..f18a2da 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
@@ -63,13 +63,14 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -84,6 +85,8 @@
public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
public static final String ACTION_LE_AUDIO_SHARING_STATE_CHANGE =
"com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_STATE_CHANGE";
+ public static final String ACTION_LE_AUDIO_SHARING_DEVICE_CONNECTED =
+ "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_DEVICE_CONNECTED";
public static final String EXTRA_LE_AUDIO_SHARING_STATE = "BLUETOOTH_LE_AUDIO_SHARING_STATE";
public static final String EXTRA_BLUETOOTH_DEVICE = "BLUETOOTH_DEVICE";
public static final String EXTRA_BT_DEVICE_TO_AUTO_ADD_SOURCE = "BT_DEVICE_TO_AUTO_ADD_SOURCE";
@@ -105,6 +108,10 @@
private static final String SYSUI_PKG = "com.android.systemui";
private static final String TAG = "LocalBluetoothLeBroadcast";
private static final boolean DEBUG = BluetoothUtils.D;
+ private static final String VALID_PASSWORD_CHARACTERS =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[]{}|;:,"
+ + ".<>?/";
+ private static final int PASSWORD_LENGTH = 16;
static final String NAME = "LE_AUDIO_BROADCAST";
private static final String UNDERLINE = "_";
@@ -142,8 +149,8 @@
private ContentResolver mContentResolver;
private ContentObserver mSettingsObserver;
// Cached broadcast callbacks being register before service is connected.
- private Map<BluetoothLeBroadcast.Callback, Executor> mCachedBroadcastCallbackExecutorMap =
- new ConcurrentHashMap<>();
+ private ConcurrentHashMap<BluetoothLeBroadcast.Callback, Executor>
+ mCachedBroadcastCallbackExecutorMap = new ConcurrentHashMap<>();
private final ServiceListener mServiceListener =
new ServiceListener() {
@@ -873,7 +880,7 @@
@NonNull @CallbackExecutor Executor executor,
@NonNull BluetoothLeBroadcast.Callback callback) {
if (mServiceBroadcast == null) {
- Log.d(TAG, "registerServiceCallBack failed, the BluetoothLeBroadcast is null.");
+ Log.d(TAG, "registerServiceCallBack failed, proxy not attached.");
mCachedBroadcastCallbackExecutorMap.putIfAbsent(callback, executor);
return;
}
@@ -895,10 +902,7 @@
@NonNull @CallbackExecutor Executor executor,
@NonNull BluetoothLeBroadcastAssistant.Callback callback) {
if (mServiceBroadcastAssistant == null) {
- Log.d(
- TAG,
- "registerBroadcastAssistantCallback failed, "
- + "the BluetoothLeBroadcastAssistant is null.");
+ Log.d(TAG, "registerBroadcastAssistantCallback failed, proxy not attached.");
return;
}
@@ -913,7 +917,7 @@
public void unregisterServiceCallBack(@NonNull BluetoothLeBroadcast.Callback callback) {
mCachedBroadcastCallbackExecutorMap.remove(callback);
if (mServiceBroadcast == null) {
- Log.d(TAG, "unregisterServiceCallBack failed, the BluetoothLeBroadcast is null.");
+ Log.d(TAG, "unregisterServiceCallBack failed, proxy not attached.");
return;
}
@@ -932,10 +936,7 @@
private void unregisterBroadcastAssistantCallback(
@NonNull BluetoothLeBroadcastAssistant.Callback callback) {
if (mServiceBroadcastAssistant == null) {
- Log.d(
- TAG,
- "unregisterBroadcastAssistantCallback, "
- + "the BluetoothLeBroadcastAssistant is null.");
+ Log.d(TAG, "unregisterBroadcastAssistantCallback, proxy not attched.");
return;
}
@@ -1085,11 +1086,16 @@
mBroadcastId = UNKNOWN_VALUE_PLACEHOLDER;
}
- private String generateRandomPassword() {
- String randomUUID = UUID.randomUUID().toString();
- // first 16 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
- return randomUUID.substring(0, 8) + randomUUID.substring(9, 13) + randomUUID.substring(14,
- 18);
+ private static String generateRandomPassword() {
+ SecureRandom random = new SecureRandom();
+ StringBuilder stringBuilder = new StringBuilder(PASSWORD_LENGTH);
+
+ for (int i = 0; i < PASSWORD_LENGTH; i++) {
+ int randomIndex = random.nextInt(VALID_PASSWORD_CHARACTERS.length());
+ stringBuilder.append(VALID_PASSWORD_CHARACTERS.charAt(randomIndex));
+ }
+
+ return stringBuilder.toString();
}
private void registerContentObserver() {
@@ -1128,7 +1134,9 @@
/** Update fallback active device if needed. */
public void updateFallbackActiveDeviceIfNeeded() {
- if (Flags.disableAudioSharingAutoPickFallbackInUi()) {
+ if (Flags.disableAudioSharingAutoPickFallbackInUi() || (mContext != null
+ && Flags.audioSharingDeveloperOption()
+ && BluetoothUtils.getAudioSharingPreviewValue(mContext.getContentResolver()))) {
Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, disable flag is on");
return;
}
@@ -1189,6 +1197,7 @@
@NonNull
private Map<Integer, List<BluetoothDevice>> getDeviceGroupsInBroadcast() {
+ if (mServiceBroadcastAssistant == null) return new HashMap<>();
boolean hysteresisModeFixEnabled =
BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext);
List<BluetoothDevice> connectedDevices = mServiceBroadcastAssistant.getConnectedDevices();
diff --git a/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS b/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS
index 9f15c1b..b676d8d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS
@@ -1,6 +1,5 @@
# Default reviewers for this and subdirectories.
andychou@google.com
-arcwang@google.com
changbetty@google.com
qal@google.com
wengsu@google.com
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
index d5cfe55..460c790 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -35,6 +35,7 @@
import android.annotation.SuppressLint;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
+import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
@@ -117,6 +118,14 @@
DISABLED_BY_OTHER
}
+ /**
+ * Information about the owner of a {@link ZenMode}. {@link #packageName()} is
+ * {@link SystemZenRules#PACKAGE_ANDROID} if the mode is system-owned; it may also be
+ * {@code null}, but only as an artifact of very old modes.
+ */
+ public record Owner(@Nullable String packageName, @Nullable ComponentName configurationActivity,
+ @Nullable ComponentName conditionProvider) { }
+
private final String mId;
private final AutomaticZenRule mRule;
private final Kind mKind;
@@ -198,7 +207,7 @@
}
@NonNull
- public AutomaticZenRule getRule() {
+ AutomaticZenRule getRule() {
return mRule;
}
@@ -207,6 +216,10 @@
return Strings.nullToEmpty(mRule.getName());
}
+ public void setName(@NonNull String name) {
+ mRule.setName(name);
+ }
+
@NonNull
public Kind getKind() {
return mKind;
@@ -217,6 +230,17 @@
return mStatus;
}
+ @NonNull
+ public Owner getOwner() {
+ return new Owner(mRule.getPackageName(), mRule.getConfigurationActivity(),
+ mRule.getOwner());
+ }
+
+ @Nullable
+ public String getOwnerPackage() {
+ return getOwner().packageName();
+ }
+
@AutomaticZenRule.Type
public int getType() {
return mRule.getType();
@@ -257,6 +281,26 @@
}
}
+ /**
+ * Returns the resource id of the icon for this mode. Note that this is the <em>stored</em>
+ * resource id, and thus can be different from the value in {@link #getIconKey()} -- in
+ * particular, for modes without a custom icon set, this method returns {@code 0} whereas
+ * {@link #getIconKey()} will return a default icon based on other mode properties.
+ *
+ * <p>Most callers are interested in {@link #getIconKey()}, unless they are editing the icon.
+ */
+ public int getIconResId() {
+ return mRule.getIconResId();
+ }
+
+ /**
+ * Sets the resource id of the icon for this mode.
+ * @see #getIconResId()
+ */
+ public void setIconResId(@DrawableRes int iconResId) {
+ mRule.setIconResId(iconResId);
+ }
+
/** Returns the interruption filter of the mode. */
@NotificationManager.InterruptionFilter
public int getInterruptionFilter() {
@@ -445,6 +489,10 @@
return mStatus == Status.ENABLED_AND_ACTIVE;
}
+ public boolean isManualInvocationAllowed() {
+ return mRule.isManualInvocationAllowed();
+ }
+
public boolean isSystemOwned() {
return SystemZenRules.PACKAGE_ANDROID.equals(mRule.getPackageName());
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeDescriptions.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeDescriptions.java
index f577698..b67339b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeDescriptions.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeDescriptions.java
@@ -70,8 +70,7 @@
public String getTriggerDescriptionForAccessibility(@NonNull ZenMode mode) {
// Only one special case: time-based schedules, where we want to use full day names.
if (mode.isSystemOwned() && mode.getType() == TYPE_SCHEDULE_TIME) {
- ZenModeConfig.ScheduleInfo schedule = ZenModeConfig.tryParseScheduleConditionId(
- mode.getRule().getConditionId());
+ ZenModeConfig.ScheduleInfo schedule = ZenModeSchedules.getTimeSchedule(mode);
if (schedule != null) {
String fullDaysSummary = SystemZenRules.getDaysOfWeekFull(mContext, schedule);
if (fullDaysSummary != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeSchedules.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeSchedules.java
new file mode 100644
index 0000000..c981652
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeSchedules.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.notification.modes;
+
+import android.service.notification.ZenModeConfig;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class ZenModeSchedules {
+
+ /**
+ * Returns the {@link ZenModeConfig.ScheduleInfo} time schedule corresponding to the mode, or
+ * {@code null} if the mode is not time-schedule-based.
+ */
+ @Nullable
+ public static ZenModeConfig.ScheduleInfo getTimeSchedule(@NonNull ZenMode mode) {
+ return ZenModeConfig.tryParseScheduleConditionId(mode.getRule().getConditionId());
+ }
+
+ /**
+ * Returns the {@link ZenModeConfig.EventInfo} calendar schedule corresponding to the mode, or
+ * {@code null} if the mode is not calendar-schedule-based.
+ */
+ @Nullable
+ public static ZenModeConfig.EventInfo getCalendarSchedule(@NonNull ZenMode mode) {
+ return ZenModeConfig.tryParseEventConditionId(mode.getRule().getConditionId());
+ }
+
+ private ZenModeSchedules() { }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/CreateUserActivity.java b/packages/SettingsLib/src/com/android/settingslib/users/CreateUserActivity.java
new file mode 100644
index 0000000..c5e6f60
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/users/CreateUserActivity.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.users;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.R;
+
+
+public class CreateUserActivity extends Activity {
+ private static final String TAG = "CreateUserActivity";
+
+ public static final String EXTRA_USER_NAME = "new_user_name";
+ public static final String EXTRA_IS_ADMIN = "is_admin";
+ public static final String EXTRA_USER_ICON_PATH = "user_icon_path";
+ private static final String DIALOG_STATE_KEY = "create_user_dialog_state";
+ private static final String EXTRA_CAN_CREATE_ADMIN = "can_create_admin";
+ private static final String EXTRA_FILE_AUTHORITY = "file_authority";
+
+ private CreateUserDialogController mCreateUserDialogController;
+ @VisibleForTesting
+ Dialog mSetupUserDialog;
+
+
+ /**
+ * Creates intent to start CreateUserActivity
+ */
+ public static @NonNull Intent createIntentForStart(@NonNull Context context,
+ boolean canCreateAdminUser, @NonNull String fileAuth) {
+ Intent intent = new Intent(context, CreateUserActivity.class);
+ intent.putExtra(EXTRA_CAN_CREATE_ADMIN, canCreateAdminUser);
+ intent.putExtra(EXTRA_FILE_AUTHORITY, fileAuth);
+ return intent;
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = getIntent();
+
+ mCreateUserDialogController = new CreateUserDialogController(
+ intent.getStringExtra(EXTRA_FILE_AUTHORITY));
+ setContentView(R.layout.activity_create_new_user);
+ if (savedInstanceState != null) {
+ mCreateUserDialogController.onRestoreInstanceState(savedInstanceState);
+ }
+ mSetupUserDialog = createDialog(intent.getBooleanExtra(EXTRA_CAN_CREATE_ADMIN, false));
+ mSetupUserDialog.show();
+ }
+
+ @Override
+ protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ Bundle savedDialogState = savedInstanceState.getBundle(DIALOG_STATE_KEY);
+ if (savedDialogState != null && mSetupUserDialog != null) {
+ mSetupUserDialog.onRestoreInstanceState(savedDialogState);
+ }
+ }
+
+ private Dialog createDialog(boolean canCreateAdminUser) {
+ return mCreateUserDialogController.createDialog(
+ this,
+ this::startActivity,
+ canCreateAdminUser,
+ this::setSuccessResult,
+ this::cancel
+ );
+ }
+
+ @Override
+ public boolean onTouchEvent(@Nullable MotionEvent event) {
+ onBackInvoked();
+ return super.onTouchEvent(event);
+ }
+
+ private void onBackInvoked() {
+ if (mSetupUserDialog != null) {
+ mSetupUserDialog.dismiss();
+ }
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+ @VisibleForTesting
+ void setSuccessResult(String userName, Drawable userIcon, String path, Boolean isAdmin) {
+ Intent intent = new Intent(this, CreateUserActivity.class);
+ intent.putExtra(EXTRA_USER_NAME, userName);
+ intent.putExtra(EXTRA_IS_ADMIN, isAdmin);
+ intent.putExtra(EXTRA_USER_ICON_PATH, path);
+
+ mSetupUserDialog.dismiss();
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+
+ @VisibleForTesting
+ void cancel() {
+ mSetupUserDialog.dismiss();
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull Bundle outState) {
+ if (mSetupUserDialog != null && mSetupUserDialog.isShowing()) {
+ outState.putBundle(DIALOG_STATE_KEY, mSetupUserDialog.onSaveInstanceState());
+ }
+ mCreateUserDialogController.onSaveInstanceState(outState);
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mCreateUserDialogController.onActivityResult(requestCode, resultCode, data);
+ }
+
+ private void startActivity(Intent intent, int requestCode) {
+ startActivityForResult(intent, requestCode);
+ mCreateUserDialogController.startingActivityForResult();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java b/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java
index d71b337..d9f1b63 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java
@@ -242,7 +242,7 @@
.setMessage(messageResId)
.setNegativeButtonText(R.string.cancel)
.setPositiveButtonText(R.string.next);
- mCustomDialogHelper.requestFocusOnTitle();
+ focus();
break;
case GRANT_ADMIN_DIALOG:
mEditUserInfoView.setVisibility(View.GONE);
@@ -255,7 +255,7 @@
.setMessage(R.string.user_grant_admin_message)
.setNegativeButtonText(R.string.back)
.setPositiveButtonText(R.string.next);
- mCustomDialogHelper.requestFocusOnTitle();
+ focus();
if (mIsAdmin == null) {
mCustomDialogHelper.setButtonEnabled(false);
}
@@ -267,7 +267,7 @@
.setTitle(R.string.user_info_settings_title)
.setNegativeButtonText(R.string.back)
.setPositiveButtonText(R.string.done);
- mCustomDialogHelper.requestFocusOnTitle();
+ focus();
mEditUserInfoView.setVisibility(View.VISIBLE);
mGrantAdminView.setVisibility(View.GONE);
break;
@@ -282,7 +282,7 @@
mCustomDialogHelper.getDialog().dismiss();
break;
case EXIT_DIALOG:
- mCustomDialogHelper.getDialog().dismiss();
+ finish();
break;
default:
if (mCurrentState < EXIT_DIALOG) {
@@ -394,13 +394,21 @@
return mCustomDialogHelper != null && mCustomDialogHelper.getDialog() != null;
}
+ void focus() {
+ mCustomDialogHelper.requestFocusOnTitle();
+ }
+
/**
* Runs callback and clears saved values after dialog is dismissed.
*/
public void finish() {
if (mCurrentState == CREATE_USER_AND_CLOSE) {
if (mSuccessCallback != null) {
- mSuccessCallback.onSuccess(mUserName, mNewUserIcon, Boolean.TRUE.equals(mIsAdmin));
+ if (mEditUserPhotoController != null && mCachedDrawablePath == null) {
+ mCachedDrawablePath = mEditUserPhotoController.getCachedDrawablePath();
+ }
+ mSuccessCallback.onSuccess(mUserName, mNewUserIcon, mCachedDrawablePath,
+ Boolean.TRUE.equals(mIsAdmin));
}
} else {
if (mCancelCallback != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/NewUserData.java b/packages/SettingsLib/src/com/android/settingslib/users/NewUserData.java
index 3d18b59..eed608e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/NewUserData.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/NewUserData.java
@@ -18,6 +18,8 @@
import android.graphics.drawable.Drawable;
+import androidx.annotation.Nullable;
+
/**
* Defines a callback when a new user data is filled out.
*/
@@ -27,8 +29,10 @@
* Consumes data relevant to new user that needs to be created.
* @param userName New user name.
* @param userImage New user icon.
+ * @param iconPath New user icon path.
* @param isNewUserAdmin A boolean that indicated whether new user has admin status.
*/
- void onSuccess(String userName, Drawable userImage, Boolean isNewUserAdmin);
+ void onSuccess(@Nullable String userName, @Nullable Drawable userImage,
+ @Nullable String iconPath, @Nullable Boolean isNewUserAdmin);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
index c71b19c..88bccc9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
@@ -119,12 +119,16 @@
private fun getIconsBasedOnFlag(): IntArray {
return if (newStatusBarIcons()) {
+ // TODO(b/396664075):
+ // The new wifi icons only define a range of [0, 3]. Since this array is indexed on
+ // level, we can simulate the range squash by mapping both level 3 to drawn-level 2,
+ // and level 4 to drawn-level 3
intArrayOf(
R.drawable.ic_wifi_0,
R.drawable.ic_wifi_1,
R.drawable.ic_wifi_2,
+ R.drawable.ic_wifi_2,
R.drawable.ic_wifi_3,
- R.drawable.ic_wifi_4
)
} else {
intArrayOf(
@@ -141,12 +145,13 @@
private fun getErrorIconsBasedOnFlag(): IntArray {
return if (newStatusBarIcons()) {
+ // See above note, new wifi icons only have 3 bars, so levels 2 and 3 are the same
intArrayOf(
R.drawable.ic_wifi_0_error,
R.drawable.ic_wifi_1_error,
R.drawable.ic_wifi_2_error,
+ R.drawable.ic_wifi_2_error,
R.drawable.ic_wifi_3_error,
- R.drawable.ic_wifi_4_error
)
} else {
intArrayOf(
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/AmbientVolumeControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/AmbientVolumeControllerTest.java
index abc1d226..e4381ae 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/AmbientVolumeControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/AmbientVolumeControllerTest.java
@@ -26,6 +26,7 @@
import android.bluetooth.AudioInputControl;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
@@ -67,6 +68,9 @@
@Before
public void setUp() {
when(mProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControlProfile);
+ when(mVolumeControlProfile.isProfileReady()).thenReturn(true);
+ when(mVolumeControlProfile.getConnectionStatus(mDevice)).thenReturn(
+ BluetoothProfile.STATE_CONNECTED);
when(mDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mDevice.isConnected()).thenReturn(true);
mVolumeController = new AmbientVolumeController(mProfileManager, mCallback);
@@ -74,8 +78,6 @@
@Test
public void onServiceConnected_notifyCallback() {
- when(mVolumeControlProfile.isProfileReady()).thenReturn(true);
-
mVolumeController.onServiceConnected();
verify(mCallback).onVolumeControlServiceConnected();
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 ebe6128..0325c0e 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
@@ -15,7 +15,9 @@
*/
package com.android.settingslib.bluetooth;
+import static com.android.settingslib.bluetooth.BluetoothUtils.getInputDevice;
import static com.android.settingslib.bluetooth.BluetoothUtils.isAvailableAudioSharingMediaBluetoothDevice;
+import static com.android.settingslib.bluetooth.BluetoothUtils.isDeviceStylus;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.UNKNOWN_VALUE_PLACEHOLDER;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_DETERMINING_ADVANCED_DETAILS_HEADER_WITH_METADATA;
@@ -42,6 +44,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
+import android.hardware.input.InputManager;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
@@ -51,6 +54,7 @@
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.util.Pair;
+import android.view.InputDevice;
import com.android.internal.R;
import com.android.settingslib.flags.Flags;
@@ -97,14 +101,18 @@
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
@Mock private CachedBluetoothDeviceManager mDeviceManager;
@Mock private BluetoothLeBroadcastReceiveState mLeBroadcastReceiveState;
+ @Mock
+ private InputManager mInputManager;
private Context mContext;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+ private final InputDevice mInputDevice = mock(InputDevice.class);
private static final String STRING_METADATA = "string_metadata";
private static final String LE_AUDIO_SHARING_METADATA = "le_audio_sharing";
private static final String BOOL_METADATA = "true";
private static final String INT_METADATA = "25";
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
+ private static final int TEST_DEVICE_ID = 123;
private static final String KEY_HEARABLE_CONTROL_SLICE = "HEARABLE_CONTROL_SLICE_WITH_WIDTH";
private static final String CONTROL_METADATA =
"<HEARABLE_CONTROL_SLICE_WITH_WIDTH>"
@@ -115,6 +123,7 @@
private static final String FAKE_TEMP_BOND_METADATA = "<TEMP_BOND_TYPE>fake</TEMP_BOND_TYPE>";
private static final String TEST_EXCLUSIVE_MANAGER_PACKAGE = "com.test.manager";
private static final String TEST_EXCLUSIVE_MANAGER_COMPONENT = "com.test.manager/.component";
+ private static final String TEST_ADDRESS = "11:22:33:44:55:66";
private static final int TEST_BROADCAST_ID = 25;
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -134,6 +143,10 @@
when(mA2dpProfile.getProfileId()).thenReturn(BluetoothProfile.A2DP);
when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO);
when(mHearingAid.getProfileId()).thenReturn(BluetoothProfile.HEARING_AID);
+ when(mContext.getSystemService(InputManager.class)).thenReturn(mInputManager);
+ when(mInputManager.getInputDeviceIds()).thenReturn(new int[]{TEST_DEVICE_ID});
+ when(mInputManager.getInputDeviceBluetoothAddress(TEST_DEVICE_ID)).thenReturn(TEST_ADDRESS);
+ when(mInputManager.getInputDevice(TEST_DEVICE_ID)).thenReturn(mInputDevice);
}
@Test
@@ -1097,9 +1110,8 @@
@Test
public void getAudioDeviceAttributesForSpatialAudio_bleHeadset() {
- String address = "11:22:33:44:55:66";
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mLeAudioProfile));
when(mLeAudioProfile.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1112,14 +1124,13 @@
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_BLE_HEADSET,
- address));
+ TEST_ADDRESS));
}
@Test
public void getAudioDeviceAttributesForSpatialAudio_bleSpeaker() {
- String address = "11:22:33:44:55:66";
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mLeAudioProfile));
when(mLeAudioProfile.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1132,14 +1143,14 @@
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_BLE_SPEAKER,
- address));
+ TEST_ADDRESS));
}
@Test
public void getAudioDeviceAttributesForSpatialAudio_a2dp() {
- String address = "11:22:33:44:55:66";
+
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mA2dpProfile));
when(mA2dpProfile.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1152,14 +1163,13 @@
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
- address));
+ TEST_ADDRESS));
}
@Test
public void getAudioDeviceAttributesForSpatialAudio_hearingAid() {
- String address = "11:22:33:44:55:66";
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mHearingAid));
when(mHearingAid.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1172,7 +1182,7 @@
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_HEARING_AID,
- address));
+ TEST_ADDRESS));
}
@Test
@@ -1375,4 +1385,54 @@
verify(mBluetoothDevice).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
TEMP_BOND_METADATA.getBytes());
}
+
+ @Test
+ public void getInputDevice_addressNotMatched_returnsNull() {
+ assertThat(getInputDevice(mContext, "123")).isNull();
+ }
+
+ @Test
+ public void getInputDevice_isInputDevice_returnsInputDevice() {
+ assertThat(getInputDevice(mContext, TEST_ADDRESS)).isEqualTo(mInputDevice);
+ }
+
+ @Test
+ public void isDeviceStylus_noDevices_false() {
+ assertThat(isDeviceStylus(null, null)).isFalse();
+ }
+
+ @Test
+ public void isDeviceStylus_nonStylusInputDevice_false() {
+ InputDevice inputDevice = new InputDevice.Builder()
+ .setSources(InputDevice.SOURCE_DPAD)
+ .build();
+
+ assertThat(isDeviceStylus(inputDevice, null)).isFalse();
+ }
+
+ @Test
+ public void isDeviceStylus_stylusInputDevice_true() {
+ InputDevice inputDevice = new InputDevice.Builder()
+ .setSources(InputDevice.SOURCE_STYLUS)
+ .build();
+
+ assertThat(isDeviceStylus(inputDevice, null)).isTrue();
+ }
+
+ @Test
+ public void isDeviceStylus_nonStylusBluetoothDevice_false() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+ BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
+
+ assertThat(isDeviceStylus(null, mCachedBluetoothDevice)).isFalse();
+ }
+
+ @Test
+ public void isDeviceStylus_stylusBluetoothDevice_true() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+ BluetoothDevice.DEVICE_TYPE_STYLUS.getBytes());
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+
+ assertThat(isDeviceStylus(null, mCachedBluetoothDevice)).isTrue();
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 69e99c6..94199df 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -662,10 +662,10 @@
@Test
@RequiresFlagsEnabled(
com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICE_SET_CONNECTION_STATUS_REPORT)
- public void onDeviceUnpaired_hearingDevice_callReportConnectionStatus() {
+ public void onDeviceUnpaired_containsHearingAidInfo_callReportConnectionStatus() {
when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
- when(mCachedDevice1.getProfiles()).thenReturn(
- ImmutableList.of(mHapClientProfile, mHearingAidProfile));
+ mCachedDevice1.setHearingAidInfo(
+ new HearingAidInfo.Builder().setHiSyncId(HISYNCID1).build());
mCachedDeviceManager.onDeviceUnpaired(mCachedDevice1);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java
index 2eccaa6..fd14d1f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CsipDeviceManagerTest.java
@@ -40,8 +40,6 @@
import android.os.Looper;
import android.os.Parcel;
import android.os.UserManager;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import com.android.settingslib.flags.Flags;
@@ -76,9 +74,6 @@
private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
private final static String DEVICE_ADDRESS_3 = "AA:BB:CC:DD:EE:33";
- private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
- private static final String TEMP_BOND_METADATA =
- "<TEMP_BOND_TYPE>le_audio_sharing</TEMP_BOND_TYPE>";
private final static int GROUP1 = 1;
private final BluetoothClass DEVICE_CLASS_1 =
createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
@@ -342,7 +337,6 @@
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void addMemberDevicesIntoMainDevice_preferredDeviceIsMainAndTwoMain_returnTrue() {
// Condition: The preferredDevice is main and there is another main device in top list
// Expected Result: return true and there is the preferredDevice in top list
@@ -352,6 +346,7 @@
mCachedDevices.add(preferredDevice);
mCachedDevices.add(mCachedDevice2);
mCachedDevices.add(mCachedDevice3);
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
.isTrue();
@@ -364,7 +359,6 @@
}
@Test
- @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
public void
addMemberDevicesIntoMainDevice_preferredDeviceIsMainAndTwoMain_workProfile_doNothing() {
// Condition: The preferredDevice is main and there is another main device in top list
@@ -375,6 +369,7 @@
mCachedDevices.add(preferredDevice);
mCachedDevices.add(mCachedDevice2);
mCachedDevices.add(mCachedDevice3);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
when(mBroadcast.isEnabled(null)).thenReturn(true);
BluetoothLeBroadcastMetadata metadata = Mockito.mock(BluetoothLeBroadcastMetadata.class);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(metadata);
@@ -382,8 +377,6 @@
BluetoothLeBroadcastReceiveState.class);
when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L));
when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(state));
- when(mDevice2.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
- .thenReturn(TEMP_BOND_METADATA.getBytes());
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
when(mUserManager.isManagedProfile()).thenReturn(true);
@@ -394,13 +387,10 @@
assertThat(mCachedDevices.contains(mCachedDevice3)).isTrue();
assertThat(preferredDevice.getMemberDevice()).contains(mCachedDevice2);
verify(mAssistant, never()).addSource(mDevice1, metadata, /* isGroupOp= */ false);
- verify(mDevice1, never()).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
- TEMP_BOND_METADATA.getBytes());
}
@Test
- @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
- public void addMemberDevicesIntoMainDevice_preferredDeviceIsMainAndTwoMain_syncState() {
+ public void addMemberDevicesIntoMainDevice_preferredDeviceIsMainAndTwoMain_syncSource() {
// Condition: The preferredDevice is main and there is another main device in top list
// Expected Result: return true and there is the preferredDevice in top list
CachedBluetoothDevice preferredDevice = mCachedDevice1;
@@ -409,6 +399,7 @@
mCachedDevices.add(preferredDevice);
mCachedDevices.add(mCachedDevice2);
mCachedDevices.add(mCachedDevice3);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
when(mBroadcast.isEnabled(null)).thenReturn(true);
BluetoothLeBroadcastMetadata metadata = Mockito.mock(BluetoothLeBroadcastMetadata.class);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(metadata);
@@ -416,8 +407,6 @@
BluetoothLeBroadcastReceiveState.class);
when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L));
when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(state));
- when(mDevice2.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
- .thenReturn(TEMP_BOND_METADATA.getBytes());
assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
.isTrue();
@@ -426,8 +415,6 @@
assertThat(mCachedDevices.contains(mCachedDevice3)).isTrue();
assertThat(preferredDevice.getMemberDevice()).contains(mCachedDevice2);
verify(mAssistant).addSource(mDevice1, metadata, /* isGroupOp= */ false);
- verify(mDevice1).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
- TEMP_BOND_METADATA.getBytes());
}
@Test
@@ -449,13 +436,13 @@
}
@Test
- @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
public void addMemberDevicesIntoMainDevice_preferredDeviceIsMemberAndTwoMain_returnTrue() {
// Condition: The preferredDevice is member and there are two main device in top list
// Expected Result: return true and there is the preferredDevice in top list
CachedBluetoothDevice preferredDevice = mCachedDevice2;
BluetoothDevice expectedMainBluetoothDevice = preferredDevice.getDevice();
mCachedDevice3.setGroupId(GROUP1);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
when(mBroadcast.isEnabled(null)).thenReturn(false);
assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
@@ -470,20 +457,16 @@
assertThat(mCachedDevice1.getDevice()).isEqualTo(expectedMainBluetoothDevice);
verify(mAssistant, never()).addSource(any(BluetoothDevice.class),
any(BluetoothLeBroadcastMetadata.class), anyBoolean());
- verify(mDevice2, never()).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
- TEMP_BOND_METADATA.getBytes());
- verify(mDevice3, never()).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
- TEMP_BOND_METADATA.getBytes());
}
@Test
- @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
- public void addMemberDevicesIntoMainDevice_preferredDeviceIsMemberAndTwoMain_syncState() {
+ public void addMemberDevicesIntoMainDevice_preferredDeviceIsMemberAndTwoMain_syncSource() {
// Condition: The preferredDevice is member and there are two main device in top list
// Expected Result: return true and there is the preferredDevice in top list
CachedBluetoothDevice preferredDevice = mCachedDevice2;
BluetoothDevice expectedMainBluetoothDevice = preferredDevice.getDevice();
mCachedDevice3.setGroupId(GROUP1);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
when(mBroadcast.isEnabled(null)).thenReturn(true);
BluetoothLeBroadcastMetadata metadata = Mockito.mock(BluetoothLeBroadcastMetadata.class);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(metadata);
@@ -491,8 +474,6 @@
BluetoothLeBroadcastReceiveState.class);
when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L));
when(mAssistant.getAllSources(mDevice1)).thenReturn(ImmutableList.of(state));
- when(mDevice1.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
- .thenReturn(TEMP_BOND_METADATA.getBytes());
assertThat(mCsipDeviceManager.addMemberDevicesIntoMainDevice(GROUP1, preferredDevice))
.isTrue();
@@ -507,10 +488,6 @@
assertThat(mCachedDevice1.getDevice()).isEqualTo(expectedMainBluetoothDevice);
verify(mAssistant).addSource(mDevice2, metadata, /* isGroupOp= */ false);
verify(mAssistant).addSource(mDevice3, metadata, /* isGroupOp= */ false);
- verify(mDevice2).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
- TEMP_BOND_METADATA.getBytes());
- verify(mDevice3).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
- TEMP_BOND_METADATA.getBytes());
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
index 6b30f15..71ecf5b7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
@@ -21,6 +21,7 @@
import static android.app.AutomaticZenRule.TYPE_IMMERSIVE;
import static android.app.AutomaticZenRule.TYPE_OTHER;
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
+import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
import static android.app.AutomaticZenRule.TYPE_THEATER;
import static android.app.AutomaticZenRule.TYPE_UNKNOWN;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
@@ -35,6 +36,8 @@
import static org.junit.Assert.assertThrows;
import android.app.AutomaticZenRule;
+import android.content.ComponentName;
+import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
import android.service.notification.Condition;
@@ -43,13 +46,17 @@
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenPolicy;
+import androidx.test.core.app.ApplicationProvider;
+
import com.android.internal.R;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
+import java.util.Calendar;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@@ -72,6 +79,13 @@
.setType(TYPE_OTHER)
.build();
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
+ }
+
@Test
public void testBasicMethods_mode() {
ZenMode zenMode = new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, true));
@@ -95,7 +109,7 @@
assertThat(manualMode.canEditPolicy()).isTrue();
assertThat(manualMode.canBeDeleted()).isFalse();
assertThat(manualMode.isActive()).isFalse();
- assertThat(manualMode.getRule().getPackageName()).isEqualTo(PACKAGE_ANDROID);
+ assertThat(manualMode.getOwnerPackage()).isEqualTo(PACKAGE_ANDROID);
}
@Test
@@ -153,7 +167,7 @@
public void isCustomManual_scheduleTime_false() {
AutomaticZenRule rule = new AutomaticZenRule.Builder("Mode", Uri.parse("x"))
.setPackage(SystemZenRules.PACKAGE_ANDROID)
- .setType(AutomaticZenRule.TYPE_SCHEDULE_TIME)
+ .setType(TYPE_SCHEDULE_TIME)
.build();
ZenMode mode = new ZenMode("id", rule, zenConfigRuleFor(rule, false));
@@ -194,6 +208,23 @@
}
@Test
+ public void getOwner_returnsOwnerDetails() {
+ AutomaticZenRule azr = new AutomaticZenRule.Builder("Rule", Uri.EMPTY)
+ .setPackage("package")
+ .setConfigurationActivity(new ComponentName("package", "configActivity"))
+ .setOwner(new ComponentName("package", "conditionService"))
+ .build();
+ ZenMode zenMode = new ZenMode("id", azr, zenConfigRuleFor(azr, false));
+
+ ZenMode.Owner owner = zenMode.getOwner();
+ assertThat(owner.packageName()).isEqualTo("package");
+ assertThat(owner.configurationActivity()).isEqualTo(
+ new ComponentName("package", "configActivity"));
+ assertThat(owner.conditionProvider()).isEqualTo(
+ new ComponentName("package", "conditionService"));
+ }
+
+ @Test
public void getPolicy_interruptionFilterPriority_returnsZenPolicy() {
AutomaticZenRule azr = new AutomaticZenRule.Builder("Rule", Uri.EMPTY)
.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
@@ -245,7 +276,7 @@
zenMode.setPolicy(ZEN_POLICY);
- assertThat(zenMode.getRule().getInterruptionFilter()).isEqualTo(
+ assertThat(zenMode.getInterruptionFilter()).isEqualTo(
INTERRUPTION_FILTER_PRIORITY);
assertThat(zenMode.getPolicy()).isEqualTo(ZEN_POLICY);
assertThat(zenMode.getRule().getZenPolicy()).isEqualTo(ZEN_POLICY);
@@ -397,6 +428,7 @@
assertThat(iconKey.resPackage()).isEqualTo("some.package");
assertThat(iconKey.resId()).isEqualTo(123);
+ assertThat(mode.getIconResId()).isEqualTo(123);
}
@Test
@@ -411,6 +443,7 @@
assertThat(iconKey.resPackage()).isNull();
assertThat(iconKey.resId()).isEqualTo(123);
+ assertThat(mode.getIconResId()).isEqualTo(123);
}
@Test
@@ -425,15 +458,18 @@
assertThat(iconKey.resPackage()).isEqualTo("some.package");
assertThat(iconKey.resId()).isEqualTo(123);
+ assertThat(mode.getIconResId()).isEqualTo(123);
}
@Test
public void getIconKey_manualDnd_isDndIcon() {
- ZenIcon.Key iconKey = TestModeBuilder.MANUAL_DND.getIconKey();
+ ZenMode mode = TestModeBuilder.MANUAL_DND;
+ ZenIcon.Key iconKey = mode.getIconKey();
assertThat(iconKey.resPackage()).isNull();
assertThat(iconKey.resId()).isEqualTo(
com.android.internal.R.drawable.ic_zen_mode_type_special_dnd);
+ assertThat(mode.getIconResId()).isEqualTo(0);
}
@Test
@@ -448,6 +484,7 @@
assertThat(iconKey.resPackage()).isNull();
assertThat(iconKey.resId()).isEqualTo(
com.android.internal.R.drawable.ic_zen_mode_type_bedtime);
+ assertThat(mode.getIconResId()).isEqualTo(0);
}
@Test
@@ -462,6 +499,7 @@
assertThat(iconKey.resPackage()).isNull();
assertThat(iconKey.resId()).isEqualTo(
com.android.internal.R.drawable.ic_zen_mode_type_schedule_calendar);
+ assertThat(mode.getIconResId()).isEqualTo(0);
}
@Test
@@ -477,6 +515,77 @@
assertThat(iconKey.resPackage()).isNull();
assertThat(iconKey.resId()).isEqualTo(
com.android.internal.R.drawable.ic_zen_mode_type_special_dnd);
+ assertThat(mode.getIconResId()).isEqualTo(0);
+ }
+
+ @Test
+ public void setCustomModeConditionId_timeSchedule() {
+ ZenMode mode = new TestModeBuilder()
+ .setPackage(PACKAGE_ANDROID)
+ .build();
+ ZenModeConfig.ScheduleInfo timeSchedule = new ZenModeConfig.ScheduleInfo();
+ timeSchedule.startHour = 9;
+ timeSchedule.endHour = 12;
+ timeSchedule.days = new int[] {Calendar.SATURDAY, Calendar.SUNDAY};
+ Uri scheduleUri = ZenModeConfig.toScheduleConditionId(timeSchedule);
+
+ mode.setCustomModeConditionId(mContext, scheduleUri);
+
+ assertThat(mode.getType()).isEqualTo(TYPE_SCHEDULE_TIME);
+ assertThat(ZenModeSchedules.getTimeSchedule(mode)).isEqualTo(timeSchedule);
+ assertThat(mode.getTriggerDescription()).isEqualTo("Sun, Sat, 9:00 AM - 12:00 PM");
+
+ assertThat(mode.getRule().getConditionId()).isEqualTo(scheduleUri);
+ assertThat(mode.getRule().getOwner()).isEqualTo(
+ ZenModeConfig.getScheduleConditionProvider());
+ }
+
+ @Test
+ public void setCustomModeConditionId_calendarSchedule() {
+ ZenMode mode = new TestModeBuilder()
+ .setPackage(PACKAGE_ANDROID)
+ .build();
+ ZenModeConfig.EventInfo calendarSchedule = new ZenModeConfig.EventInfo();
+ calendarSchedule.calendarId = 1L;
+ calendarSchedule.calName = "My events";
+ Uri scheduleUri = ZenModeConfig.toEventConditionId(calendarSchedule);
+
+ mode.setCustomModeConditionId(mContext, scheduleUri);
+
+ assertThat(mode.getType()).isEqualTo(TYPE_SCHEDULE_CALENDAR);
+ assertThat(ZenModeSchedules.getCalendarSchedule(mode)).isEqualTo(calendarSchedule);
+ assertThat(mode.getTriggerDescription()).isEqualTo("My events");
+
+ assertThat(mode.getRule().getConditionId()).isEqualTo(scheduleUri);
+ assertThat(mode.getRule().getOwner()).isEqualTo(
+ ZenModeConfig.getEventConditionProvider());
+ }
+
+ @Test
+ public void setCustomModeConditionId_manualSchedule() {
+ ZenMode mode = new TestModeBuilder()
+ .setPackage(PACKAGE_ANDROID)
+ .build();
+
+ mode.setCustomModeConditionId(mContext, ZenModeConfig.toCustomManualConditionId());
+
+ assertThat(mode.getType()).isEqualTo(TYPE_OTHER);
+ assertThat(mode.getTriggerDescription()).isEqualTo("");
+
+ assertThat(mode.getRule().getConditionId()).isEqualTo(
+ ZenModeConfig.toCustomManualConditionId());
+ assertThat(mode.getRule().getOwner()).isEqualTo(
+ ZenModeConfig.getCustomManualConditionProvider());
+ }
+
+ @Test
+ public void setCustomModeConditionId_nonSystemRule_throws() {
+ ZenMode mode = new TestModeBuilder()
+ .setPackage("some.other.package")
+ .build();
+
+ assertThrows(IllegalStateException.class,
+ () -> mode.setCustomModeConditionId(mContext, Uri.parse("blah")));
}
private static void assertUnparceledIsEqualToOriginal(String type, ZenMode original) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserActivityTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserActivityTest.java
new file mode 100644
index 0000000..f58eb7c
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserActivityTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.users;
+
+import static com.android.settingslib.users.CreateUserActivity.EXTRA_IS_ADMIN;
+import static com.android.settingslib.users.CreateUserActivity.EXTRA_USER_ICON_PATH;
+import static com.android.settingslib.users.CreateUserActivity.EXTRA_USER_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.MotionEvent;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class CreateUserActivityTest {
+
+ private static final String TEST_USER_NAME = "test_user";
+ private static final String TEST_USER_ICON_PATH = "/test_path";
+ private static final boolean TEST_IS_ADMIN = true;
+
+ private Context mContext;
+ private CreateUserActivity mCreateUserActivity;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mCreateUserActivity = Robolectric.buildActivity(CreateUserActivity.class).setup().get();
+ }
+
+ @Test
+ public void startActivity_startsActivityForResult() {
+ Intent activityIntent = CreateUserActivity.createIntentForStart(mContext, true, "");
+ mCreateUserActivity.startActivity(activityIntent, null);
+
+ assertThat(shadowOf(mCreateUserActivity).getNextStartedActivityForResult().intent)
+ .isEqualTo(activityIntent);
+ }
+
+ @Test
+ public void onTouchEvent_dismissesDialogAndCancelsResult() {
+ mCreateUserActivity.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0,
+ 0));
+
+ assertThat(mCreateUserActivity.mSetupUserDialog.isShowing()).isFalse();
+ assertThat(shadowOf(mCreateUserActivity).getResultCode())
+ .isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ public void setSuccessResult_dismissesDialogAndSetsSuccessResult() {
+ Drawable mockDrawable = mock(Drawable.class);
+
+ mCreateUserActivity.setSuccessResult(TEST_USER_NAME, mockDrawable, TEST_USER_ICON_PATH,
+ TEST_IS_ADMIN);
+
+ assertThat(mCreateUserActivity.mSetupUserDialog.isShowing()).isFalse();
+ assertThat(shadowOf(mCreateUserActivity).getResultCode()).isEqualTo(Activity.RESULT_OK);
+
+ Intent resultIntent = shadowOf(mCreateUserActivity).getResultIntent();
+ assertThat(resultIntent.getStringExtra(EXTRA_USER_NAME)).isEqualTo(TEST_USER_NAME);
+ assertThat(resultIntent.getBooleanExtra(EXTRA_IS_ADMIN, false)).isEqualTo(TEST_IS_ADMIN);
+ assertThat(resultIntent.getStringExtra(EXTRA_USER_ICON_PATH))
+ .isEqualTo(TEST_USER_ICON_PATH);
+ }
+
+ @Test
+ public void cancel_dismissesDialogAndSetsCancelResult() {
+ mCreateUserActivity.cancel();
+
+ assertThat(mCreateUserActivity.mSetupUserDialog.isShowing()).isFalse();
+ assertThat(shadowOf(mCreateUserActivity).getResultCode())
+ .isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ public void onSaveInstanceState_savesDialogState() {
+ Bundle outState = new Bundle();
+ mCreateUserActivity.onSaveInstanceState(outState);
+
+ CreateUserActivity restoredActivity =
+ Robolectric.buildActivity(CreateUserActivity.class).setup(outState).get();
+
+ assertThat(restoredActivity.mSetupUserDialog).isNotNull();
+ assertThat(restoredActivity.mSetupUserDialog.isShowing()).isTrue();
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
index 6831222..e602323 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
@@ -211,7 +211,7 @@
editText.setText(expectedNewName);
next.performClick();
verify(successCallback, times(1))
- .onSuccess(expectedNewName, null, true);
+ .onSuccess(expectedNewName, null, null, true);
verifyNoInteractions(cancelCallback);
}
@@ -233,7 +233,7 @@
editText.setText(expectedNewName);
next.performClick();
verify(successCallback, times(1))
- .onSuccess(expectedNewName, null, false);
+ .onSuccess(expectedNewName, null, null, false);
verifyNoInteractions(cancelCallback);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 9505977..f03a5fb 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1696,6 +1696,7 @@
proto.write(SettingProto.DEFAULT_VALUE, setting.getDefaultValue());
proto.write(SettingProto.DEFAULT_FROM_SYSTEM, setting.isDefaultFromSystem());
}
+ proto.write(SettingProto.PRESERVED_IN_RESTORE, setting.isValuePreservedInRestore());
proto.end(settingsToken);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 7c588b3..bc281ee 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -988,6 +988,11 @@
if (setting.getTag() != null) {
pw.print(" tag:"); pw.print(setting.getTag());
}
+ // The majority of settings are preserved in restore, so we're just dumping those that
+ // are not (to save space).
+ if (!setting.isValuePreservedInRestore()) {
+ pw.println(" notPreservedInRestore");
+ }
pw.println();
}
}
@@ -1498,7 +1503,7 @@
if (DEBUG) {
Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value + ", "
+ ", " + tag + ", " + makeDefault + ", " + requestingUserId
- + ", " + forceNotify + ")");
+ + ", " + forceNotify + ", " + overrideableByRestore + ")");
}
return mutateGlobalSetting(name, value, tag, makeDefault, requestingUserId,
MUTATION_OPERATION_INSERT, forceNotify, 0, overrideableByRestore);
@@ -1780,7 +1785,7 @@
if (DEBUG) {
Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", "
+ ", " + tag + ", " + makeDefault + ", " + requestingUserId
- + ", " + forceNotify + ")");
+ + ", " + forceNotify + ", " + overrideableByRestore + ")");
}
return mutateSecureSetting(name, value, tag, makeDefault, requestingUserId,
MUTATION_OPERATION_INSERT, forceNotify, 0, overrideableByRestore);
@@ -1941,7 +1946,7 @@
boolean overrideableByRestore) {
if (DEBUG) {
Slog.v(LOG_TAG, "insertSystemSetting(" + name + ", " + value + ", "
- + requestingUserId + ")");
+ + requestingUserId + ", " + overrideableByRestore + ")");
}
return mutateSystemSetting(name, value, /* tag= */ null, requestingUserId,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 17ebf6f..0484def 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -30,6 +30,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.util.Slog;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -94,6 +95,8 @@
}
final static class MyShellCommand extends ShellCommand {
+ private static final String LOG_TAG = "SettingsShellCmd";
+
final SettingsProvider mProvider;
final boolean mDumping;
@@ -115,6 +118,7 @@
String mTag = null;
int mResetMode = -1;
boolean mMakeDefault;
+ boolean mOverrideableByRestore;
MyShellCommand(SettingsProvider provider, boolean dumping) {
mProvider = provider;
@@ -209,6 +213,7 @@
return -1;
}
break;
+ // At this point, mVerb == PUT
} else if (mKey == null) {
mKey = arg;
// keep going; there's another PUT arg
@@ -217,36 +222,8 @@
// what we have so far is a valid command
valid = true;
// keep going; there may be another PUT arg
- } else if (mTag == null) {
- mTag = arg;
- if ("default".equalsIgnoreCase(mTag)) {
- mTag = null;
- mMakeDefault = true;
- if (peekNextArg() == null) {
- valid = true;
- } else {
- perr.println("Too many arguments");
- return -1;
- }
- break;
- }
- if (peekNextArg() == null) {
- valid = true;
- break;
- }
- } else { // PUT, final arg
- if (!"default".equalsIgnoreCase(arg)) {
- perr.println("Argument expected to be 'default'");
- return -1;
- }
- mMakeDefault = true;
- if (peekNextArg() == null) {
- valid = true;
- } else {
- perr.println("Too many arguments");
- return -1;
- }
- break;
+ } else {
+ valid = parseOptionalPutArgument(arg);
}
} while ((arg = getNextArg()) != null);
@@ -275,7 +252,8 @@
pout.println(getForUser(iprovider, mUser, mTable, mKey));
break;
case PUT:
- putForUser(iprovider, mUser, mTable, mKey, mValue, mTag, mMakeDefault);
+ putForUser(iprovider, mUser, mTable, mKey, mValue, mTag, mMakeDefault,
+ mOverrideableByRestore);
break;
case DELETE:
pout.println("Deleted "
@@ -297,6 +275,41 @@
return 0;
}
+ private boolean parseOptionalPutArgument(String arg) {
+ boolean valid = true;
+ // Given that the order is TAG default overrideableByRestore, we need to parse from the
+ // opposite direction
+ switch (arg) {
+ case "overrideableByRestore":
+ if (mOverrideableByRestore) {
+ valid = false;
+ } else {
+ mOverrideableByRestore = true;
+ }
+ break;
+ case "default":
+ if (mMakeDefault || mOverrideableByRestore) {
+ valid = false;
+ } else {
+ mMakeDefault = true;
+ }
+ break;
+ default: // tag
+ if (mMakeDefault || mOverrideableByRestore || mTag != null) {
+ valid = false;
+ } else {
+ mTag = arg;
+ }
+ break;
+ }
+ if (!valid) {
+ Slog.e(LOG_TAG, "parseOptionalPutArgument(" + arg + "): invalid state ("
+ + "mTag=" + mTag + ", mMakeDefault=" + mMakeDefault
+ + ", mOverrideableByRestore=" + mOverrideableByRestore + ")");
+ }
+ return valid;
+ }
+
List<String> listForUser(IContentProvider provider, int userHandle, String table) {
final String callListCommand;
if ("system".equals(table)) callListCommand = Settings.CALL_METHOD_LIST_SYSTEM;
@@ -351,7 +364,11 @@
}
void putForUser(IContentProvider provider, int userHandle, final String table,
- final String key, final String value, String tag, boolean makeDefault) {
+ final String key, final String value, String tag, boolean makeDefault,
+ boolean overrideableByRestore) {
+ Slog.v(LOG_TAG, "putForUser(userId=" + userHandle + ", table=" + table + ", key=" + key
+ + ", value=" + value + ", tag=" + tag + ", makeDefault=" + makeDefault
+ + ", overrideableByRestore=" + overrideableByRestore + ")");
final String callPutCommand;
if ("system".equals(table)) {
callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
@@ -377,6 +394,9 @@
if (makeDefault) {
arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
}
+ if (overrideableByRestore) {
+ arg.putBoolean(Settings.CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY, true);
+ }
final AttributionSource attributionSource = new AttributionSource(
Binder.getCallingUid(), resolveCallingPackage(), /*attributionTag*/ null);
provider.call(attributionSource, Settings.AUTHORITY,
@@ -474,10 +494,11 @@
pw.println(" Print this help text.");
pw.println(" get [--user <USER_ID> | current] NAMESPACE KEY");
pw.println(" Retrieve the current value of KEY.");
- pw.println(" put [--user <USER_ID> | current] NAMESPACE KEY VALUE [TAG] [default]");
+ pw.println(" put [--user <USER_ID> | current] NAMESPACE KEY VALUE [TAG] [default] [overrideableByRestore]");
pw.println(" Change the contents of KEY to VALUE.");
- pw.println(" TAG to associate with the setting.");
+ pw.println(" TAG to associate with the setting (cannot be default or overrideableByRestore).");
pw.println(" {default} to set as the default, case-insensitive only for global/secure namespace");
+ pw.println(" {overrideableByRestore} to let the value be overridden by BackupManager on restore operations");
pw.println(" delete [--user <USER_ID> | current] NAMESPACE KEY");
pw.println(" Delete the entry for KEY.");
pw.println(" reset [--user <USER_ID> | current] NAMESPACE {PACKAGE_NAME | RESET_MODE}");
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 85617ba..70c042c 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -811,7 +811,7 @@
Settings.Secure.V_TO_U_RESTORE_ALLOWLIST,
Settings.Secure.V_TO_U_RESTORE_DENYLIST,
Settings.Secure.REDACT_OTP_NOTIFICATION_WHILE_CONNECTED_TO_WIFI,
- Settings.Secure.REDACT_OTP_NOTIFICATION_IMMEDIATELY);
+ Settings.Secure.OTP_NOTIFICATION_REDACTION_LOCK_TIME);
@Test
public void systemSettingsBackedUpOrDenied() {
diff --git a/packages/SoundPicker/res/values-fr/strings.xml b/packages/SoundPicker/res/values-fr/strings.xml
index 9452e70..bfcbc67 100644
--- a/packages/SoundPicker/res/values-fr/strings.xml
+++ b/packages/SoundPicker/res/values-fr/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="ringtone_default" msgid="798836092118824500">"Sonnerie par défaut"</string>
<string name="notification_sound_default" msgid="8133121186242636840">"Son de notification par défaut"</string>
- <string name="alarm_sound_default" msgid="4787646764557462649">"Son de l\'alarme par défaut"</string>
+ <string name="alarm_sound_default" msgid="4787646764557462649">"Son par défaut de l\'alarme"</string>
<string name="add_ringtone_text" msgid="6642389991738337529">"Ajouter une sonnerie"</string>
<string name="add_alarm_text" msgid="3545497316166999225">"Ajouter une alarme"</string>
<string name="add_notification_text" msgid="4431129543300614788">"Ajouter une notification"</string>
diff --git a/packages/SoundPicker/res/values-mr/strings.xml b/packages/SoundPicker/res/values-mr/strings.xml
index 3ddb991..39c7c4b 100644
--- a/packages/SoundPicker/res/values-mr/strings.xml
+++ b/packages/SoundPicker/res/values-mr/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="ringtone_default" msgid="798836092118824500">"डीफॉल्ट रिंगटोन"</string>
- <string name="notification_sound_default" msgid="8133121186242636840">"डीफॉल्ट सूचना आवाज"</string>
+ <string name="notification_sound_default" msgid="8133121186242636840">"डीफॉल्ट नोटिफिकेशन आवाज"</string>
<string name="alarm_sound_default" msgid="4787646764557462649">"डीफॉल्ट अलार्म आवाज"</string>
<string name="add_ringtone_text" msgid="6642389991738337529">"रिंगटोन जोडा"</string>
<string name="add_alarm_text" msgid="3545497316166999225">"अलार्म जोडा"</string>
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 29b578a..eb5b22f 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1370,6 +1370,16 @@
}
flag {
+ name: "media_controls_a11y_colors"
+ namespace: "systemui"
+ description: "Color scheme updates for improved a11y"
+ bug: "378848399"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "output_switcher_redesign"
namespace: "systemui"
description: "Enables visual update for Media Output Switcher"
@@ -1915,6 +1925,13 @@
}
flag {
+ name: "physical_notification_movement"
+ namespace: "systemui"
+ description: "Make notifications use physics based animations for movement"
+ bug: "393581344"
+}
+
+flag {
name: "glanceable_hub_direct_edit_mode"
namespace: "systemui"
description: "Invokes edit mode directly from long press in glanceable hub"
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
index f8bcb81..bc75b1d 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
@@ -22,19 +22,8 @@
import android.util.LruCache
import android.util.MathUtils
import androidx.annotation.VisibleForTesting
-import java.lang.Float.max
-import java.lang.Float.min
import kotlin.math.roundToInt
-private const val TAG_WGHT = "wght"
-private const val TAG_ITAL = "ital"
-
-private const val FONT_WEIGHT_DEFAULT_VALUE = 400f
-private const val FONT_ITALIC_MAX = 1f
-private const val FONT_ITALIC_MIN = 0f
-private const val FONT_ITALIC_ANIMATION_STEP = 0.1f
-private const val FONT_ITALIC_DEFAULT_VALUE = 0f
-
/** Caches for font interpolation */
interface FontCache {
val animationFrameCount: Int
@@ -91,11 +80,8 @@
class FontInterpolator(val fontCache: FontCache = FontCacheImpl()) {
/** Linear interpolate the font variation settings. */
fun lerp(start: Font, end: Font, progress: Float, linearProgress: Float): Font {
- if (progress == 0f) {
- return start
- } else if (progress == 1f) {
- return end
- }
+ if (progress <= 0f) return start
+ if (progress >= 1f) return end
val startAxes = start.axes ?: EMPTY_AXES
val endAxes = end.axes ?: EMPTY_AXES
@@ -110,7 +96,7 @@
InterpKey(start, end, (linearProgress * fontCache.animationFrameCount).roundToInt())
fontCache.get(iKey)?.let {
if (DEBUG) {
- Log.d(LOG_TAG, "[$progress] Interp. cache hit for $iKey")
+ Log.d(LOG_TAG, "[$progress, $linearProgress] Interp. cache hit for $iKey")
}
return it
}
@@ -121,37 +107,16 @@
// and also pre-fill the missing axes value with default value from 'fvar' table.
val newAxes =
lerp(startAxes, endAxes) { tag, startValue, endValue ->
- when (tag) {
- TAG_WGHT ->
- MathUtils.lerp(
- startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
- endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
- progress,
- )
- TAG_ITAL ->
- adjustItalic(
- MathUtils.lerp(
- startValue ?: FONT_ITALIC_DEFAULT_VALUE,
- endValue ?: FONT_ITALIC_DEFAULT_VALUE,
- progress,
- )
- )
- else -> {
- require(startValue != null && endValue != null) {
- "Unable to interpolate due to unknown default axes value : $tag"
- }
- MathUtils.lerp(startValue, endValue, progress)
- }
- }
+ MathUtils.lerp(startValue, endValue, progress)
}
// Check if we already make font for this axes. This is typically happens if the animation
- // happens backward.
+ // happens backward and is being linearly interpolated.
val vKey = VarFontKey(start, newAxes)
fontCache.get(vKey)?.let {
fontCache.put(iKey, it)
if (DEBUG) {
- Log.d(LOG_TAG, "[$progress] Axis cache hit for $vKey")
+ Log.d(LOG_TAG, "[$progress, $linearProgress] Axis cache hit for $vKey")
}
return it
}
@@ -164,14 +129,14 @@
fontCache.put(vKey, newFont)
// Cache misses are likely to create memory leaks, so this is logged at error level.
- Log.e(LOG_TAG, "[$progress] Cache MISS for $iKey / $vKey")
+ Log.e(LOG_TAG, "[$progress, $linearProgress] Cache MISS for $iKey / $vKey")
return newFont
}
private fun lerp(
start: Array<FontVariationAxis>,
end: Array<FontVariationAxis>,
- filter: (tag: String, left: Float?, right: Float?) -> Float,
+ filter: (tag: String, left: Float, right: Float) -> Float,
): List<FontVariationAxis> {
// Safe to modify result of Font#getAxes since it returns cloned object.
start.sortBy { axis -> axis.tag }
@@ -191,39 +156,37 @@
else -> tagA.compareTo(tagB)
}
- val axis =
+ val tag =
when {
- comp == 0 -> {
- val v = filter(tagA!!, start[i++].styleValue, end[j++].styleValue)
- FontVariationAxis(tagA, v)
- }
- comp < 0 -> {
- val v = filter(tagA!!, start[i++].styleValue, null)
- FontVariationAxis(tagA, v)
- }
- else -> { // comp > 0
- val v = filter(tagB!!, null, end[j++].styleValue)
- FontVariationAxis(tagB, v)
- }
+ comp == 0 -> tagA!!
+ comp < 0 -> tagA!!
+ else -> tagB!!
}
- result.add(axis)
+ val axisDefinition = GSFAxes.getAxis(tag)
+ require(comp == 0 || axisDefinition != null) {
+ "Unable to interpolate due to unknown default axes value: $tag"
+ }
+
+ val axisValue =
+ when {
+ comp == 0 -> filter(tag, start[i++].styleValue, end[j++].styleValue)
+ comp < 0 -> filter(tag, start[i++].styleValue, axisDefinition!!.defaultValue)
+ else -> filter(tag, axisDefinition!!.defaultValue, end[j++].styleValue)
+ }
+
+ // Round axis value to valid intermediate steps. This improves the cache hit rate.
+ val step = axisDefinition?.animationStep ?: DEFAULT_ANIMATION_STEP
+ result.add(FontVariationAxis(tag, (axisValue / step).roundToInt() * step))
}
return result
}
- // For the performance reasons, we animate italic with FONT_ITALIC_ANIMATION_STEP. This helps
- // Cache hit ratio in the Skia glyph cache.
- private fun adjustItalic(value: Float) =
- coerceInWithStep(value, FONT_ITALIC_MIN, FONT_ITALIC_MAX, FONT_ITALIC_ANIMATION_STEP)
-
- private fun coerceInWithStep(v: Float, min: Float, max: Float, step: Float) =
- (v.coerceIn(min, max) / step).toInt() * step
-
companion object {
private const val LOG_TAG = "FontInterpolator"
private val DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG)
private val EMPTY_AXES = arrayOf<FontVariationAxis>()
+ private const val DEFAULT_ANIMATION_STEP = 1f
// Returns true if given two font instance can be interpolated.
fun canInterpolate(start: Font, end: Font) =
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt
index 9545bda..9a74687 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontVariationUtils.kt
@@ -1,12 +1,20 @@
-package com.android.systemui.animation
+/*
+ * 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.
+ */
-object GSFAxes {
- const val WEIGHT = "wght"
- const val WIDTH = "wdth"
- const val SLANT = "slnt"
- const val ROUND = "ROND"
- const val OPTICAL_SIZE = "opsz"
-}
+package com.android.systemui.animation
class FontVariationUtils {
private var mWeight = -1
@@ -46,20 +54,20 @@
}
var resultString = ""
if (mWeight >= 0) {
- resultString += "'${GSFAxes.WEIGHT}' $mWeight"
+ resultString += "'${GSFAxes.WEIGHT.tag}' $mWeight"
}
if (mWidth >= 0) {
resultString +=
- (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.WIDTH}' $mWidth"
+ (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.WIDTH.tag}' $mWidth"
}
if (mOpticalSize >= 0) {
resultString +=
(if (resultString.isBlank()) "" else ", ") +
- "'${GSFAxes.OPTICAL_SIZE}' $mOpticalSize"
+ "'${GSFAxes.OPTICAL_SIZE.tag}' $mOpticalSize"
}
if (mRoundness >= 0) {
resultString +=
- (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.ROUND}' $mRoundness"
+ (if (resultString.isBlank()) "" else ", ") + "'${GSFAxes.ROUND.tag}' $mRoundness"
}
return if (isUpdated) resultString else ""
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt
new file mode 100644
index 0000000..f4e0361
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GSFAxes.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.animation
+
+data class AxisDefinition(
+ val tag: String,
+ val minValue: Float,
+ val defaultValue: Float,
+ val maxValue: Float,
+ val animationStep: Float,
+)
+
+object GSFAxes {
+ val WEIGHT =
+ AxisDefinition(
+ tag = "wght",
+ minValue = 1f,
+ defaultValue = 400f,
+ maxValue = 1000f,
+ animationStep = 10f,
+ )
+
+ val WIDTH =
+ AxisDefinition(
+ tag = "wdth",
+ minValue = 25f,
+ defaultValue = 100f,
+ maxValue = 151f,
+ animationStep = 1f,
+ )
+
+ val SLANT =
+ AxisDefinition(
+ tag = "slnt",
+ minValue = 0f,
+ defaultValue = 0f,
+ maxValue = -10f,
+ animationStep = 0.1f,
+ )
+
+ val ROUND =
+ AxisDefinition(
+ tag = "ROND",
+ minValue = 0f,
+ defaultValue = 0f,
+ maxValue = 100f,
+ animationStep = 1f,
+ )
+
+ val GRADE =
+ AxisDefinition(
+ tag = "GRAD",
+ minValue = 0f,
+ defaultValue = 0f,
+ maxValue = 100f,
+ animationStep = 1f,
+ )
+
+ val OPTICAL_SIZE =
+ AxisDefinition(
+ tag = "opsz",
+ minValue = 6f,
+ defaultValue = 18f,
+ maxValue = 144f,
+ animationStep = 1f,
+ )
+
+ // Not a GSF Axis, but present for FontInterpolator compatibility
+ val ITALIC =
+ AxisDefinition(
+ tag = "ITAL",
+ minValue = 0f,
+ defaultValue = 0f,
+ maxValue = 1f,
+ animationStep = 0.1f,
+ )
+
+ private val AXIS_MAP =
+ listOf(WEIGHT, WIDTH, SLANT, ROUND, GRADE, OPTICAL_SIZE, ITALIC)
+ .map { def -> def.tag.toLowerCase() to def }
+ .toMap()
+
+ fun getAxis(axis: String): AxisDefinition? = AXIS_MAP[axis.toLowerCase()]
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt
index 444389f..fdb07bd 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt
@@ -155,7 +155,7 @@
/** [ViewTransitionToken] to be used for storing transitioning view in [transitionRegistry] */
private val transitionToken =
if (Flags.decoupleViewControllerInAnimlib()) {
- ViewTransitionToken(transitioningView::class.java)
+ transitionRegistry?.register(transitioningView)
} else {
null
}
@@ -164,7 +164,7 @@
private val ghostedView: View
get() =
if (Flags.decoupleViewControllerInAnimlib()) {
- transitionRegistry?.getView(transitionToken!!)
+ transitionToken?.let { token -> transitionRegistry?.getView(token) }
} else {
_ghostedView
}!!
@@ -186,10 +186,6 @@
)
}
- if (Flags.decoupleViewControllerInAnimlib()) {
- transitionRegistry?.register(transitionToken!!, transitioningView)
- }
-
/** Find the first view with a background in [view] and its children. */
fun findBackground(view: View): Drawable? {
if (view.background != null) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/IViewTransitionRegistry.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/IViewTransitionRegistry.kt
index af3ca87..280d90d 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/IViewTransitionRegistry.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/IViewTransitionRegistry.kt
@@ -22,12 +22,12 @@
interface IViewTransitionRegistry {
/**
- * Registers the transitioning [view] mapped to a [token]
+ * Registers the transitioning [view] mapped to returned token
*
- * @param token The token corresponding to the transitioning view
* @param view The view undergoing transition
+ * @return token mapped to the transitioning view
*/
- fun register(token: ViewTransitionToken, view: View)
+ fun register(view: View): ViewTransitionToken
/**
* Unregisters the transitioned view from its corresponding [token]
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewTransitionRegistry.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewTransitionRegistry.kt
index 86c7f76..882ff3b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewTransitionRegistry.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewTransitionRegistry.kt
@@ -22,21 +22,21 @@
/**
* A registry to temporarily store the view being transitioned into a Dialog (using
- * [DialogTransitionAnimator]) or an Activity (using [ActivityTransitionAnimator])
+ * [DialogTransitionAnimator]) or an Activity (using [ActivityTransitionAnimator]).
*/
class ViewTransitionRegistry : IViewTransitionRegistry {
/**
* A map of a unique token to a WeakReference of the View being transitioned. WeakReference
* ensures that Views are garbage collected whenever they become eligible and avoid any
- * memory leaks
+ * memory leaks.
*/
- private val registry by lazy { mutableMapOf<ViewTransitionToken, WeakReference<View>>() }
+ private val registry by lazy { mutableMapOf<ViewTransitionToken, ViewTransitionInfo>() }
/**
* A [View.OnAttachStateChangeListener] to be attached to all views stored in the registry to
* ensure that views (and their corresponding entry) is automatically removed when the view is
- * detached from the Window
+ * detached from the Window.
*/
private val listener by lazy {
object : View.OnAttachStateChangeListener {
@@ -45,74 +45,121 @@
}
override fun onViewDetachedFromWindow(view: View) {
- getViewToken(view)?.let { token -> unregister(token) }
+ // if view is detached from window, remove it from registry irrespective of number
+ // of reference held by clients/user of this registry
+ getViewToken(view)?.let { token -> remove(token) }
}
}
}
/**
- * Creates an entry of a unique "token" mapped to "transitioning view" in the registry
+ * Creates an entry of a unique token mapped to transitioning [view] in the registry.
*
- * @param token unique token associated with the transitioning view
* @param view view undergoing transitions
+ * @return unique token mapped to the view being registered
*/
- override fun register(token: ViewTransitionToken, view: View) {
+ override fun register(view: View): ViewTransitionToken {
+ // if view being registered is already present in the registry and has a unique token
+ // assigned to it, reuse that token
+ getViewToken(view)?.let { token ->
+ registry[token]?.let { info -> info.viewRefCount += 1 }
+ return token
+ }
+
// token embedded as a view tag enables to use a single listener for all views
+ val token = ViewTransitionToken(view::class.java)
view.setTag(R.id.tag_view_transition_token, token)
view.addOnAttachStateChangeListener(listener)
- registry[token] = WeakReference(view)
+ registry[token] = ViewTransitionInfo(WeakReference(view))
onRegistryUpdate()
+
+ return token
}
/**
- * Removes the entry associated with the unique "token" in the registry
+ * Unregisters a view mapped to the unique [token] in the registry. This will either remove the
+ * entry entirely from registry (if the reference count of the associated view reached zero) or
+ * will decrement the reference count of the associated view in the registry.
*
* @param token unique token associated with the transitioning view
*/
override fun unregister(token: ViewTransitionToken) {
- registry.remove(token)?.let {
- it.get()?.let { view ->
+ registry[token]?.let { info ->
+ info.viewRefCount -= 1
+ if (info.viewRefCount == 0) {
+ remove(token)
+ }
+ }
+ }
+
+ /**
+ * Removes the entry associated with the unique [token] in the registry.
+ *
+ * @param token unique token associated with the transitioning view
+ */
+ private fun remove(token: ViewTransitionToken) {
+ registry.remove(token)?.let { removedInfo ->
+ removedInfo.viewRef.get()?.let { view ->
view.removeOnAttachStateChangeListener(listener)
view.setTag(R.id.tag_view_transition_token, null)
}
- it.clear()
+ removedInfo.viewRef.clear()
onRegistryUpdate()
}
}
/**
- * Access a view from registry using unique "token" associated with it
+ * Access a view from registry using unique [token] associated with it.
* WARNING - this returns a StrongReference to the View stored in the registry
*/
override fun getView(token: ViewTransitionToken): View? {
- return registry[token]?.get()
+ return registry[token]?.viewRef?.get()
}
/**
- * Return token mapped to the [view], if it is present in the registry
+ * Return token mapped to the [view], if it is present in the registry.
*
* @param view the transitioning view whose token we are requesting
* @return token associated with the [view] if present, else null
*/
override fun getViewToken(view: View): ViewTransitionToken? {
- return (view.getTag(R.id.tag_view_transition_token) as? ViewTransitionToken)?.let { token ->
- getView(token)?.let { token }
+ // extract token from the view if it is embedded inside it as a tag
+ val token = view.getTag(R.id.tag_view_transition_token) as? ViewTransitionToken
+
+ // this should never really happen, but if token embedded inside the view as tag, doesn't
+ // point to a valid view in the registry, remove that token (tag) from the view and registry
+ if (token != null && getView(token) == null) {
+ view.setTag(R.id.tag_view_transition_token, null)
+ remove(token)
+ return null
}
+
+ return token
}
- /** Event call to run on registry update (on both [register] and [unregister]) */
+ /** Event call to run on registry update (on both [register] and [unregister]). */
override fun onRegistryUpdate() {
emitCountForTrace()
}
/**
* Utility function to emit number of non-null views in the registry whenever the registry is
- * updated (via [register] or [unregister])
+ * updated (via [register] or [unregister]).
*/
private fun emitCountForTrace() {
Trace.setCounter("transition_registry_view_count", registry.count().toLong())
}
+ /** Information associated with each transitioning view in the registry. */
+ private data class ViewTransitionInfo(
+
+ /** View being transitioned */
+ val viewRef: WeakReference<View>,
+
+ /** Count of clients (users of this registry) referencing same transitioning view */
+ var viewRefCount: Int = 1
+ )
+
companion object {
val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ViewTransitionRegistry() }
}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDetector.kt
index 2a27a30..6eafb9f 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDetector.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDetector.kt
@@ -29,6 +29,14 @@
import org.jetbrains.uast.UClass
import org.jetbrains.uast.getContainingUFile
+/**
+ * Lint check to ensure that when including a Context or Context-dependent argument in
+ * shade-relevant packages, the argument has the @ShadeDisplayAware annotation.
+ *
+ * This is to ensure that Context-dependent components correctly handle Configuration changes when
+ * the shade is moved to a different display. @ShadeDisplayAware-annotated components will update
+ * accordingly to reflect the new display.
+ */
class ShadeDisplayAwareDetector : Detector(), SourceCodeScanner {
override fun getApplicableUastTypes() = listOf(UClass::class.java)
@@ -38,8 +46,8 @@
for (constructor in node.constructors) {
// Visit all injected constructors in shade-relevant packages
if (!constructor.hasAnnotation(INJECT_ANNOTATION)) continue
- if (!isInRelevantShadePackage(node)) continue
- if (IGNORED_PACKAGES.contains(node.qualifiedName)) continue
+ if (!isInRelevantShadePackage(node.getContainingUFile()?.packageName)) continue
+ if (IGNORED_CLASSES.contains(node.qualifiedName)) continue
for (parameter in constructor.parameterList.parameters) {
if (parameter.shouldReport()) {
@@ -84,24 +92,19 @@
CONFIG_INTERACTOR,
)
- private val CONFIG_CLASSES = setOf(CONFIG_STATE, CONFIG_CONTROLLER, CONFIG_INTERACTOR)
-
private val SHADE_WINDOW_PACKAGES =
listOf(
"com.android.systemui.biometrics",
"com.android.systemui.bouncer",
"com.android.systemui.keyboard.docking.ui.viewmodel",
+ "com.android.systemui.media.controls.ui.controller",
"com.android.systemui.qs",
"com.android.systemui.shade",
- "com.android.systemui.statusbar.notification",
+ "com.android.systemui.statusbar.lockscreen",
"com.android.systemui.unfold.domain.interactor",
)
- private val IGNORED_PACKAGES =
- setOf(
- "com.android.systemui.biometrics.UdfpsController",
- "com.android.systemui.qs.customize.TileAdapter",
- )
+ private val IGNORED_CLASSES = setOf("com.android.systemui.statusbar.phone.SystemUIDialog")
private fun PsiParameter.shouldReport(): Boolean {
val className = type.canonicalText
@@ -116,8 +119,7 @@
return true
}
- private fun isInRelevantShadePackage(node: UClass): Boolean {
- val packageName = node.getContainingUFile()?.packageName
+ fun isInRelevantShadePackage(packageName: String?): Boolean {
if (packageName.isNullOrBlank()) return false
return SHADE_WINDOW_PACKAGES.any { relevantPackage ->
packageName.startsWith(relevantPackage)
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDialogDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDialogDetector.kt
new file mode 100644
index 0000000..4cd5d89
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/ShadeDisplayAwareDialogDetector.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.systemui.lint
+
+import com.android.internal.systemui.lint.ShadeDisplayAwareDetector.Companion.isInRelevantShadePackage
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.android.tools.lint.detector.api.UastLintUtils.Companion.tryResolveUDeclaration
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.getContainingUClass
+import org.jetbrains.uast.getContainingUFile
+
+/**
+ * Lint check to ensure that when creating dialogs shade-relevant packages, the correct Context is
+ * provided.
+ *
+ * This is to ensure that the dialog is created with the correct context when the shade is moved to
+ * a different display. When the shade is moved, the configuration might change, and only
+ * `@ShadeDisplayAware`-annotated components will update accordingly to reflect the new display.
+ *
+ * Example:
+ * ```kotlin
+ * class ExampleClass
+ * @Inject
+ * constructor(private val contextInteractor: ShadeDialogContextInteractor) {
+ *
+ * fun showDialog() {
+ * val dialog = systemUIDialogFactory.create(delegate, contextInteractor.context)
+ * dialog.show()
+ * }
+ * }
+ * ```
+ */
+// TODO: b/396066687 - update linter after refactoring to use ShadeDialogFactory
+class ShadeDisplayAwareDialogDetector : Detector(), SourceCodeScanner {
+ override fun getApplicableMethodNames(): List<String> = listOf(CREATE_METHOD)
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ if (!isInRelevantShadePackage(node.getContainingUFile()?.packageName)) return
+ if (!context.evaluator.isMemberInClass(method, SYSUI_DIALOG_FACTORY)) return
+ val contextArg =
+ node.valueArguments.find {
+ it.getExpressionType()?.canonicalText == "android.content.Context"
+ }
+ if (contextArg == null) {
+ context.report(
+ issue = ISSUE,
+ scope = node,
+ location = context.getNameLocation(node),
+ message =
+ "SystemUIDialog.Factory#create requires a Context that accounts for the " +
+ "shade's display. Use create(shadeDialogContextInteractor.getContext()) " +
+ "or create(shadeDialogContextInteractor.context) to provide the correct Context.",
+ )
+ } else {
+ val isProvidedByContextInteractor =
+ contextArg.tryResolveUDeclaration()?.getContainingUClass()?.qualifiedName ==
+ SHADE_DIALOG_CONTEXT_INTERACTOR
+
+ if (!isProvidedByContextInteractor) {
+ context.report(
+ issue = ISSUE,
+ scope = contextArg,
+ location = context.getNameLocation(contextArg),
+ message =
+ "In shade-relevant packages, SystemUIDialog.Factory#create must be called " +
+ "with the Context directly from ShadeDialogContextInteractor " +
+ "(ShadeDialogContextInteractor.context or getContext()). " +
+ "Avoid intermediate variables or function calls. This direct usage " +
+ "is required to ensure proper shade display handling.",
+ )
+ }
+ }
+ }
+
+ companion object {
+ private const val CREATE_METHOD = "create"
+ private const val SYSUI_DIALOG_FACTORY =
+ "com.android.systemui.statusbar.phone.SystemUIDialog.Factory"
+ private const val SHADE_DIALOG_CONTEXT_INTERACTOR =
+ "com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor"
+
+ @JvmField
+ val ISSUE: Issue =
+ Issue.create(
+ id = "ShadeDisplayAwareDialogChecker",
+ briefDescription = "Checking for shade display aware context when creating dialogs",
+ explanation =
+ """
+ Dialogs created by the notification shade must use a special Context to appear
+ on the correct display, especially when the shade is not on the default display.
+ """
+ .trimIndent(),
+ category = Category.CORRECTNESS,
+ priority = 8,
+ severity = Severity.WARNING,
+ implementation =
+ Implementation(
+ ShadeDisplayAwareDialogDetector::class.java,
+ Scope.JAVA_FILE_SCOPE,
+ ),
+ )
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 6d18f93..adb3116 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -47,6 +47,7 @@
TestFunctionNameViolationDetector.ISSUE,
MissingApacheLicenseDetector.ISSUE,
ShadeDisplayAwareDetector.ISSUE,
+ ShadeDisplayAwareDialogDetector.ISSUE,
RegisterContentObserverSyncViaSettingsProxyDetector.SYNC_WARNING,
RegisterContentObserverViaContentResolverDetector.CONTENT_RESOLVER_ERROR,
)
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDetectorTest.kt
index 638d7cb7..f8f8b40 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDetectorTest.kt
@@ -410,34 +410,6 @@
.expectClean()
}
- @Test
- fun injectedConstructor_inExemptPackage_withRelevantParameter_withoutAnnotation() {
- lint()
- .files(
- TestFiles.java(
- """
- package com.android.systemui.qs.customize;
-
- import javax.inject.Inject;
- import com.android.systemui.qs.dagger.QSThemedContext;
- import android.content.Context;
-
- public class TileAdapter {
- @Inject
- public TileAdapter(@QSThemedContext Context context) {}
- }
- """
- .trimIndent()
- ),
- *androidStubs,
- *otherStubs,
- )
- .issues(ShadeDisplayAwareDetector.ISSUE)
- .testModes(TestMode.DEFAULT)
- .run()
- .expectClean()
- }
-
private fun errorMsgString(lineNumber: Int, className: String) =
"src/com/android/systemui/shade/example/ExampleClass.kt:$lineNumber: Error: UI elements of " +
"the shade window should use ShadeDisplayAware-annotated $className, as the shade " +
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDialogDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDialogDetectorTest.kt
new file mode 100644
index 0000000..86cdcdc
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/ShadeDisplayAwareDialogDetectorTest.kt
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.checks.infrastructure.TestMode
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+class ShadeDisplayAwareDialogDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector = ShadeDisplayAwareDialogDetector()
+
+ override fun getIssues(): List<Issue> = listOf(ShadeDisplayAwareDialogDetector.ISSUE)
+
+ private val injectStub: TestFile =
+ kotlin(
+ """
+ package javax.inject
+ @Retention(AnnotationRetention.RUNTIME) annotation class Inject
+ """
+ )
+ .indented()
+ private val shadeDisplayAwareStub: TestFile =
+ kotlin(
+ """
+ package com.android.systemui.shade
+ @Retention(AnnotationRetention.RUNTIME) annotation class ShadeDisplayAware
+ """
+ )
+ .indented()
+ private val mainStub: TestFile =
+ kotlin(
+ """
+ package com.android.systemui.dagger.qualifiers
+
+ @Retention(AnnotationRetention.RUNTIME) annotation class Main
+ """
+ )
+ .indented()
+ private val dialogContextStub: TestFile =
+ kotlin(
+ """
+ package com.android.systemui.shade.domain.interactor
+
+ import android.content.Context
+
+ interface ShadeDialogContextInteractor {
+ val context: Context
+ }
+ """
+ )
+ .indented()
+ private val delegateStub: TestFile =
+ java(
+ """
+ package com.android.systemui.statusbar.phone;
+
+ public interface Delegate { }
+ """
+ .trimIndent()
+ )
+ private val sysuiDialogStub: TestFile =
+ java(
+ """
+ package com.android.systemui.statusbar.phone;
+
+ import android.content.Context;
+ public class SystemUIDialog {
+ public SystemUIDialog(int id) { }
+
+ public static class Factory {
+ public SystemUIDialog create() {
+ return new SystemUIDialog();
+ }
+
+ public SystemUIDialog create(Context context) {
+ return new SystemUIDialog();
+ }
+
+ public SystemUIDialog create(Delegate delegate, Context context) {
+ return new SystemUIDialog();
+ }
+
+ public SystemUIDialog create(Delegate delegate, Context context,
+ boolean shouldAcsdDismissDialog) {
+ return new SystemUIDialog();
+ }
+
+ public SystemUIDialog create(Delegate delegate, Context context, int theme) {
+ return new SystemUIDialog();
+ }
+
+ public SystemUIDialog create(Delegate delegate) {
+ return new SystemUIDialog();
+ }
+ }
+ }
+ """
+ )
+ .indented()
+
+ private val otherStubs =
+ arrayOf(
+ injectStub,
+ shadeDisplayAwareStub,
+ mainStub,
+ delegateStub,
+ sysuiDialogStub,
+ dialogContextStub,
+ )
+
+ @Test
+ fun create_noArguments() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import android.content.Context
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+
+ class ExampleClass
+ @Inject
+ constructor(private val systemUIDialogFactory: SystemUIDialog.Factory) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create()
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expectContains(
+ "SystemUIDialog.Factory#create requires a Context that accounts for the " +
+ "shade's display. Use create(shadeDialogContextInteractor.getContext()) " +
+ "or create(shadeDialogContextInteractor.context) to provide the correct Context."
+ )
+ .expectContains("[ShadeDisplayAwareDialogChecker]")
+ .expectContains("0 errors, 1 warning")
+ }
+
+ @Test
+ fun create_UnannotatedContext() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import android.content.Context
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ class ExampleClass
+ @Inject
+ constructor(
+ private val context: Context,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(context)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expectContains(
+ "In shade-relevant packages, SystemUIDialog.Factory#create must be called " +
+ "with the Context directly from ShadeDialogContextInteractor " +
+ "(ShadeDialogContextInteractor.context or getContext()). " +
+ "Avoid intermediate variables or function calls. This direct usage " +
+ "is required to ensure proper shade display handling."
+ )
+ .expectContains("[ShadeDisplayAwareDialogChecker]")
+ .expectContains("0 errors, 1 warning")
+ }
+
+ @Test
+ fun create_annotatedContext() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import android.content.Context
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ import com.android.systemui.shade.ShadeDisplayAware
+ class ExampleClass
+ @Inject
+ constructor(
+ @ShadeDisplayAware private val context: Context,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(context)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expectContains(
+ "In shade-relevant packages, SystemUIDialog.Factory#create must be called " +
+ "with the Context directly from ShadeDialogContextInteractor " +
+ "(ShadeDialogContextInteractor.context or getContext()). " +
+ "Avoid intermediate variables or function calls. This direct usage " +
+ "is required to ensure proper shade display handling."
+ )
+ .expectContains("[ShadeDisplayAwareDialogChecker]")
+ .expectContains("0 errors, 1 warning")
+ }
+
+ @Test
+ fun create_LocalVariable() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
+
+ class ExampleClass
+ @Inject
+ constructor(
+ private val contextInteractor: ShadeDialogContextInteractor,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val context2 = contextInteractor.context
+ val dialog = systemUIDialogFactory.create(context2)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expectContains(
+ "In shade-relevant packages, SystemUIDialog.Factory#create must be called " +
+ "with the Context directly from ShadeDialogContextInteractor " +
+ "(ShadeDialogContextInteractor.context or getContext()). " +
+ "Avoid intermediate variables or function calls. This direct usage " +
+ "is required to ensure proper shade display handling."
+ )
+ .expectContains("[ShadeDisplayAwareDialogChecker]")
+ .expectContains("0 errors, 1 warning")
+ }
+
+ @Test
+ fun create_delegate_UnannotatedContext() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import android.content.Context
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ import com.android.systemui.statusbar.phone.Delegate
+ class ExampleClass
+ @Inject
+ constructor(
+ private val context: Context,
+ private val delegate: Delegate,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(delegate, context)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expectContains(
+ "In shade-relevant packages, SystemUIDialog.Factory#create must be called " +
+ "with the Context directly from ShadeDialogContextInteractor " +
+ "(ShadeDialogContextInteractor.context or getContext()). " +
+ "Avoid intermediate variables or function calls. This direct usage " +
+ "is required to ensure proper shade display handling."
+ )
+ .expectContains("[ShadeDisplayAwareDialogChecker]")
+ .expectContains("0 errors, 1 warning")
+ }
+
+ @Test
+ fun create_delegate_Context() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import android.content.Context
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ import com.android.systemui.statusbar.phone.Delegate
+ import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
+
+ class ExampleClass
+ @Inject
+ constructor(
+ private val delegate: Delegate,
+ private val contextInteractor: ShadeDialogContextInteractor,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(delegate, contextInteractor.context)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun create_Delegate_Context_Boolean() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ import com.android.systemui.statusbar.phone.Delegate
+
+ class ExampleClass
+ @Inject
+ constructor(
+ private val delegate: Delegate,
+ private val contextInteractor: ShadeDialogContextInteractor,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(delegate, contextInteractor.context, true)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun create_Delegate_UnannotatedContext_Int() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import android.content.Context
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ import com.android.systemui.statusbar.phone.Delegate
+ class ExampleClass
+ @Inject
+ constructor(
+ private val context: Context,
+ private val delegate: Delegate,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(delegate, context, 0)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expectContains(
+ "In shade-relevant packages, SystemUIDialog.Factory#create must be called " +
+ "with the Context directly from ShadeDialogContextInteractor " +
+ "(ShadeDialogContextInteractor.context or getContext()). " +
+ "Avoid intermediate variables or function calls. This direct usage " +
+ "is required to ensure proper shade display handling."
+ )
+ .expectContains("[ShadeDisplayAwareDialogChecker]")
+ .expectContains("0 errors, 1 warning")
+ }
+
+ @Test
+ fun create_Delegate_Context_Int() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+ import com.android.systemui.statusbar.phone.Delegate
+
+ class ExampleClass
+ @Inject
+ constructor(
+ private val delegate: Delegate,
+ private val contextInteractor: ShadeDialogContextInteractor,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(delegate, contextInteractor.context, 0)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun create_Delegate() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package com.android.systemui.shade.example
+ import javax.inject.Inject
+ import com.android.systemui.statusbar.phone.Delegate
+ import com.android.systemui.statusbar.phone.SystemUIDialog
+
+ class ExampleClass
+ @Inject
+ constructor(
+ private val delegate: Delegate,
+ private val systemUIDialogFactory: SystemUIDialog.Factory
+ ) {
+
+ fun showDialog() {
+ val dialog = systemUIDialogFactory.create(delegate)
+ dialog.show()
+ }
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs,
+ *otherStubs,
+ )
+ .issues(ShadeDisplayAwareDialogDetector.ISSUE)
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expectContains(
+ "SystemUIDialog.Factory#create requires a Context that accounts for the " +
+ "shade's display. Use create(shadeDialogContextInteractor.getContext()) " +
+ "or create(shadeDialogContextInteractor.context) to provide the correct Context."
+ )
+ .expectContains("[ShadeDisplayAwareDialogChecker]")
+ .expectContains("0 errors, 1 warning")
+ }
+}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index ae75e6c..8739919 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -31,15 +31,13 @@
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.contentColorFor
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.movableContentOf
import androidx.compose.runtime.mutableStateOf
@@ -63,9 +61,17 @@
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.scale
+import androidx.compose.ui.graphics.drawscope.translate
+import androidx.compose.ui.graphics.layer.GraphicsLayer
+import androidx.compose.ui.graphics.layer.drawLayer
+import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.layout.boundsInRoot
import androidx.compose.ui.layout.findRootCoordinates
+import androidx.compose.ui.layout.layout
import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.layout.onPlaced
+import androidx.compose.ui.node.DrawModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.Density
@@ -76,6 +82,8 @@
import androidx.lifecycle.setViewTreeViewModelStoreOwner
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import com.android.compose.modifiers.thenIf
+import com.android.compose.ui.graphics.FullScreenComposeViewInOverlay
import com.android.systemui.animation.Expandable
import com.android.systemui.animation.TransitionAnimator
import kotlin.math.max
@@ -123,6 +131,9 @@
borderStroke: BorderStroke? = null,
onClick: ((Expandable) -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
+ // TODO(b/285250939): Default this to true then remove once the Compose QS expandables have
+ // proven that the new implementation is robust.
+ useModifierBasedImplementation: Boolean = false,
content: @Composable (Expandable) -> Unit,
) {
Expandable(
@@ -130,6 +141,7 @@
modifier,
onClick,
interactionSource,
+ useModifierBasedImplementation,
content,
)
}
@@ -158,16 +170,26 @@
* @sample com.android.systemui.compose.gallery.ActivityLaunchScreen
* @sample com.android.systemui.compose.gallery.DialogLaunchScreen
*/
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Expandable(
controller: ExpandableController,
modifier: Modifier = Modifier,
onClick: ((Expandable) -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
+ // TODO(b/285250939): Default this to true then remove once the Compose QS expandables have
+ // proven that the new implementation is robust.
+ useModifierBasedImplementation: Boolean = false,
content: @Composable (Expandable) -> Unit,
) {
val controller = controller as ExpandableControllerImpl
+
+ if (useModifierBasedImplementation) {
+ Box(modifier.expandable(controller, onClick, interactionSource)) {
+ WrappedContent(controller.expandable, controller.contentColor, content)
+ }
+ return
+ }
+
val color = controller.color
val contentColor = controller.contentColor
val shape = controller.shape
@@ -175,21 +197,7 @@
val wrappedContent =
remember(content) {
movableContentOf { expandable: Expandable ->
- CompositionLocalProvider(LocalContentColor provides contentColor) {
- // We make sure that the content itself (wrapped by the background) is at least
- // 40.dp, which is the same as the M3 buttons. This applies even if onClick is
- // null, to make it easier to write expandables that are sometimes clickable and
- // sometimes not. There shouldn't be any Expandable smaller than 40dp because if
- // the expandable is not clickable directly, then something in its content
- // should be (and with a size >= 40dp).
- val minSize = 40.dp
- Box(
- Modifier.defaultMinSize(minWidth = minSize, minHeight = minSize),
- contentAlignment = Alignment.Center,
- ) {
- content(expandable)
- }
- }
+ WrappedContent(expandable, contentColor, content)
}
}
@@ -209,11 +217,7 @@
// Make sure we don't read animatorState directly here to avoid recomposition every time the
// state changes (i.e. every frame of the animation).
- val isAnimating by remember {
- derivedStateOf {
- controller.animatorState.value != null && controller.overlay.value != null
- }
- }
+ val isAnimating = controller.isAnimating
// If this expandable is expanded when it's being directly clicked on, let's ensure that it has
// the minimum interactive size followed by all M3 components (48.dp).
@@ -237,58 +241,36 @@
// animating.
AnimatedContentInOverlay(
color,
- controller.boundsInComposeViewRoot.value.size,
- controller.animatorState,
- controller.overlay.value
+ controller.boundsInComposeViewRoot.size,
+ controller.overlay
?: error("AnimatedContentInOverlay shouldn't be composed with null overlay."),
controller,
wrappedContent,
controller.composeViewRoot,
- { controller.currentComposeViewInOverlay.value = it },
+ { controller.currentComposeViewInOverlay = it },
controller.density,
)
}
- controller.isDialogShowing.value -> {
+ controller.isDialogShowing -> {
Box(
modifier
.updateExpandableSize()
.then(minInteractiveSizeModifier)
.drawWithContent { /* Don't draw anything when the dialog is shown. */ }
- .onGloballyPositioned {
- controller.boundsInComposeViewRoot.value = it.boundsInRoot()
- }
+ .onGloballyPositioned { controller.boundsInComposeViewRoot = it.boundsInRoot() }
) {
wrappedContent(controller.expandable)
}
}
else -> {
- val clickModifier =
- if (onClick != null) {
- if (interactionSource != null) {
- // If the caller provided an interaction source, then that means that they
- // will draw the click indication themselves.
- Modifier.clickable(interactionSource, indication = null) {
- onClick(controller.expandable)
- }
- } else {
- // If no interaction source is provided, we draw the default indication (a
- // ripple) and make sure it's clipped by the expandable shape.
- Modifier.clip(shape).clickable { onClick(controller.expandable) }
- }
- } else {
- Modifier
- }
-
Box(
modifier
.updateExpandableSize()
.then(minInteractiveSizeModifier)
- .then(clickModifier)
+ .then(clickModifier(controller, onClick, interactionSource))
.background(color, shape)
.border(controller)
- .onGloballyPositioned {
- controller.boundsInComposeViewRoot.value = it.boundsInRoot()
- }
+ .onGloballyPositioned { controller.boundsInComposeViewRoot = it.boundsInRoot() }
) {
wrappedContent(controller.expandable)
}
@@ -296,12 +278,182 @@
}
}
+@Composable
+private fun WrappedContent(
+ expandable: Expandable,
+ contentColor: Color,
+ content: @Composable (Expandable) -> Unit,
+) {
+ CompositionLocalProvider(LocalContentColor provides contentColor) {
+ // We make sure that the content itself (wrapped by the background) is at least 40.dp, which
+ // is the same as the M3 buttons. This applies even if onClick is null, to make it easier to
+ // write expandables that are sometimes clickable and sometimes not. There shouldn't be any
+ // Expandable smaller than 40dp because if the expandable is not clickable directly, then
+ // something in its content should be (and with a size >= 40dp).
+ val minSize = 40.dp
+ Box(
+ Modifier.defaultMinSize(minWidth = minSize, minHeight = minSize),
+ contentAlignment = Alignment.Center,
+ ) {
+ content(expandable)
+ }
+ }
+}
+
+@Composable
+@Stable
+private fun Modifier.expandable(
+ controller: ExpandableController,
+ onClick: ((Expandable) -> Unit)? = null,
+ interactionSource: MutableInteractionSource? = null,
+): Modifier {
+ val controller = controller as ExpandableControllerImpl
+
+ val isAnimating = controller.isAnimating
+ val drawInOverlayModifier =
+ if (isAnimating) {
+ val graphicsLayer = rememberGraphicsLayer()
+
+ FullScreenComposeViewInOverlay { view ->
+ Modifier.then(DrawExpandableInOverlayElement(view, controller, graphicsLayer))
+ }
+
+ Modifier.drawWithContent { graphicsLayer.record { this@drawWithContent.drawContent() } }
+ } else {
+ null
+ }
+
+ return this.thenIf(onClick != null) { Modifier.minimumInteractiveComponentSize() }
+ .thenIf(!isAnimating) {
+ Modifier.border(controller)
+ .then(clickModifier(controller, onClick, interactionSource))
+ .background(controller.color, controller.shape)
+ }
+ .thenIf(drawInOverlayModifier != null) { drawInOverlayModifier!! }
+ .onPlaced { controller.boundsInComposeViewRoot = it.boundsInRoot() }
+ .thenIf(!isAnimating && controller.isDialogShowing) {
+ Modifier.layout { measurable, constraints ->
+ measurable.measure(constraints).run {
+ layout(width, height) { /* Do not place/draw. */ }
+ }
+ }
+ }
+}
+
+private data class DrawExpandableInOverlayElement(
+ private val overlayComposeView: ComposeView,
+ private val controller: ExpandableControllerImpl,
+ private val contentGraphicsLayer: GraphicsLayer,
+) : ModifierNodeElement<DrawExpandableInOverlayNode>() {
+ override fun create(): DrawExpandableInOverlayNode {
+ return DrawExpandableInOverlayNode(overlayComposeView, controller, contentGraphicsLayer)
+ }
+
+ override fun update(node: DrawExpandableInOverlayNode) {
+ node.update(overlayComposeView, controller, contentGraphicsLayer)
+ }
+}
+
+private class DrawExpandableInOverlayNode(
+ composeView: ComposeView,
+ controller: ExpandableControllerImpl,
+ private var contentGraphicsLayer: GraphicsLayer,
+) : Modifier.Node(), DrawModifierNode {
+ private var controller = controller
+ set(value) {
+ resetCurrentNodeInOverlay()
+ field = value
+ setCurrentNodeInOverlay()
+ }
+
+ private var composeViewLocationOnScreen = composeView.locationOnScreen
+
+ fun update(
+ composeView: ComposeView,
+ controller: ExpandableControllerImpl,
+ contentGraphicsLayer: GraphicsLayer,
+ ) {
+ this.controller = controller
+ this.composeViewLocationOnScreen = composeView.locationOnScreen
+ this.contentGraphicsLayer = contentGraphicsLayer
+ }
+
+ override fun onAttach() {
+ setCurrentNodeInOverlay()
+ }
+
+ override fun onDetach() {
+ resetCurrentNodeInOverlay()
+ }
+
+ private fun setCurrentNodeInOverlay() {
+ controller.currentNodeInOverlay = this
+ }
+
+ private fun resetCurrentNodeInOverlay() {
+ if (controller.currentNodeInOverlay == this) {
+ controller.currentNodeInOverlay = null
+ }
+ }
+
+ override fun ContentDrawScope.draw() {
+ val state = controller.animatorState ?: return
+ val topOffset = state.top.toFloat() - composeViewLocationOnScreen[1]
+ val leftOffset = state.left.toFloat() - composeViewLocationOnScreen[0]
+
+ translate(top = topOffset, left = leftOffset) {
+ // Background.
+ this@draw.drawBackground(
+ state,
+ controller.color,
+ controller.borderStroke,
+ size = Size(state.width.toFloat(), state.height.toFloat()),
+ )
+
+ // Content, scaled & centered w.r.t. the animated state bounds.
+ val contentSize = controller.boundsInComposeViewRoot.size
+ val contentWidth = contentSize.width
+ val contentHeight = contentSize.height
+ val scale = min(state.width / contentWidth, state.height / contentHeight)
+ scale(scale, pivot = Offset(state.width / 2f, state.height / 2f)) {
+ translate(
+ left = (state.width - contentWidth) / 2f,
+ top = (state.height - contentHeight) / 2f,
+ ) {
+ drawLayer(contentGraphicsLayer)
+ }
+ }
+ }
+ }
+}
+
+private fun clickModifier(
+ controller: ExpandableControllerImpl,
+ onClick: ((Expandable) -> Unit)?,
+ interactionSource: MutableInteractionSource?,
+): Modifier {
+ if (onClick == null) {
+ return Modifier
+ }
+
+ if (interactionSource != null) {
+ // If the caller provided an interaction source, then that means that they will draw the
+ // click indication themselves.
+ return Modifier.clickable(interactionSource, indication = null) {
+ onClick(controller.expandable)
+ }
+ }
+
+ // If no interaction source is provided, we draw the default indication (a ripple) and make sure
+ // it's clipped by the expandable shape.
+ return Modifier.clip(controller.shape).clickable { onClick(controller.expandable) }
+}
+
/** Draw [content] in [overlay] while respecting its screen position given by [animatorState]. */
@Composable
private fun AnimatedContentInOverlay(
color: Color,
sizeInOriginalLayout: Size,
- animatorState: State<TransitionAnimator.State?>,
overlay: ViewGroupOverlay,
controller: ExpandableControllerImpl,
content: @Composable (Expandable) -> Unit,
@@ -324,7 +476,7 @@
// so that its content is laid out exactly the same way.
.requiredSize(with(density) { sizeInOriginalLayout.toDpSize() })
.drawWithContent {
- val animatorState = animatorState.value ?: return@drawWithContent
+ val animatorState = controller.animatorState ?: return@drawWithContent
// Scale the content with the background while keeping its aspect ratio.
val widthRatio =
@@ -348,7 +500,8 @@
setContent {
Box(
Modifier.fillMaxSize().drawWithContent {
- val animatorState = animatorState.value ?: return@drawWithContent
+ val animatorState =
+ controller.animatorState ?: return@drawWithContent
if (!animatorState.visible) {
return@drawWithContent
}
@@ -385,7 +538,7 @@
overlay.add(composeViewInOverlay)
val startState =
- animatorState.value
+ controller.animatorState
?: throw IllegalStateException(
"AnimatedContentInOverlay shouldn't be composed with null animatorState."
)
@@ -444,6 +597,7 @@
animatorState: TransitionAnimator.State,
color: Color,
border: BorderStroke?,
+ size: Size = this.size,
) {
val topRadius = animatorState.topCornerRadius
val bottomRadius = animatorState.bottomCornerRadius
@@ -452,7 +606,7 @@
val cornerRadius = CornerRadius(topRadius)
// Draw the background.
- drawRoundRect(color, cornerRadius = cornerRadius)
+ drawRoundRect(color, cornerRadius = cornerRadius, size = size)
// Draw the border.
if (border != null) {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
index c5d2802..a03c896 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
@@ -25,16 +25,21 @@
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.node.DrawModifierNode
+import androidx.compose.ui.node.invalidateDraw
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalView
@@ -49,10 +54,14 @@
import kotlin.math.roundToInt
/** A controller that can control animated launches from an [Expandable]. */
+@Stable
interface ExpandableController {
/** The [Expandable] controlled by this controller. */
val expandable: Expandable
+ /** Whether this controller is currently animating a launch. */
+ val isAnimating: Boolean
+
/** Called when the [Expandable] stop being included in the composition. */
fun onDispose()
}
@@ -73,24 +82,9 @@
val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current
- // The current animation state, if we are currently animating a dialog or activity.
- val animatorState = remember { mutableStateOf<TransitionAnimator.State?>(null) }
-
- // Whether a dialog controlled by this ExpandableController is currently showing.
- val isDialogShowing = remember { mutableStateOf(false) }
-
- // The overlay in which we should animate the launch.
- val overlay = remember { mutableStateOf<ViewGroupOverlay?>(null) }
-
- // The current [ComposeView] being animated in the [overlay], if any.
- val currentComposeViewInOverlay = remember { mutableStateOf<View?>(null) }
-
- // The bounds in [composeViewRoot] of the expandable controlled by this controller.
- val boundsInComposeViewRoot = remember { mutableStateOf(Rect.Zero) }
-
// Whether this composable is still composed. We only do the dialog exit animation if this is
// true.
- val isComposed = remember { mutableStateOf(true) }
+ var isComposed by remember { mutableStateOf(true) }
val controller =
remember(
@@ -109,19 +103,14 @@
borderStroke,
composeViewRoot,
density,
- animatorState,
- isDialogShowing,
- overlay,
- currentComposeViewInOverlay,
- boundsInComposeViewRoot,
layoutDirection,
- isComposed,
+ { isComposed },
)
}
DisposableEffect(Unit) {
onDispose {
- isComposed.value = false
+ isComposed = false
if (TransitionAnimator.returnAnimationsEnabled()) {
controller.onDispose()
}
@@ -138,17 +127,35 @@
internal val borderStroke: BorderStroke?,
internal val composeViewRoot: View,
internal val density: Density,
- internal val animatorState: MutableState<TransitionAnimator.State?>,
- internal val isDialogShowing: MutableState<Boolean>,
- internal val overlay: MutableState<ViewGroupOverlay?>,
- internal val currentComposeViewInOverlay: MutableState<View?>,
- internal val boundsInComposeViewRoot: MutableState<Rect>,
private val layoutDirection: LayoutDirection,
- private val isComposed: State<Boolean>,
+ private val isComposed: () -> Boolean,
) : ExpandableController {
+ /** The current animation state, if we are currently animating a dialog or activity. */
+ var animatorState by mutableStateOf<TransitionAnimator.State?>(null)
+ private set
+
+ /** Whether a dialog controlled by this ExpandableController is currently showing. */
+ var isDialogShowing by mutableStateOf(false)
+ private set
+
+ /** The overlay in which we should animate the launch. */
+ var overlay by mutableStateOf<ViewGroupOverlay?>(null)
+ private set
+
+ /** The current [ComposeView] being animated in the [overlay], if any. */
+ var currentComposeViewInOverlay by mutableStateOf<View?>(null)
+
+ /** The bounds in [composeViewRoot] of the expandable controlled by this controller. */
+ var boundsInComposeViewRoot by mutableStateOf(Rect.Zero)
+
/** The [ActivityTransitionAnimator.Controller] to be cleaned up [onDispose]. */
private var activityControllerForDisposal: ActivityTransitionAnimator.Controller? = null
+ /**
+ * The current [DrawModifierNode] in the overlay, drawing the expandable during a transition.
+ */
+ internal var currentNodeInOverlay: DrawModifierNode? = null
+
override val expandable: Expandable =
object : Expandable {
override fun activityTransitionController(
@@ -158,7 +165,7 @@
returnCujType: Int?,
isEphemeral: Boolean,
): ActivityTransitionAnimator.Controller? {
- if (!isComposed.value) {
+ if (!isComposed()) {
return null
}
@@ -174,7 +181,7 @@
override fun dialogTransitionController(
cuj: DialogCuj?
): DialogTransitionAnimator.Controller? {
- if (!isComposed.value) {
+ if (!isComposed()) {
return null
}
@@ -182,6 +189,8 @@
}
}
+ override val isAnimating: Boolean by derivedStateOf { animatorState != null && overlay != null }
+
override fun onDispose() {
activityControllerForDisposal?.onDispose()
activityControllerForDisposal = null
@@ -204,7 +213,11 @@
override val isLaunching: Boolean = true
override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
- animatorState.value = null
+ animatorState = null
+
+ // Force invalidate the drawing done in the overlay whenever the animation state
+ // changes.
+ currentNodeInOverlay?.invalidateDraw()
}
override fun onTransitionAnimationProgress(
@@ -214,7 +227,7 @@
) {
// We copy state given that it's always the same object that is mutated by
// ActivityTransitionAnimator.
- animatorState.value =
+ animatorState =
TransitionAnimator.State(
state.top,
state.bottom,
@@ -227,13 +240,15 @@
// Force measure and layout the ComposeView in the overlay whenever the animation
// state changes.
- currentComposeViewInOverlay.value?.let {
- measureAndLayoutComposeViewInOverlay(it, state)
- }
+ currentComposeViewInOverlay?.let { measureAndLayoutComposeViewInOverlay(it, state) }
+
+ // Force invalidate the drawing done in the overlay whenever the animation state
+ // changes.
+ currentNodeInOverlay?.invalidateDraw()
}
override fun createAnimatorState(): TransitionAnimator.State {
- val boundsInRoot = boundsInComposeViewRoot.value
+ val boundsInRoot = boundsInComposeViewRoot
val outline =
shape.createOutline(
Size(boundsInRoot.width, boundsInRoot.height),
@@ -285,7 +300,7 @@
private fun rootLocationOnScreen(): Offset {
composeViewRoot.getLocationOnScreen(rootLocationOnScreen)
- val boundsInRoot = boundsInComposeViewRoot.value
+ val boundsInRoot = boundsInComposeViewRoot
val x = rootLocationOnScreen[0] + boundsInRoot.left
val y = rootLocationOnScreen[1] + boundsInRoot.top
return Offset(x, y)
@@ -319,14 +334,14 @@
override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
delegate.onTransitionAnimationStart(isExpandingFullyAbove)
- overlay.value = transitionContainer.overlay as ViewGroupOverlay
+ overlay = transitionContainer.overlay as ViewGroupOverlay
cujType?.let { InteractionJankMonitor.getInstance().begin(composeViewRoot, it) }
}
override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
cujType?.let { InteractionJankMonitor.getInstance().end(it) }
delegate.onTransitionAnimationEnd(isExpandingFullyAbove)
- overlay.value = null
+ overlay = null
}
}
}
@@ -339,14 +354,14 @@
override fun startDrawingInOverlayOf(viewGroup: ViewGroup) {
val newOverlay = viewGroup.overlay as ViewGroupOverlay
- if (newOverlay != overlay.value) {
- overlay.value = newOverlay
+ if (newOverlay != overlay) {
+ overlay = newOverlay
}
}
override fun stopDrawingInOverlay() {
- if (overlay.value != null) {
- overlay.value = null
+ if (overlay != null) {
+ overlay = null
}
}
@@ -357,7 +372,7 @@
delegate.onTransitionAnimationEnd(isExpandingFullyAbove)
// Make sure we don't draw this expandable when the dialog is showing.
- isDialogShowing.value = true
+ isDialogShowing = true
}
}
}
@@ -367,16 +382,17 @@
return object : TransitionAnimator.Controller by delegate {
override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
delegate.onTransitionAnimationEnd(isExpandingFullyAbove)
- isDialogShowing.value = false
+ isDialogShowing = false
}
}
}
- override fun shouldAnimateExit(): Boolean =
- isComposed.value && composeViewRoot.isAttachedToWindow && composeViewRoot.isShown
+ override fun shouldAnimateExit(): Boolean {
+ return isComposed() && composeViewRoot.isAttachedToWindow && composeViewRoot.isShown
+ }
override fun onExitAnimationCancelled() {
- isDialogShowing.value = false
+ isDialogShowing = false
}
override fun jankConfigurationBuilder(): InteractionJankMonitor.Configuration.Builder? {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/ui/graphics/DrawInOverlay.kt b/packages/SystemUI/compose/core/src/com/android/compose/ui/graphics/DrawInOverlay.kt
index f5c3a83..089da4b 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/ui/graphics/DrawInOverlay.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/ui/graphics/DrawInOverlay.kt
@@ -42,13 +42,19 @@
@Composable
fun Modifier.drawInOverlay(): Modifier {
val containerState = remember { ContainerState() }
+ FullScreenComposeViewInOverlay { Modifier.container(containerState) }
+ return this.drawInContainer(containerState, enabled = { true })
+}
+
+@Composable
+internal fun FullScreenComposeViewInOverlay(modifier: (ComposeView) -> Modifier = { Modifier }) {
val context = LocalContext.current
val localView = LocalView.current
val compositionContext = rememberCompositionContext()
val displayMetrics = context.resources.displayMetrics
val displaySize = IntSize(displayMetrics.widthPixels, displayMetrics.heightPixels)
- DisposableEffect(containerState, context, localView, compositionContext, displaySize) {
+ DisposableEffect(context, localView, compositionContext, displaySize) {
val overlay = localView.rootView.overlay as ViewGroupOverlay
val view =
ComposeView(context).apply {
@@ -59,7 +65,8 @@
setViewTreeViewModelStoreOwner(localView.findViewTreeViewModelStoreOwner())
setViewTreeSavedStateRegistryOwner(localView.findViewTreeSavedStateRegistryOwner())
- setContent { Box(Modifier.fillMaxSize().container(containerState)) }
+ val view = this
+ setContent { Box(modifier(view).fillMaxSize()) }
}
overlay.add(view)
@@ -74,6 +81,4 @@
onDispose { overlay.remove(view) }
}
-
- return this.drawInContainer(containerState, enabled = { true })
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index 2f38dc2..fad8ae7 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -24,7 +24,6 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.testTag
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.UserAction
@@ -103,8 +102,6 @@
viewModel,
dialogFactory,
Modifier.element(Bouncer.Elements.Content)
- // TODO(b/393516240): Use the same sysuiResTag() as views instead.
- .testTag(Bouncer.Elements.Content.testTag)
.overscroll(verticalOverscrollEffect)
.sysuiResTag(Bouncer.TestTags.Root)
.fillMaxSize(),
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
index aa07370..5e61af6 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
@@ -19,7 +19,6 @@
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.testTag
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
@@ -56,11 +55,7 @@
@Composable
override fun ContentScope.Content(modifier: Modifier) {
- LockscreenScene(
- lockscreenContent = lockscreenContent,
- // TODO(b/393516240): Use the same sysuiResTag() as views instead.
- modifier = modifier.testTag(key.rootElementKey.testTag),
- )
+ LockscreenScene(lockscreenContent = lockscreenContent, modifier = modifier)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
index 297995b..7cd6c6b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
@@ -124,7 +124,6 @@
SmallClock(
burnInParams = burnIn.parameters,
onTopChanged = burnIn.onSmallClockTopChanged,
- modifier = Modifier.fillMaxWidth(),
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index f0d3f3e..9c85c96 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -80,6 +80,7 @@
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.compose.modifiers.sysuiResTag
+import com.android.systemui.qs.flags.QSComposeFragment
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsForegroundServicesButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsSecurityButtonViewModel
@@ -218,11 +219,24 @@
Spacer(Modifier.weight(1f))
}
- security?.let { SecurityButton(it, Modifier.weight(1f)) }
- foregroundServices?.let { ForegroundServicesButton(it) }
- userSwitcher?.let { IconButton(it, Modifier.sysuiResTag("multi_user_switch")) }
- IconButton(viewModel.settings, Modifier.sysuiResTag("settings_button_container"))
- power?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
+ val useModifierBasedExpandable = remember { QSComposeFragment.isEnabled }
+ security?.let { SecurityButton(it, useModifierBasedExpandable, Modifier.weight(1f)) }
+ foregroundServices?.let { ForegroundServicesButton(it, useModifierBasedExpandable) }
+ userSwitcher?.let {
+ IconButton(
+ it,
+ useModifierBasedExpandable,
+ Modifier.sysuiResTag("multi_user_switch"),
+ )
+ }
+ IconButton(
+ viewModel.settings,
+ useModifierBasedExpandable,
+ Modifier.sysuiResTag("settings_button_container"),
+ )
+ power?.let {
+ IconButton(it, useModifierBasedExpandable, Modifier.sysuiResTag("pm_lite"))
+ }
}
}
}
@@ -231,6 +245,7 @@
@Composable
private fun SecurityButton(
model: FooterActionsSecurityButtonViewModel,
+ useModifierBasedExpandable: Boolean,
modifier: Modifier = Modifier,
) {
val onClick: ((Expandable) -> Unit)? =
@@ -239,13 +254,21 @@
{ expandable -> onClick(context, expandable) }
}
- TextButton(model.icon, model.text, showNewDot = false, onClick = onClick, modifier)
+ TextButton(
+ model.icon,
+ model.text,
+ showNewDot = false,
+ onClick = onClick,
+ useModifierBasedExpandable,
+ modifier,
+ )
}
/** The foreground services button. */
@Composable
private fun RowScope.ForegroundServicesButton(
- model: FooterActionsForegroundServicesButtonViewModel
+ model: FooterActionsForegroundServicesButtonViewModel,
+ useModifierBasedExpandable: Boolean,
) {
if (model.displayText) {
TextButton(
@@ -253,6 +276,7 @@
model.text,
showNewDot = model.hasNewChanges,
onClick = model.onClick,
+ useModifierBasedExpandable,
Modifier.weight(1f),
)
} else {
@@ -261,13 +285,18 @@
contentDescription = model.text,
showNewDot = model.hasNewChanges,
onClick = model.onClick,
+ useModifierBasedExpandable,
)
}
}
/** A button with an icon. */
@Composable
-fun IconButton(model: FooterActionsButtonViewModel, modifier: Modifier = Modifier) {
+fun IconButton(
+ model: FooterActionsButtonViewModel,
+ useModifierBasedExpandable: Boolean,
+ modifier: Modifier = Modifier,
+) {
Expandable(
color = colorAttr(model.backgroundColor),
shape = CircleShape,
@@ -277,6 +306,7 @@
color = MaterialTheme.colorScheme.secondary,
CornerSize(percent = 50),
),
+ useModifierBasedImplementation = useModifierBasedExpandable,
) {
val tint = model.iconTint?.let { Color(it) } ?: Color.Unspecified
Icon(model.icon, tint = tint, modifier = Modifier.size(20.dp))
@@ -290,6 +320,7 @@
contentDescription: String,
showNewDot: Boolean,
onClick: (Expandable) -> Unit,
+ useModifierBasedExpandable: Boolean,
modifier: Modifier = Modifier,
) {
// By default Expandable will show a ripple above its content when clicked, and clip the content
@@ -309,6 +340,7 @@
color = MaterialTheme.colorScheme.secondary,
CornerSize(percent = 50),
),
+ useModifierBasedImplementation = useModifierBasedExpandable,
) {
Box(Modifier.size(40.dp)) {
Box(
@@ -355,6 +387,7 @@
text: String,
showNewDot: Boolean,
onClick: ((Expandable) -> Unit)?,
+ useModifierBasedExpandable: Boolean,
modifier: Modifier = Modifier,
) {
Expandable(
@@ -367,12 +400,17 @@
.padding(horizontal = 4.dp)
.borderOnFocus(color = MaterialTheme.colorScheme.secondary, CornerSize(50)),
onClick = onClick,
+ useModifierBasedImplementation = useModifierBasedExpandable,
) {
Row(
Modifier.padding(horizontal = dimensionResource(R.dimen.qs_footer_padding)),
verticalAlignment = Alignment.CenterVertically,
) {
- Icon(icon, Modifier.padding(end = 12.dp).size(20.dp))
+ Icon(
+ icon,
+ Modifier.padding(end = 12.dp).size(20.dp),
+ colorAttr(R.attr.onShadeInactiveVariant),
+ )
Text(
text,
@@ -381,6 +419,7 @@
// TODO(b/242040009): Remove this letter spacing. We should only use the M3 text
// styles without modifying them.
letterSpacing = 0.01.em,
+ color = colorAttr(R.attr.onShadeInactiveVariant),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
@@ -394,6 +433,7 @@
painterResource(com.android.internal.R.drawable.ic_chevron_end),
contentDescription = null,
Modifier.padding(start = 8.dp).size(20.dp),
+ colorAttr(R.attr.onShadeInactiveVariant),
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
index da0b8ac..0f1cb40 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
@@ -50,6 +50,8 @@
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.rememberViewModel
+import com.android.systemui.media.controls.ui.composable.MediaCarousel
+import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.COLLAPSED
import com.android.systemui.notifications.ui.composable.SnoozeableHeadsUpNotificationSpace
import com.android.systemui.qs.composefragment.ui.GridAnchor
import com.android.systemui.qs.flags.QsDetailedView
@@ -104,7 +106,10 @@
}
val quickSettingsContainerViewModel =
rememberViewModel("QuickSettingsShadeOverlayContainer") {
- quickSettingsContainerViewModelFactory.create(supportsBrightnessMirroring = true)
+ quickSettingsContainerViewModelFactory.create(
+ supportsBrightnessMirroring = true,
+ expansion = COLLAPSED,
+ )
}
val hunPlaceholderViewModel =
rememberViewModel("QuickSettingsShadeOverlayPlaceholder") {
@@ -232,12 +237,20 @@
Toolbar(
modifier =
Modifier.fillMaxWidth().requiredHeight(QuickSettingsShade.Dimensions.ToolbarHeight),
- toolbarViewModelFactory = viewModel.toolbarViewModelFactory,
+ viewModel = viewModel.toolbarViewModel,
)
Column(
verticalArrangement = Arrangement.spacedBy(QuickSettingsShade.Dimensions.Padding),
modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
+ MediaCarousel(
+ isVisible = viewModel.showMedia,
+ mediaHost = viewModel.mediaHost,
+ carouselController = viewModel.mediaCarouselController,
+ usingCollapsedLandscapeMedia = true,
+ modifier = Modifier.padding(horizontal = QuickSettingsShade.Dimensions.Padding),
+ )
+
BrightnessSliderContainer(
viewModel = viewModel.brightnessSliderViewModel,
containerColor = OverlayShade.Colors.PanelBackground,
@@ -245,6 +258,7 @@
Modifier.fillMaxWidth()
.height(QuickSettingsShade.Dimensions.BrightnessSliderHeight),
)
+
Box {
GridAnchor()
TileGrid(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
index 60eaa28..b9aca25 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt
@@ -21,7 +21,6 @@
import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
-import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.observableTransitionState
import com.android.systemui.scene.shared.model.SceneDataSource
import kotlinx.coroutines.CoroutineScope
@@ -106,6 +105,6 @@
}
override fun freezeAndAnimateToCurrentState() {
- (state.transitionState as? TransitionState.Transition)?.freezeAndAnimateToCurrentState()
+ state.currentTransition?.freezeAndAnimateToCurrentState()
}
}
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 cdb1e2e..7e7b629 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
@@ -54,6 +54,7 @@
import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.res.R
+import androidx.compose.ui.unit.Dp
/** Renders a lightweight shade UI container, as an overlay. */
@Composable
@@ -202,10 +203,15 @@
}
object Dimensions {
- val PanelCornerRadius = 46.dp
+ val PanelCornerRadius: Dp
+ @Composable
+ @ReadOnlyComposable get() =
+ dimensionResource(R.dimen.overlay_shade_panel_shape_radius)
}
object Shapes {
- val RoundedCornerPanel = RoundedCornerShape(Dimensions.PanelCornerRadius)
+ val RoundedCornerPanel: RoundedCornerShape
+ @Composable
+ @ReadOnlyComposable get() = RoundedCornerShape(Dimensions.PanelCornerRadius)
}
}
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 02de78b..db9035b 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
@@ -25,8 +25,8 @@
import androidx.compose.foundation.interaction.collectIsHoveredAsState
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.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
@@ -43,10 +43,8 @@
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
@@ -67,6 +65,7 @@
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.theme.colorAttr
import com.android.settingslib.Utils
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
@@ -77,21 +76,18 @@
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.ui.composable.ShadeHeader.Colors.chipBackground
-import com.android.systemui.shade.ui.composable.ShadeHeader.Colors.chipHighlighted
import com.android.systemui.shade.ui.composable.ShadeHeader.Colors.onScrimDim
+import com.android.systemui.shade.ui.composable.ShadeHeader.Dimensions.ChipPaddingHorizontal
+import com.android.systemui.shade.ui.composable.ShadeHeader.Dimensions.ChipPaddingVertical
import com.android.systemui.shade.ui.composable.ShadeHeader.Dimensions.CollapsedHeight
import com.android.systemui.shade.ui.composable.ShadeHeader.Values.ClockScale
import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel.HeaderChipHighlight
-import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder
-import com.android.systemui.statusbar.phone.NotificationIconContainer
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel
import com.android.systemui.statusbar.policy.Clock
-import kotlinx.coroutines.launch
object ShadeHeader {
object Elements {
@@ -110,6 +106,8 @@
object Dimensions {
val CollapsedHeight = 48.dp
val ExpandedHeight = 120.dp
+ val ChipPaddingHorizontal = 6.dp
+ val ChipPaddingVertical = 4.dp
}
object Colors {
@@ -118,12 +116,6 @@
val ColorScheme.onScrimDim: Color
get() = Color.DarkGray
-
- val ColorScheme.chipBackground: Color
- get() = Color.DarkGray
-
- val ColorScheme.chipHighlighted: Color
- get() = Color.LightGray
}
object TestTags {
@@ -149,9 +141,6 @@
}
}
- val longerDateText by viewModel.longerDateText.collectAsStateWithLifecycle()
- val shorterDateText by viewModel.shorterDateText.collectAsStateWithLifecycle()
-
val isShadeLayoutWide = viewModel.isShadeLayoutWide
val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsStateWithLifecycle()
@@ -167,9 +156,9 @@
) {
Clock(scale = 1f, onClick = viewModel::onClockClicked)
VariableDayDate(
- longerDateText = longerDateText,
- shorterDateText = shorterDateText,
- chipHighlight = viewModel.notificationsChipHighlight,
+ longerDateText = viewModel.longerDateText,
+ shorterDateText = viewModel.shorterDateText,
+ textColor = colorAttr(android.R.attr.textColorPrimary),
modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentStart),
)
}
@@ -229,8 +218,6 @@
derivedStateOf { shouldUseExpandedFormat(layoutState.transitionState) }
}
- val longerDateText by viewModel.longerDateText.collectAsStateWithLifecycle()
- val shorterDateText by viewModel.shorterDateText.collectAsStateWithLifecycle()
val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsStateWithLifecycle()
Box(modifier = modifier.sysuiResTag(ShadeHeader.TestTags.Root)) {
@@ -269,9 +256,9 @@
modifier = Modifier.element(ShadeHeader.Elements.ExpandedContent),
) {
VariableDayDate(
- longerDateText = longerDateText,
- shorterDateText = shorterDateText,
- chipHighlight = viewModel.notificationsChipHighlight,
+ longerDateText = viewModel.longerDateText,
+ shorterDateText = viewModel.shorterDateText,
+ textColor = colorAttr(android.R.attr.textColorPrimary),
modifier = Modifier.widthIn(max = 90.dp),
)
Spacer(modifier = Modifier.weight(1f))
@@ -316,6 +303,7 @@
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = horizontalPadding),
) {
+ val chipHighlight = viewModel.notificationsChipHighlight
if (isShadeLayoutWide) {
Clock(
scale = 1f,
@@ -324,28 +312,15 @@
)
Spacer(modifier = Modifier.width(5.dp))
}
- val chipHighlight = viewModel.notificationsChipHighlight
- NotificationIconChip(
- chipHighlight = chipHighlight,
+ NotificationsChip(
onClick = viewModel::onNotificationIconChipClicked,
+ backgroundColor = chipHighlight.backgroundColor(MaterialTheme.colorScheme),
) {
- if (isShadeLayoutWide) {
- NotificationIcons(
- chipHighlight = chipHighlight,
- notificationIconContainerStatusBarViewBinder =
- viewModel.notificationIconContainerStatusBarViewBinder,
- modifier = Modifier.width(IntrinsicSize.Min).height(20.dp),
- )
- } else {
- val longerDateText by viewModel.longerDateText.collectAsStateWithLifecycle()
- val shorterDateText by
- viewModel.shorterDateText.collectAsStateWithLifecycle()
- VariableDayDate(
- longerDateText = longerDateText,
- shorterDateText = shorterDateText,
- chipHighlight = viewModel.notificationsChipHighlight,
- )
- }
+ VariableDayDate(
+ longerDateText = viewModel.longerDateText,
+ shorterDateText = viewModel.shorterDateText,
+ textColor = chipHighlight.foregroundColor(MaterialTheme.colorScheme),
+ )
}
}
},
@@ -357,14 +332,13 @@
) {
val chipHighlight = viewModel.quickSettingsChipHighlight
SystemIconChip(
- chipHighlight = chipHighlight,
+ backgroundColor = chipHighlight.backgroundColor(MaterialTheme.colorScheme),
onClick = viewModel::onSystemIconChipClicked,
) {
StatusIcons(
viewModel = viewModel,
useExpandedFormat = false,
modifier = Modifier.padding(end = 6.dp).weight(1f, fill = false),
- chipHighlight = chipHighlight,
)
BatteryIcon(
createBatteryMeterViewController =
@@ -534,6 +508,7 @@
batteryIcon.setPercentShowMode(
if (useExpandedFormat) BatteryMeterView.MODE_ESTIMATE else BatteryMeterView.MODE_ON
)
+ // TODO(b/397223606): Get the actual spec for this.
if (chipHighlight is HeaderChipHighlight.Strong) {
batteryIcon.updateColors(primaryColor, inverseColor, inverseColor)
} else if (chipHighlight is HeaderChipHighlight.Weak) {
@@ -546,11 +521,8 @@
@Composable
private fun ShadeCarrierGroup(viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier) {
- Row(modifier = modifier) {
- val subIds by viewModel.mobileSubIds.collectAsStateWithLifecycle()
-
- for (subId in subIds) {
- Spacer(modifier = Modifier.width(5.dp))
+ Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(5.dp)) {
+ for (subId in viewModel.mobileSubIds) {
AndroidView(
factory = { context ->
ModernShadeCarrierGroupMobileView.constructAndBind(
@@ -571,36 +543,10 @@
}
@Composable
-private fun NotificationIcons(
- chipHighlight: HeaderChipHighlight,
- notificationIconContainerStatusBarViewBinder: NotificationIconContainerStatusBarViewBinder,
- modifier: Modifier = Modifier,
-) {
- val scope = rememberCoroutineScope()
-
- AndroidView(
- factory = { context ->
- NotificationIconContainer(context, null).also { view ->
- view.setOverrideIconColor(true)
- scope.launch {
- notificationIconContainerStatusBarViewBinder.bindWhileAttached(
- view = view,
- displayId = context.displayId,
- )
- }
- }
- },
- update = { it.setUseInverseOverrideIconColor(chipHighlight is HeaderChipHighlight.Strong) },
- modifier = modifier,
- )
-}
-
-@Composable
private fun ContentScope.StatusIcons(
viewModel: ShadeHeaderViewModel,
useExpandedFormat: Boolean,
modifier: Modifier = Modifier,
- chipHighlight: HeaderChipHighlight = HeaderChipHighlight.None,
) {
val localContext = LocalContext.current
val themedContext =
@@ -628,6 +574,8 @@
viewModel.createTintedIconManager(iconContainer, StatusBarLocation.QS)
}
+ val chipHighlight = viewModel.quickSettingsChipHighlight
+
AndroidView(
factory = { context ->
iconManager.setTint(primaryColor, inverseColor)
@@ -664,6 +612,7 @@
iconContainer.removeIgnoredSlot(locationSlot)
}
+ // TODO(b/397223606): Get the actual spec for this.
if (chipHighlight is HeaderChipHighlight.Strong) {
iconManager.setTint(inverseColor, primaryColor)
} else if (chipHighlight is HeaderChipHighlight.Weak) {
@@ -675,62 +624,49 @@
}
@Composable
-private fun NotificationIconChip(
- chipHighlight: HeaderChipHighlight,
+private fun NotificationsChip(
onClick: () -> Unit,
modifier: Modifier = Modifier,
- content: @Composable RowScope.() -> Unit,
+ backgroundColor: Color = Color.Unspecified,
+ content: @Composable BoxScope.() -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
- Box(modifier = modifier) {
- Row(
- modifier =
- Modifier.align(Alignment.CenterStart)
- .clickable(
- interactionSource = interactionSource,
- indication = null,
- onClick = { onClick() },
- )
- .clip(RoundedCornerShape(25.dp))
- .background(
- if (chipHighlight is HeaderChipHighlight.Strong)
- MaterialTheme.colorScheme.chipHighlighted
- else MaterialTheme.colorScheme.chipBackground
- )
- .padding(horizontal = 8.dp, vertical = 4.dp)
- ) {
- content()
- }
+ Box(
+ modifier =
+ modifier
+ .clickable(
+ interactionSource = interactionSource,
+ indication = null,
+ onClick = onClick,
+ )
+ .background(backgroundColor, RoundedCornerShape(25.dp))
+ .padding(horizontal = ChipPaddingHorizontal, vertical = ChipPaddingVertical)
+ ) {
+ content()
}
}
@Composable
private fun SystemIconChip(
modifier: Modifier = Modifier,
- chipHighlight: HeaderChipHighlight = HeaderChipHighlight.None,
+ backgroundColor: Color = Color.Unspecified,
onClick: (() -> Unit)? = null,
content: @Composable RowScope.() -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
val isHovered by interactionSource.collectIsHoveredAsState()
val hoverModifier =
- Modifier.clip(RoundedCornerShape(CollapsedHeight / 4))
- .background(MaterialTheme.colorScheme.onScrimDim)
- val backgroundColor =
- if (chipHighlight is HeaderChipHighlight.Strong) MaterialTheme.colorScheme.chipHighlighted
- else MaterialTheme.colorScheme.chipBackground
+ with(MaterialTheme.colorScheme) {
+ Modifier.background(onScrimDim, RoundedCornerShape(CollapsedHeight / 4))
+ }
Row(
verticalAlignment = Alignment.CenterVertically,
modifier =
modifier
- .thenIf(chipHighlight !is HeaderChipHighlight.None) {
- Modifier.graphicsLayer {
- shape = RoundedCornerShape(25.dp)
- clip = true
- }
- .background(backgroundColor)
- .padding(horizontal = 8.dp, vertical = 4.dp)
+ .thenIf(backgroundColor != Color.Unspecified) {
+ Modifier.background(backgroundColor, RoundedCornerShape(25.dp))
+ .padding(horizontal = ChipPaddingHorizontal, vertical = ChipPaddingVertical)
}
.thenIf(onClick != null) {
Modifier.clickable(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/VariableDayDate.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/VariableDayDate.kt
index 64aada5..8fbd051 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/VariableDayDate.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/VariableDayDate.kt
@@ -4,22 +4,16 @@
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
-import com.android.compose.theme.colorAttr
-import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel.HeaderChipHighlight
@Composable
fun VariableDayDate(
longerDateText: String,
shorterDateText: String,
- chipHighlight: HeaderChipHighlight,
+ textColor: Color,
modifier: Modifier = Modifier,
) {
- val textColor =
- if (chipHighlight is HeaderChipHighlight.Strong)
- colorAttr(android.R.attr.textColorPrimaryInverse)
- else colorAttr(android.R.attr.textColorPrimary)
-
Layout(
contents =
listOf(
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 05958a2..907b5bc 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
@@ -169,7 +169,7 @@
Modifier.maybeElevateInContent(layoutImpl, content, key, currentTransitionStates)
}
.then(ElementModifier(layoutImpl, currentTransitionStates, content, key))
- .thenIf(layoutImpl.implicitTestTags) { Modifier.testTag(key.testTag) }
+ .testTag(key.testTag)
}
/**
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 d47210c..72bb82b 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
@@ -65,8 +65,6 @@
swipeSourceDetector: SwipeSourceDetector = DefaultEdgeDetector,
swipeDetector: SwipeDetector = DefaultSwipeDetector,
@FloatRange(from = 0.0, to = 0.5) transitionInterceptionThreshold: Float = 0.05f,
- // TODO(b/240432457) Remove this once test utils can access the internal STLForTesting().
- implicitTestTags: Boolean = false,
builder: SceneTransitionLayoutScope<ContentScope>.() -> Unit,
) {
SceneTransitionLayoutForTesting(
@@ -75,7 +73,6 @@
swipeSourceDetector,
swipeDetector,
transitionInterceptionThreshold,
- implicitTestTags = implicitTestTags,
onLayoutImpl = null,
builder = builder,
)
@@ -728,8 +725,10 @@
}
/**
- * An internal version of [SceneTransitionLayout] to be used for tests, that provides access to the
- * internal [SceneTransitionLayoutImpl] and implicitly tags all scenes and elements.
+ * An internal version of [SceneTransitionLayout] to be used for tests.
+ *
+ * Important: You should use this only in tests and if you need to access the underlying
+ * [SceneTransitionLayoutImpl]. In other cases, you should use [SceneTransitionLayout].
*/
@Composable
internal fun SceneTransitionLayoutForTesting(
@@ -742,7 +741,6 @@
sharedElementMap: MutableMap<ElementKey, Element> = remember { mutableMapOf() },
ancestors: List<Ancestor> = remember { emptyList() },
lookaheadScope: LookaheadScope? = null,
- implicitTestTags: Boolean = true,
builder: SceneTransitionLayoutScope<InternalContentScope>.() -> Unit,
) {
val density = LocalDensity.current
@@ -767,7 +765,6 @@
directionChangeSlop = directionChangeSlop,
defaultEffectFactory = defaultEffectFactory,
decayAnimationSpec = decayAnimationSpec,
- implicitTestTags = implicitTestTags,
)
.also { onLayoutImpl?.invoke(it) }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
index e3c4eb0..53996d2 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
@@ -122,9 +122,6 @@
* This is used to enable transformations and shared elements across NestedSTLs.
*/
internal val ancestors: List<Ancestor> = emptyList(),
-
- /** Whether elements and scene should be tagged using `Modifier.testTag`. */
- internal val implicitTestTags: Boolean = false,
lookaheadScope: LookaheadScope? = null,
defaultEffectFactory: OverscrollFactory,
) {
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 64cfe38..95d6440 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
@@ -171,7 +171,7 @@
.thenIf(layoutImpl.state.isElevationPossible(content = key, element = null)) {
Modifier.container(containerState)
}
- .thenIf(layoutImpl.implicitTestTags) { Modifier.testTag(key.testTag) }
+ .testTag(key.testTag)
) {
CompositionLocalProvider(LocalOverscrollFactory provides lastFactory) {
scope.content()
@@ -290,7 +290,6 @@
sharedElementMap = layoutImpl.elements,
ancestors = ancestors,
lookaheadScope = layoutImpl.lookaheadScope,
- implicitTestTags = layoutImpl.implicitTestTags,
)
}
}
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 8fce708..698a808 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
@@ -227,7 +227,7 @@
to = SceneB,
transitionLayout = { state ->
coroutineScope = rememberCoroutineScope()
- SceneTransitionLayoutForTesting(state) {
+ SceneTransitionLayout(state) {
scene(SceneA) {
Box(Modifier.size(layoutSize)) {
// Transformed element
@@ -633,7 +633,7 @@
val scope =
rule.setContentAndCreateMainScope {
- SceneTransitionLayoutForTesting(state) {
+ SceneTransitionLayout(state) {
scene(SceneA) { Box(Modifier.element(TestElements.Foo).size(20.dp)) }
scene(SceneB) {}
}
@@ -674,7 +674,7 @@
CompositionLocalProvider(
LocalOverscrollFactory provides rememberOffsetOverscrollEffectFactory()
) {
- SceneTransitionLayoutForTesting(state, Modifier.size(layoutWidth, layoutHeight)) {
+ SceneTransitionLayout(state, Modifier.size(layoutWidth, layoutHeight)) {
scene(key = SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
Spacer(Modifier.fillMaxSize())
}
@@ -734,7 +734,7 @@
CompositionLocalProvider(
LocalOverscrollFactory provides rememberOffsetOverscrollEffectFactory()
) {
- SceneTransitionLayoutForTesting(state, Modifier.size(layoutWidth, layoutHeight)) {
+ SceneTransitionLayout(state, Modifier.size(layoutWidth, layoutHeight)) {
scene(key = SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
Spacer(
Modifier.overscroll(verticalOverscrollEffect)
@@ -834,7 +834,7 @@
CompositionLocalProvider(
LocalOverscrollFactory provides rememberOffsetOverscrollEffectFactory()
) {
- SceneTransitionLayoutForTesting(state, Modifier.size(layoutWidth, layoutHeight)) {
+ SceneTransitionLayout(state, Modifier.size(layoutWidth, layoutHeight)) {
scene(key = SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
Spacer(Modifier.fillMaxSize())
}
@@ -893,7 +893,7 @@
CompositionLocalProvider(
LocalOverscrollFactory provides rememberOffsetOverscrollEffectFactory()
) {
- SceneTransitionLayoutForTesting(
+ SceneTransitionLayout(
state = state,
modifier = Modifier.size(layoutWidth, layoutHeight),
) {
@@ -970,7 +970,7 @@
rule.setContent {
touchSlop = LocalViewConfiguration.current.touchSlop
- SceneTransitionLayoutForTesting(
+ SceneTransitionLayout(
state = state,
modifier = Modifier.size(layoutWidth, layoutHeight),
) {
@@ -1057,7 +1057,7 @@
rule.setContent {
coroutineScope = rememberCoroutineScope()
- SceneTransitionLayoutForTesting(state) {
+ SceneTransitionLayout(state) {
scene(SceneA) {
Box(Modifier.size(layoutSize)) {
Box(
@@ -1374,7 +1374,7 @@
val scope =
rule.setContentAndCreateMainScope {
- SceneTransitionLayoutForTesting(state, Modifier.size(layoutSize)) {
+ SceneTransitionLayout(state, Modifier.size(layoutSize)) {
scene(SceneA) {
Box(Modifier.fillMaxSize()) { Foo(Modifier.align(Alignment.TopStart)) }
}
@@ -1742,7 +1742,7 @@
val scope =
rule.setContentAndCreateMainScope {
- SceneTransitionLayoutForTesting(state, Modifier.size(200.dp)) {
+ SceneTransitionLayout(state, Modifier.size(200.dp)) {
scene(SceneA) { Foo(offset = 0.dp) }
scene(SceneB) { Foo(offset = 20.dp) }
scene(SceneC) { Foo(offset = 40.dp) }
@@ -1828,7 +1828,7 @@
val scope =
rule.setContentAndCreateMainScope {
- SceneTransitionLayoutForTesting(state) {
+ SceneTransitionLayout(state) {
scene(SceneB) { Foo(Modifier.offset(40.dp, 60.dp)) }
// Define A after B so that Foo is placed in A during A <=> B.
@@ -1887,7 +1887,7 @@
val scope =
rule.setContentAndCreateMainScope {
- SceneTransitionLayoutForTesting(state) {
+ SceneTransitionLayout(state) {
scene(SceneA) { Foo() }
scene(SceneB) { Foo(Modifier.offset(40.dp, 60.dp)) }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
index 98ecb64..04c762f 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
@@ -90,7 +90,7 @@
lateinit var coroutineScope: CoroutineScope
rule.setContent {
coroutineScope = rememberCoroutineScope()
- SceneTransitionLayoutForTesting(state, Modifier.size(200.dp)) {
+ SceneTransitionLayout(state, Modifier.size(200.dp)) {
scene(SceneA) { Box(Modifier.fillMaxSize()) { Foo() } }
overlay(OverlayA) { Foo() }
}
@@ -132,7 +132,7 @@
lateinit var coroutineScope: CoroutineScope
rule.setContent {
coroutineScope = rememberCoroutineScope()
- SceneTransitionLayoutForTesting(state, Modifier.size(200.dp)) {
+ SceneTransitionLayout(state, Modifier.size(200.dp)) {
scene(SceneA) { Box(Modifier.fillMaxSize()) { Foo() } }
overlay(OverlayA) { Foo() }
overlay(OverlayB) { Foo() }
@@ -230,7 +230,7 @@
lateinit var coroutineScope: CoroutineScope
rule.setContent {
coroutineScope = rememberCoroutineScope()
- SceneTransitionLayoutForTesting(state, Modifier.size(200.dp)) {
+ SceneTransitionLayout(state, Modifier.size(200.dp)) {
scene(SceneA) { Box(Modifier.fillMaxSize()) { MovableBar() } }
overlay(OverlayA) { MovableBar() }
overlay(OverlayB) { MovableBar() }
@@ -302,7 +302,7 @@
}
var alignment by mutableStateOf(Alignment.Center)
rule.setContent {
- SceneTransitionLayoutForTesting(state, Modifier.size(200.dp)) {
+ SceneTransitionLayout(state, Modifier.size(200.dp)) {
scene(SceneA) { Box(Modifier.fillMaxSize()) { Foo() } }
overlay(OverlayA, alignment = alignment) { Foo() }
}
@@ -761,7 +761,7 @@
val movableElementChildTag = "movableElementChildTag"
val scope =
rule.setContentAndCreateMainScope {
- SceneTransitionLayoutForTesting(state) {
+ SceneTransitionLayout(state) {
scene(SceneA) {
MovableElement(key, Modifier) {
content { Box(Modifier.testTag(movableElementChildTag).size(100.dp)) }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt
index 366b11d..2bf2358 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt
@@ -250,7 +250,7 @@
}
rule.setContent {
- SceneTransitionLayoutForTesting(state, Modifier.size(200.dp)) {
+ SceneTransitionLayout(state, Modifier.size(200.dp)) {
scene(SceneA) { Box(Modifier.fillMaxSize()) }
overlay(OverlayA) { Box(Modifier.fillMaxSize()) }
overlay(OverlayB) { Box(Modifier.fillMaxSize()) }
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 5cbc98f..3578be4 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
@@ -97,7 +97,7 @@
MutableSceneTransitionLayoutStateForTests(SceneA, EmptyTestTransitions)
}
- SceneTransitionLayoutForTesting(state = layoutState, modifier = Modifier.size(LayoutSize)) {
+ SceneTransitionLayout(state = layoutState, modifier = Modifier.size(LayoutSize)) {
scene(SceneA, userActions = mapOf(Back to SceneB)) {
Box(Modifier.fillMaxSize()) {
SharedFoo(size = 50.dp, childOffset = 0.dp, Modifier.align(Alignment.TopEnd))
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 11abbbe..751b314 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
@@ -763,7 +763,7 @@
var touchSlop = 0f
rule.setContent {
touchSlop = LocalViewConfiguration.current.touchSlop
- SceneTransitionLayoutForTesting(state, Modifier.size(layoutSize)) {
+ SceneTransitionLayout(state, Modifier.size(layoutSize)) {
scene(SceneA, userActions = mapOf(Swipe.Start to SceneB, Swipe.End to SceneC)) {
Box(Modifier.fillMaxSize())
}
@@ -837,7 +837,7 @@
rule.setContent {
touchSlop = LocalViewConfiguration.current.touchSlop
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- SceneTransitionLayoutForTesting(state, Modifier.size(layoutSize)) {
+ SceneTransitionLayout(state, Modifier.size(layoutSize)) {
scene(SceneA, userActions = mapOf(Swipe.Start to SceneB, Swipe.End to SceneC)) {
Box(Modifier.fillMaxSize())
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedElementTransformationTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedElementTransformationTest.kt
index 8b56892..bb511bc 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedElementTransformationTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedElementTransformationTest.kt
@@ -40,7 +40,7 @@
import com.android.compose.animation.scene.MutableSceneTransitionLayoutStateForTests
import com.android.compose.animation.scene.Scale
import com.android.compose.animation.scene.SceneKey
-import com.android.compose.animation.scene.SceneTransitionLayoutForTesting
+import com.android.compose.animation.scene.SceneTransitionLayout
import com.android.compose.animation.scene.SceneTransitions
import com.android.compose.animation.scene.TestScenes
import com.android.compose.animation.scene.testNestedTransition
@@ -114,7 +114,7 @@
@Composable
(states: List<MutableSceneTransitionLayoutState>) -> Unit =
{ states ->
- SceneTransitionLayoutForTesting(states[0]) {
+ SceneTransitionLayout(states[0]) {
scene(TestScenes.SceneA, content = { TestElement(elementVariant0A) })
scene(
TestScenes.SceneB,
diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestContentScope.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestContentScope.kt
index e56d1be..6d47bab 100644
--- a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestContentScope.kt
+++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestContentScope.kt
@@ -30,7 +30,5 @@
content: @Composable ContentScope.() -> Unit,
) {
val state = rememberMutableSceneTransitionLayoutState(currentScene)
- SceneTransitionLayout(state, modifier, implicitTestTags = true) {
- scene(currentScene, content = content)
- }
+ SceneTransitionLayout(state, modifier) { scene(currentScene, content = content) }
}
diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt
index a362a37..f94a7ed 100644
--- a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt
@@ -137,7 +137,7 @@
},
changeState = changeState,
transitionLayout = { state ->
- SceneTransitionLayout(state, layoutModifier, implicitTestTags = true) {
+ SceneTransitionLayout(state, layoutModifier) {
scene(fromScene, content = fromSceneContent)
scene(toScene, content = toSceneContent)
}
@@ -163,7 +163,7 @@
)
},
transitionLayout = { state ->
- SceneTransitionLayout(state, implicitTestTags = true) {
+ SceneTransitionLayout(state) {
scene(fromScene) { fromSceneContent() }
overlay(overlay) { overlayContent() }
}
@@ -191,7 +191,7 @@
)
},
transitionLayout = { state ->
- SceneTransitionLayout(state, implicitTestTags = true) {
+ SceneTransitionLayout(state) {
scene(toScene) { toSceneContent() }
overlay(overlay) { overlayContent() }
}
@@ -223,7 +223,7 @@
)
},
transitionLayout = { state ->
- SceneTransitionLayout(state, implicitTestTags = true) {
+ SceneTransitionLayout(state) {
scene(currentScene) { currentSceneContent() }
overlay(from, alignment = fromAlignment) { fromContent() }
overlay(to, alignment = toAlignment) { toContent() }
@@ -273,7 +273,7 @@
}
}
- SceneTransitionLayout(state, layoutModifier, implicitTestTags = true) {
+ SceneTransitionLayout(state, layoutModifier) {
scene(fromScene, content = fromSceneContent)
scene(toScene, content = toSceneContent)
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
index 004d1aa..ac1c5a8 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
@@ -130,39 +130,25 @@
private val FONT_AXES =
listOf(
- ClockFontAxis(
- key = GSFAxes.WEIGHT,
+ GSFAxes.WEIGHT.toClockAxis(
type = AxisType.Float,
- minValue = 25f,
currentValue = 400f,
- maxValue = 1000f,
name = "Weight",
description = "Glyph Weight",
),
- ClockFontAxis(
- key = GSFAxes.WIDTH,
+ GSFAxes.WIDTH.toClockAxis(
type = AxisType.Float,
- minValue = 25f,
currentValue = 85f,
- maxValue = 151f,
name = "Width",
description = "Glyph Width",
),
- ClockFontAxis(
- key = GSFAxes.ROUND,
+ GSFAxes.ROUND.toClockAxis(
type = AxisType.Boolean,
- minValue = 0f,
- currentValue = 0f,
- maxValue = 100f,
name = "Round",
description = "Glyph Roundness",
),
- ClockFontAxis(
- key = GSFAxes.SLANT,
+ GSFAxes.SLANT.toClockAxis(
type = AxisType.Boolean,
- minValue = 0f,
- currentValue = 0f,
- maxValue = -10f,
name = "Slant",
description = "Glyph Slant",
),
@@ -170,10 +156,10 @@
private val LEGACY_FLEX_SETTINGS =
listOf(
- ClockFontAxisSetting(GSFAxes.WEIGHT, 600f),
- ClockFontAxisSetting(GSFAxes.WIDTH, 100f),
- ClockFontAxisSetting(GSFAxes.ROUND, 100f),
- ClockFontAxisSetting(GSFAxes.SLANT, 0f),
+ GSFAxes.WEIGHT.toClockAxisSetting(600f),
+ GSFAxes.WIDTH.toClockAxisSetting(100f),
+ GSFAxes.ROUND.toClockAxisSetting(100f),
+ GSFAxes.SLANT.toClockAxisSetting(0f),
)
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
index b2dbd65..b4c2f5d 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
@@ -132,7 +132,7 @@
if (!isLargeClock) {
axes =
axes.map { axis ->
- if (axis.key == GSFAxes.WIDTH && axis.value > SMALL_CLOCK_MAX_WDTH) {
+ if (axis.key == GSFAxes.WIDTH.tag && axis.value > SMALL_CLOCK_MAX_WDTH) {
axis.copy(value = SMALL_CLOCK_MAX_WDTH)
} else {
axis
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FontUtils.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FontUtils.kt
new file mode 100644
index 0000000..212b1e2
--- /dev/null
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FontUtils.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.clocks
+
+import com.android.systemui.animation.AxisDefinition
+import com.android.systemui.plugins.clocks.AxisType
+import com.android.systemui.plugins.clocks.ClockFontAxis
+import com.android.systemui.plugins.clocks.ClockFontAxisSetting
+
+fun AxisDefinition.toClockAxis(
+ type: AxisType,
+ currentValue: Float? = null,
+ name: String,
+ description: String,
+): ClockFontAxis {
+ return ClockFontAxis(
+ key = this.tag,
+ type = type,
+ maxValue = this.maxValue,
+ minValue = this.minValue,
+ currentValue = currentValue ?: this.defaultValue,
+ name = name,
+ description = description,
+ )
+}
+
+fun AxisDefinition.toClockAxisSetting(value: Float? = null): ClockFontAxisSetting {
+ return ClockFontAxisSetting(this.tag, value ?: this.defaultValue)
+}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
index 8317aa3..b7ce20e 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
@@ -49,6 +49,7 @@
import com.android.systemui.shared.clocks.DimensionParser
import com.android.systemui.shared.clocks.FLEX_CLOCK_ID
import com.android.systemui.shared.clocks.FontTextStyle
+import com.android.systemui.shared.clocks.toClockAxisSetting
import java.lang.Thread
import kotlin.math.max
import kotlin.math.min
@@ -215,12 +216,7 @@
)
}
- setInterpolatedViewBounds(
- getInterpolatedTextBounds(),
- widthMeasureSpec,
- heightMeasureSpec,
- force = true,
- )
+ setInterpolatedViewBounds(getInterpolatedTextBounds(), widthMeasureSpec, heightMeasureSpec)
}
override fun onDraw(canvas: Canvas) {
@@ -388,7 +384,6 @@
interpBounds: Rect,
widthMeasureSpec: Int = measuredWidthAndState,
heightMeasureSpec: Int = measuredHeightAndState,
- force: Boolean = false,
) {
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
@@ -415,10 +410,7 @@
)
}
- if (force || widthSpec != measuredWidthAndState || heightSpec != measuredHeightAndState) {
- setMeasuredDimension(widthSpec, heightSpec)
- parent?.requestLayout()
- }
+ setMeasuredDimension(widthSpec, heightSpec)
}
private fun updateXTranslation(inPoint: Point, interpolatedTextBounds: Rect): Point {
@@ -594,25 +586,25 @@
val FIDGET_INTERPOLATOR = PathInterpolator(0.26873f, 0f, 0.45042f, 1f)
val FIDGET_DISTS =
mapOf(
- GSFAxes.WEIGHT to Pair(200f, 500f),
- GSFAxes.WIDTH to Pair(30f, 75f),
- GSFAxes.ROUND to Pair(0f, 50f),
- GSFAxes.SLANT to Pair(0f, -5f),
+ GSFAxes.WEIGHT.tag to Pair(200f, 500f),
+ GSFAxes.WIDTH.tag to Pair(30f, 75f),
+ GSFAxes.ROUND.tag to Pair(0f, 50f),
+ GSFAxes.SLANT.tag to Pair(0f, -5f),
)
val AOD_COLOR = Color.WHITE
- val LS_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 400f)
- val AOD_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 200f)
- val WIDTH_AXIS = ClockFontAxisSetting(GSFAxes.WIDTH, 85f)
- val ROUND_AXIS = ClockFontAxisSetting(GSFAxes.ROUND, 0f)
- val SLANT_AXIS = ClockFontAxisSetting(GSFAxes.SLANT, 0f)
+ val LS_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(400f)
+ val AOD_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(200f)
+ val WIDTH_AXIS = GSFAxes.WIDTH.toClockAxisSetting(85f)
+ val ROUND_AXIS = GSFAxes.ROUND.toClockAxisSetting(0f)
+ val SLANT_AXIS = GSFAxes.SLANT.toClockAxisSetting(0f)
// Axes for Legacy version of the Flex Clock
- val FLEX_LS_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 600f)
- val FLEX_AOD_LARGE_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 74f)
- val FLEX_AOD_SMALL_WEIGHT_AXIS = ClockFontAxisSetting(GSFAxes.WEIGHT, 133f)
- val FLEX_LS_WIDTH_AXIS = ClockFontAxisSetting(GSFAxes.WIDTH, 100f)
- val FLEX_AOD_WIDTH_AXIS = ClockFontAxisSetting(GSFAxes.WIDTH, 43f)
- val FLEX_ROUND_AXIS = ClockFontAxisSetting(GSFAxes.ROUND, 100f)
+ val FLEX_LS_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(600f)
+ val FLEX_AOD_LARGE_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(74f)
+ val FLEX_AOD_SMALL_WEIGHT_AXIS = GSFAxes.WEIGHT.toClockAxisSetting(133f)
+ val FLEX_LS_WIDTH_AXIS = GSFAxes.WIDTH.toClockAxisSetting(100f)
+ val FLEX_AOD_WIDTH_AXIS = GSFAxes.WIDTH.toClockAxisSetting(43f)
+ val FLEX_ROUND_AXIS = GSFAxes.ROUND.toClockAxisSetting(100f)
}
}
diff --git a/packages/SystemUI/lint-baseline.xml b/packages/SystemUI/lint-baseline.xml
index b0963d3..993932c 100644
--- a/packages/SystemUI/lint-baseline.xml
+++ b/packages/SystemUI/lint-baseline.xml
@@ -32784,4 +32784,15 @@
column="23"/>
</issue>
+ <issue
+ id="ShadeDisplayAwareContextChecker"
+ message="UI elements of the shade window should use ShadeDisplayAware-annotated Context, as the shade might move between windows, and only @ShadeDisplayAware resources are updated with the new configuration correctly. Failures to do so might result in wrong dimensions for shade window classes (e.g. using the wrong density or theme). If the usage of Context is not related to display specific configuration or UI, then there is technically no need to use the annotation, and you can annotate the class with @SuppressLint("ShadeDisplayAwareContextChecker")/@Suppress("ShadeDisplayAwareContextChecker")"
+ errorLine1=" @QSThemedContext Context context,"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+ line="126"
+ column="38"/>
+ </issue>
+
</issues>
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
index c42e25b..d046ad1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
@@ -103,7 +103,7 @@
fun testUpdateEmergencyButton() {
Mockito.`when`(telecomManager.isInCall).thenReturn(true)
Mockito.`when`(lockPatternUtils.isSecure(anyInt())).thenReturn(true)
- Mockito.`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY))
+ Mockito.`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING))
.thenReturn(true)
underTest.updateEmergencyCallButton()
backgroundExecutor.runAllReady()
@@ -112,7 +112,7 @@
/* isInCall= */ any(),
/* hasTelephonyRadio= */ any(),
/* simLocked= */ any(),
- /* isSecure= */ any()
+ /* isSecure= */ any(),
)
mainExecutor.runAllReady()
verify(emergencyButton)
@@ -120,7 +120,7 @@
/* isInCall= */ eq(true),
/* hasTelephonyRadio= */ eq(true),
/* simLocked= */ any(),
- /* isSecure= */ eq(true)
+ /* isSecure= */ eq(true),
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt
index f44769d..8d3640d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/FontVariationUtilsTest.kt
@@ -21,7 +21,7 @@
roundness = 100,
)
Assert.assertEquals(
- "'${GSFAxes.WEIGHT}' 100, '${GSFAxes.WIDTH}' 100, '${GSFAxes.ROUND}' 100",
+ "'${GSFAxes.WEIGHT.tag}' 100, '${GSFAxes.WIDTH.tag}' 100, '${GSFAxes.ROUND.tag}' 100",
initFvar,
)
val updatedFvar =
@@ -32,7 +32,8 @@
roundness = 100,
)
Assert.assertEquals(
- "'${GSFAxes.WEIGHT}' 200, '${GSFAxes.WIDTH}' 100, '${GSFAxes.OPTICAL_SIZE}' 0, '${GSFAxes.ROUND}' 100",
+ "'${GSFAxes.WEIGHT.tag}' 200, '${GSFAxes.WIDTH.tag}' 100," +
+ " '${GSFAxes.OPTICAL_SIZE.tag}' 0, '${GSFAxes.ROUND.tag}' 100",
updatedFvar,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/GhostedViewTransitionAnimatorControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/GhostedViewTransitionAnimatorControllerTest.kt
index 052d520..18b68d2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/GhostedViewTransitionAnimatorControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/GhostedViewTransitionAnimatorControllerTest.kt
@@ -153,10 +153,12 @@
private class FakeViewTransitionRegistry : IViewTransitionRegistry {
val registry = mutableMapOf<ViewTransitionToken, View>()
+ val token = ViewTransitionToken()
- override fun register(token: ViewTransitionToken, view: View) {
+ override fun register(view: View): ViewTransitionToken {
registry[token] = view
view.setTag(R.id.tag_view_transition_token, token)
+ return token
}
override fun unregister(token: ViewTransitionToken) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/ViewTransitionRegistryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/ViewTransitionRegistryTest.kt
index ef91c79..b18eafd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/ViewTransitionRegistryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/ViewTransitionRegistryTest.kt
@@ -25,9 +25,9 @@
import org.junit.Before
import org.junit.runner.RunWith
import org.mockito.kotlin.argumentCaptor
-import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
import kotlin.test.Test
@SmallTest
@@ -36,24 +36,22 @@
private lateinit var view: View
private lateinit var underTest: ViewTransitionRegistry
- private var token: ViewTransitionToken = ViewTransitionToken()
@Before
fun setup() {
view = FrameLayout(mContext)
underTest = ViewTransitionRegistry()
- token = ViewTransitionToken()
}
@Test
fun testSuccessfulRegisterInViewTransitionRegistry() {
- underTest.register(token, view)
+ val token = underTest.register(view)
assertThat(underTest.getView(token)).isNotNull()
}
@Test
fun testSuccessfulUnregisterInViewTransitionRegistry() {
- underTest.register(token, view)
+ val token = underTest.register(view)
assertThat(underTest.getView(token)).isNotNull()
underTest.unregister(token)
@@ -62,13 +60,14 @@
@Test
fun testSuccessfulUnregisterOnViewDetachedFromWindow() {
- val view: View = mock {
- on { getTag(R.id.tag_view_transition_token) } doReturn token
- }
+ val view: View = mock()
- underTest.register(token, view)
+ val token = underTest.register(view)
+ assertThat(token).isEqualTo(token)
assertThat(underTest.getView(token)).isNotNull()
+ whenever(view.getTag(R.id.tag_view_transition_token)).thenReturn(token)
+
argumentCaptor<View.OnAttachStateChangeListener>()
.apply { verify(view).addOnAttachStateChangeListener(capture()) }
.firstValue
@@ -76,4 +75,58 @@
assertThat(underTest.getView(token)).isNull()
}
+
+ @Test
+ fun testMultipleRegisterOnSameView() {
+ val token = underTest.register(view)
+
+ // multiple register on same view should return same token
+ assertThat(underTest.register(view)).isEqualTo(token)
+
+ // 1st unregister doesn't remove the token from registry as refCount = 2
+ underTest.unregister(token)
+ assertThat(underTest.getView(token)).isNotNull()
+
+ // 2nd unregister removes the token from registry
+ underTest.unregister(token)
+ assertThat(underTest.getView(token)).isNull()
+ }
+
+ @Test
+ fun testMultipleRegisterOnSameViewRemovedAfterViewDetached() {
+ val view: View = mock()
+
+ val token = underTest.register(view)
+ whenever(view.getTag(R.id.tag_view_transition_token)).thenReturn(token)
+
+ assertThat(underTest.getViewToken(view)).isEqualTo(token)
+
+ // mock view's detach event
+ val caller = argumentCaptor<View.OnAttachStateChangeListener>()
+ .apply { verify(view).addOnAttachStateChangeListener(capture()) }
+ .firstValue
+
+ // register 3 times
+ underTest.register(view)
+ underTest.register(view)
+ underTest.register(view)
+
+ // unregister 1 time and verify entry should still be present in registry
+ underTest.unregister(token)
+ assertThat(underTest.getView(token)).isNotNull()
+
+ // view's associated entry should be gone from registry, after view detaches
+ caller.onViewDetachedFromWindow(view)
+ assertThat(underTest.getView(token)).isNull()
+ }
+
+ @Test
+ fun testDistinctViewsSameClassRegisterWithDifferentToken() {
+ var prev: ViewTransitionToken? = underTest.register(FrameLayout(mContext))
+ for (i in 0 until 10) {
+ val curr = underTest.register(FrameLayout(mContext))
+ assertThat(curr).isNotEqualTo(prev)
+ prev = curr
+ }
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 50762ed..88c9e74 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -21,6 +21,7 @@
import android.hardware.biometrics.BiometricAuthenticator
import android.hardware.biometrics.BiometricConstants
import android.hardware.biometrics.BiometricManager
+import android.hardware.biometrics.BiometricPrompt
import android.hardware.biometrics.PromptContentViewWithMoreOptionsButton
import android.hardware.biometrics.PromptInfo
import android.hardware.biometrics.PromptVerticalListContentView
@@ -290,7 +291,7 @@
verify(callback)
.onDismissed(
- eq(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED),
+ eq(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED),
eq<ByteArray?>(null), /* credentialAttestation */
eq(authContainer?.requestId ?: 0L),
)
@@ -310,7 +311,7 @@
)
verify(callback)
.onDismissed(
- eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
+ eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL),
eq<ByteArray?>(null), /* credentialAttestation */
eq(authContainer?.requestId ?: 0L),
)
@@ -325,7 +326,7 @@
verify(callback)
.onDismissed(
- eq(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE),
+ eq(BiometricPrompt.DISMISSED_REASON_NEGATIVE),
eq<ByteArray?>(null), /* credentialAttestation */
eq(authContainer?.requestId ?: 0L),
)
@@ -352,7 +353,7 @@
verify(callback)
.onDismissed(
- eq(AuthDialogCallback.DISMISSED_ERROR),
+ eq(BiometricPrompt.DISMISSED_REASON_ERROR),
eq<ByteArray?>(null), /* credentialAttestation */
eq(authContainer?.requestId ?: 0L),
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
index acc97a9..a1a2aa7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -138,9 +138,9 @@
@Mock
private IBiometricContextListener mContextListener;
@Mock
- private AuthDialog mDialog1;
+ private AuthContainerView mDialog1;
@Mock
- private AuthDialog mDialog2;
+ private AuthContainerView mDialog2;
@Mock
private CommandQueue mCommandQueue;
@Mock
@@ -382,7 +382,7 @@
@Test
public void testSendsReasonUserCanceled_whenDismissedByUserCancel() throws Exception {
showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
null, /* credentialAttestation */
mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
@@ -393,7 +393,7 @@
@Test
public void testSendsReasonNegative_whenDismissedByButtonNegative() throws Exception {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE,
null, /* credentialAttestation */
mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
@@ -404,7 +404,7 @@
@Test
public void testSendsReasonConfirmed_whenDismissedByButtonPositive() throws Exception {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_POSITIVE,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED,
null, /* credentialAttestation */
mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
@@ -415,7 +415,7 @@
@Test
public void testSendsReasonConfirmNotRequired_whenDismissedByAuthenticated() throws Exception {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED,
null, /* credentialAttestation */
mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
@@ -426,7 +426,7 @@
@Test
public void testSendsReasonError_whenDismissedByError() throws Exception {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_ERROR,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_ERROR,
null, /* credentialAttestation */
mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
@@ -437,7 +437,7 @@
@Test
public void testSendsReasonServerRequested_whenDismissedByServer() throws Exception {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED,
null, /* credentialAttestation */
mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
@@ -452,7 +452,7 @@
final byte[] credentialAttestation = generateRandomHAT();
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED,
credentialAttestation, mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
eq(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED),
@@ -462,7 +462,7 @@
@Test
public void testSendsReasonContentViewMoreOptions_whenButtonPressed() throws Exception {
showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS,
null, /* credentialAttestation */
mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
@@ -696,7 +696,7 @@
final byte[] credentialAttestation = generateRandomHAT();
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED,
credentialAttestation, mAuthController.mCurrentDialog.getRequestId());
verify(mReceiver).onDialogDismissed(
eq(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED),
@@ -755,7 +755,7 @@
public void testDoesNotCrash_whenTryAgainPressedAfterDismissal() {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
final long requestID = mAuthController.mCurrentDialog.getRequestId();
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
null, /* credentialAttestation */requestID);
mAuthController.onTryAgainPressed(requestID);
}
@@ -764,7 +764,7 @@
public void testDoesNotCrash_whenDeviceCredentialPressedAfterDismissal() {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
final long requestID = mAuthController.mCurrentDialog.getRequestId();
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
null /* credentialAttestation */, requestID);
mAuthController.onDeviceCredentialPressed(requestID);
}
@@ -818,7 +818,7 @@
// WHEN dialog is shown and then dismissed
showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
- mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED,
+ mAuthController.onDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
null /* credentialAttestation */,
mAuthController.mCurrentDialog.getRequestId());
@@ -1218,14 +1218,14 @@
}
@Override
- protected AuthDialog buildDialog(DelayableExecutor bgExecutor, PromptInfo promptInfo,
+ protected AuthContainerView buildDialog(DelayableExecutor bgExecutor, PromptInfo promptInfo,
boolean requireConfirmation, int userId, int[] sensorIds,
String opPackageName, boolean skipIntro, long operationId, long requestId,
WakefulnessLifecycle wakefulnessLifecycle,
UserManager userManager,
LockPatternUtils lockPatternUtils, PromptViewModel viewModel) {
- AuthDialog dialog;
+ AuthContainerView dialog;
if (mBuildCount == 0) {
dialog = mDialog1;
} else if (mBuildCount == 1) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
index 197cb84..9c3ef04 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
@@ -25,6 +25,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -39,6 +40,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import org.junit.Before;
@@ -65,22 +67,25 @@
@Mock SystemUIDialog.Factory mSystemUIDialogFactory;
@Mock SystemUIDialog mDialog;
@Mock BiometricNotificationDialogFactory.ActivityStarter mActivityStarter;
-
private final ArgumentCaptor<DialogInterface.OnClickListener> mOnClickListenerArgumentCaptor =
ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
private final ArgumentCaptor<Intent> mIntentArgumentCaptor =
ArgumentCaptor.forClass(Intent.class);
private BiometricNotificationDialogFactory mDialogFactory;
+ private FakeShadeDialogContextInteractor mDialogContextInteractor;
@Before
public void setUp() throws ExecutionException, InterruptedException {
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
- when(mSystemUIDialogFactory.create()).thenReturn(mDialog);
+ when(mSystemUIDialogFactory.create(any(Context.class))).thenReturn(mDialog);
+
+ mDialogContextInteractor = new FakeShadeDialogContextInteractor(mContext);
mDialogFactory = new BiometricNotificationDialogFactory(
mResources,
mSystemUIDialogFactory,
+ mDialogContextInteractor,
mFingerprintManager,
mFaceManager
);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
index 98486a2..af6c65e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
@@ -538,7 +538,6 @@
simpleShortcutCategory(System, "System apps", "Open settings"),
simpleShortcutCategory(System, "System controls", "Lock screen"),
simpleShortcutCategory(System, "System controls", "View notifications"),
- simpleShortcutCategory(System, "System apps", "Take a note"),
simpleShortcutCategory(System, "System controls", "Take screenshot"),
simpleShortcutCategory(System, "System controls", "Go back"),
simpleShortcutCategory(MultiTasking, "Split screen", "Use full screen"),
@@ -570,7 +569,6 @@
simpleInputGestureData(
keyGestureType = KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL
),
- simpleInputGestureData(keyGestureType = KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES),
simpleInputGestureData(
keyGestureType = KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT
),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
index 208abf3..6c4325a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
@@ -35,12 +35,20 @@
import android.os.PowerManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
+import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.common.data.repository.batteryRepository
+import com.android.systemui.common.data.repository.fake
+import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository
+import com.android.systemui.communal.domain.interactor.communalSceneInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalV2Available
+import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -54,6 +62,8 @@
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
@@ -62,6 +72,8 @@
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
import com.android.systemui.testKosmos
+import com.android.systemui.util.settings.fakeSettings
+import com.google.common.truth.Truth
import junit.framework.Assert.assertEquals
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.advanceTimeBy
@@ -416,4 +428,25 @@
assertThat(transitionRepository)
.startedTransition(from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN)
}
+
+ @Test
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun testTransitionToGlanceableHub_onWakeUpFromAod() =
+ kosmos.runTest {
+ val user = setCommunalV2Available(true)
+ fakeSettings.putIntForUser(Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, user.id)
+ batteryRepository.fake.setDevicePluggedIn(true)
+
+ val currentScene by collectLastValue(communalSceneInteractor.currentScene)
+ fakeCommunalSceneRepository.changeScene(CommunalScenes.Blank)
+
+ // Communal is not showing
+ Truth.assertThat(currentScene).isEqualTo(CommunalScenes.Blank)
+
+ powerInteractor.setAwakeForTest()
+ testScope.advanceTimeBy(100) // account for debouncing
+
+ Truth.assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
+ assertThat(transitionRepository).noTransitionsStarted()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModelTest.kt
new file mode 100644
index 0000000..052dfd5
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModelTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DozingToDreamingTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+
+ val underTest by lazy { kosmos.dozingToDreamingTransitionViewModel }
+
+ @Test
+ fun notificationShadeAlpha() =
+ kosmos.runTest {
+ val values by collectValues(underTest.notificationAlpha)
+ assertThat(values).isEmpty()
+
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.DOZING,
+ to = KeyguardState.DREAMING,
+ testScope,
+ )
+
+ assertThat(values).isNotEmpty()
+ values.forEach { assertThat(it).isEqualTo(0) }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt
index 4e14fec..943ada9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/binder/SeekBarObserverTest.kt
@@ -18,6 +18,9 @@
import android.animation.Animator
import android.animation.ObjectAnimator
+import android.icu.text.MeasureFormat
+import android.icu.util.Measure
+import android.icu.util.MeasureUnit
import android.testing.TestableLooper
import android.view.View
import android.widget.SeekBar
@@ -30,6 +33,7 @@
import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel
import com.android.systemui.res.R
import com.google.common.truth.Truth.assertThat
+import java.util.Locale
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -61,11 +65,11 @@
fun setUp() {
context.orCreateTestableResources.addOverride(
R.dimen.qs_media_enabled_seekbar_height,
- enabledHeight
+ enabledHeight,
)
context.orCreateTestableResources.addOverride(
R.dimen.qs_media_disabled_seekbar_height,
- disabledHeight
+ disabledHeight,
)
seekBarView = SeekBar(context)
@@ -110,14 +114,31 @@
@Test
fun seekBarProgress() {
+ val elapsedTime = 3000
+ val duration = (1.5 * 60 * 60 * 1000).toInt()
// WHEN part of the track has been played
- val data = SeekBarViewModel.Progress(true, true, true, false, 3000, 120000, true)
+ val data = SeekBarViewModel.Progress(true, true, true, false, elapsedTime, duration, true)
observer.onChanged(data)
// THEN seek bar shows the progress
- assertThat(seekBarView.progress).isEqualTo(3000)
- assertThat(seekBarView.max).isEqualTo(120000)
+ assertThat(seekBarView.progress).isEqualTo(elapsedTime)
+ assertThat(seekBarView.max).isEqualTo(duration)
- val desc = context.getString(R.string.controls_media_seekbar_description, "00:03", "02:00")
+ val expectedProgress =
+ MeasureFormat.getInstance(Locale.getDefault(), MeasureFormat.FormatWidth.WIDE)
+ .formatMeasures(Measure(3, MeasureUnit.SECOND))
+ val expectedDuration =
+ MeasureFormat.getInstance(Locale.getDefault(), MeasureFormat.FormatWidth.WIDE)
+ .formatMeasures(
+ Measure(1, MeasureUnit.HOUR),
+ Measure(30, MeasureUnit.MINUTE),
+ Measure(0, MeasureUnit.SECOND),
+ )
+ val desc =
+ context.getString(
+ R.string.controls_media_seekbar_description,
+ expectedProgress,
+ expectedDuration,
+ )
assertThat(seekBarView.contentDescription).isEqualTo(desc)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacyTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacyTest.java
index a7a0c24..f293614 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacyTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacyTest.java
@@ -369,6 +369,37 @@
}
@Test
+ public void onBindViewHolder_initSeekbarWithUnmutedVolume_displaysMuteIcon() {
+ when(mMediaSwitchingController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true);
+ when(mMediaDevice1.getMaxVolume()).thenReturn(TEST_MAX_VOLUME);
+ when(mMediaDevice1.getCurrentVolume()).thenReturn(TEST_CURRENT_VOLUME);
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mIconAreaLayout.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mViewHolder.mIconAreaLayout.performClick();
+ verify(mMediaSwitchingController).adjustVolume(mMediaDevice1, 0);
+ verify(mMediaSwitchingController).logInteractionMuteDevice(mMediaDevice1);
+ }
+
+ @Test
+ public void onBindViewHolder_initSeekbarWithMutedVolume_displaysUnmuteIcon() {
+ when(mMediaSwitchingController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true);
+ when(mMediaDevice1.getMaxVolume()).thenReturn(TEST_MAX_VOLUME);
+ when(mMediaDevice1.getCurrentVolume()).thenReturn(0); // muted.
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mIconAreaLayout.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mViewHolder.mIconAreaLayout.performClick();
+ // Default unmute volume is 2.
+ verify(mMediaSwitchingController).adjustVolume(mMediaDevice1, 2);
+ verify(mMediaSwitchingController).logInteractionUnmuteDevice(mMediaDevice1);
+ }
+
+ @Test
public void onBindViewHolder_dragSeekbar_setsVolume() {
mOnSeekBarChangeListenerCaptor = ArgumentCaptor.forClass(
SeekBar.OnSeekBarChangeListener.class);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt
index 645efae..ab217a3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt
@@ -31,21 +31,18 @@
@Test
fun selectTile_isCorrectlySelected() {
- assertThat(underTest.selection?.tileSpec).isNotEqualTo(TEST_SPEC)
+ assertThat(underTest.selection).isNotEqualTo(TEST_SPEC)
- underTest.select(TEST_SPEC, manual = true)
- assertThat(underTest.selection?.tileSpec).isEqualTo(TEST_SPEC)
- assertThat(underTest.selection?.manual).isTrue()
+ underTest.select(TEST_SPEC)
+ assertThat(underTest.selection).isEqualTo(TEST_SPEC)
underTest.unSelect()
assertThat(underTest.selection).isNull()
val newSpec = TileSpec.create("newSpec")
- underTest.select(TEST_SPEC, manual = true)
- underTest.select(newSpec, manual = false)
- assertThat(underTest.selection?.tileSpec).isNotEqualTo(TEST_SPEC)
- assertThat(underTest.selection?.tileSpec).isEqualTo(newSpec)
- assertThat(underTest.selection?.manual).isFalse()
+ underTest.select(TEST_SPEC)
+ underTest.select(newSpec)
+ assertThat(underTest.selection).isEqualTo(newSpec)
}
companion object {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
index fee358a..83860ec 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
@@ -63,6 +63,7 @@
import org.mockito.MockitoAnnotations;
import java.util.List;
+import java.util.Optional;
import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;
@@ -100,7 +101,7 @@
@Mock
private BatteryController mBatteryController;
@Mock
- DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
+ Optional<DeviceStateRotationLockSettingController> mDeviceStateRotationLockSettingController;
@Mock
RotationPolicyWrapper mRotationPolicyWrapper;
@Mock
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegateTest.kt
index 97a10e6..e5191e9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegateTest.kt
@@ -23,6 +23,7 @@
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -46,24 +47,27 @@
private lateinit var sysuiDialogFactory: SystemUIDialog.Factory
private lateinit var sysuiDialog: SystemUIDialog
private lateinit var dataSaverDialogDelegate: DataSaverDialogDelegate
+ private lateinit var contextInteractor: FakeShadeDialogContextInteractor
@Before
fun setup() {
sysuiDialog = mock<SystemUIDialog>()
sysuiDialogFactory = mock<SystemUIDialog.Factory>()
+ contextInteractor = FakeShadeDialogContextInteractor(context)
dataSaverDialogDelegate =
DataSaverDialogDelegate(
sysuiDialogFactory,
- context,
+ contextInteractor,
EmptyCoroutineContext,
dataSaverController,
- mock<SharedPreferences>()
+ mock<SharedPreferences>(),
)
whenever(sysuiDialogFactory.create(eq(dataSaverDialogDelegate), eq(context)))
.thenReturn(sysuiDialog)
}
+
@Test
fun delegateSetsDialogTitleCorrectly() {
val expectedResId = R.string.data_saver_enable_title
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractorTest.kt
index 2e9f24c..87ac034a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractorTest.kt
@@ -29,6 +29,7 @@
import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
import com.android.systemui.settings.UserFileManager
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -53,17 +54,19 @@
private lateinit var sharedPreferences: SharedPreferences
private lateinit var dialogFactory: SystemUIDialog.Factory
private lateinit var underTest: DataSaverTileUserActionInteractor
+ private lateinit var contextInteractor: FakeShadeDialogContextInteractor
@Before
fun setup() {
userFileManager = mock<UserFileManager>()
sharedPreferences = mock<SharedPreferences>()
dialogFactory = mock<SystemUIDialog.Factory>()
+ contextInteractor = FakeShadeDialogContextInteractor(mContext)
whenever(
userFileManager.getSharedPreferences(
eq(DataSaverTileUserActionInteractor.PREFS),
eq(Context.MODE_PRIVATE),
- eq(context.userId)
+ eq(context.userId),
)
)
.thenReturn(sharedPreferences)
@@ -71,6 +74,7 @@
underTest =
DataSaverTileUserActionInteractor(
context,
+ contextInteractor,
EmptyCoroutineContext,
EmptyCoroutineContext,
dataSaverController,
@@ -87,7 +91,7 @@
whenever(
sharedPreferences.getBoolean(
eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
- any()
+ any(),
)
)
.thenReturn(true)
@@ -107,7 +111,7 @@
whenever(
sharedPreferences.getBoolean(
eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
- any()
+ any(),
)
)
.thenReturn(false)
@@ -128,7 +132,7 @@
whenever(
sharedPreferences.getBoolean(
eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
- any()
+ any(),
)
)
.thenReturn(false)
@@ -144,7 +148,7 @@
whenever(
sharedPreferences.getBoolean(
eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
- any()
+ any(),
)
)
.thenReturn(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelTest.kt
index 6e26fa11..701e55d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelTest.kt
@@ -24,17 +24,22 @@
import com.android.systemui.flags.EnableSceneContainer
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.composefragment.dagger.usingMediaInComposeFragment
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@@ -79,4 +84,22 @@
assertThat(underTest.showHeader).isFalse()
}
+
+ @Test
+ fun showMedia_activeMedia_true() =
+ testScope.runTest {
+ kosmos.mediaFilterRepository.addSelectedUserMediaEntry(MediaData(active = true))
+ runCurrent()
+
+ assertThat(underTest.showMedia).isTrue()
+ }
+
+ @Test
+ fun showMedia_noActiveMedia_false() =
+ testScope.runTest {
+ kosmos.mediaFilterRepository.addSelectedUserMediaEntry(MediaData(active = false))
+ runCurrent()
+
+ assertThat(underTest.showMedia).isFalse()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryTest.kt
index 35368ca..9498daa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryTest.kt
@@ -60,6 +60,7 @@
policies,
shadeOnDefaultDisplayWhenLocked = shadeOnDefaultDisplayWhenLocked,
keyguardRepository,
+ displayRepository,
)
@Test
@@ -90,6 +91,30 @@
}
@Test
+ fun displayId_afterDisplayDisconnected_fallsBackToDefaultDisplay() =
+ testScope.runTest {
+ val underTest = createUnderTest()
+ globalSettings.putString(
+ DEVELOPMENT_SHADE_DISPLAY_AWARENESS,
+ FakeShadeDisplayPolicy.name,
+ )
+ val displayId by collectLastValue(underTest.displayId)
+
+ displayRepository.addDisplay(displayId = 1)
+
+ FakeShadeDisplayPolicy.setDisplayId(1)
+ assertThat(displayId).isEqualTo(1)
+
+ // Let's disconnect and make sure it goes back to the default one
+ displayRepository.removeDisplay(displayId = 1)
+ assertThat(displayId).isEqualTo(Display.DEFAULT_DISPLAY)
+
+ // Let's re-connect it and make sure it goes back to the non-default one
+ displayRepository.addDisplay(displayId = 1)
+ assertThat(displayId).isEqualTo(1)
+ }
+
+ @Test
fun policy_updatesBasedOnSettingValue_defaultDisplay() =
testScope.runTest {
val underTest = createUnderTest()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorTest.kt
index 84fc930..a3dd67f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorTest.kt
@@ -22,6 +22,9 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.activityStarter
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback
@@ -31,22 +34,32 @@
import com.android.systemui.util.mockito.argThat
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import java.util.Date
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatcher
-import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class ShadeHeaderClockInteractorTest : SysuiTestCase() {
+
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val activityStarter = kosmos.activityStarter
private val nextAlarmController = kosmos.nextAlarmController
- val underTest = kosmos.shadeHeaderClockInteractor
+ private val underTest = kosmos.shadeHeaderClockInteractor
@Test
fun launchClockActivity_default() =
@@ -55,7 +68,7 @@
verify(activityStarter)
.postStartActivityDismissingKeyguard(
argThat(IntentMatcherAction(AlarmClock.ACTION_SHOW_ALARMS)),
- any()
+ any(),
)
}
@@ -71,6 +84,75 @@
underTest.launchClockActivity()
verify(activityStarter).postStartActivityDismissingKeyguard(any())
}
+
+ @Test
+ fun onTimezoneOrLocaleChanged_localeAndTimezoneChanged_emitsForEach() =
+ testScope.runTest {
+ val timeZoneOrLocaleChanges by collectValues(underTest.onTimezoneOrLocaleChanged)
+
+ sendIntentActionBroadcast(Intent.ACTION_TIMEZONE_CHANGED)
+ sendIntentActionBroadcast(Intent.ACTION_LOCALE_CHANGED)
+ sendIntentActionBroadcast(Intent.ACTION_LOCALE_CHANGED)
+ sendIntentActionBroadcast(Intent.ACTION_TIMEZONE_CHANGED)
+
+ assertThat(timeZoneOrLocaleChanges).hasSize(4)
+ }
+
+ @Test
+ fun onTimezoneOrLocaleChanged_timeChanged_doesNotEmit() =
+ testScope.runTest {
+ val timeZoneOrLocaleChanges by collectValues(underTest.onTimezoneOrLocaleChanged)
+ assertThat(timeZoneOrLocaleChanges).hasSize(1)
+
+ sendIntentActionBroadcast(Intent.ACTION_TIME_CHANGED)
+ sendIntentActionBroadcast(Intent.ACTION_TIME_TICK)
+
+ // Expect only 1 event to have been emitted onStart, but no more.
+ assertThat(timeZoneOrLocaleChanges).hasSize(1)
+ }
+
+ @Test
+ fun currentTime_timeChanged() =
+ testScope.runTest {
+ val currentTime by collectLastValue(underTest.currentTime)
+
+ sendIntentActionBroadcast(Intent.ACTION_TIME_CHANGED)
+ val earlierTime = checkNotNull(currentTime)
+
+ advanceTimeBy(3.seconds)
+ runCurrent()
+
+ sendIntentActionBroadcast(Intent.ACTION_TIME_CHANGED)
+ val laterTime = checkNotNull(currentTime)
+
+ assertThat(differenceBetween(laterTime, earlierTime)).isEqualTo(3.seconds)
+ }
+
+ @Test
+ fun currentTime_timeTicked() =
+ testScope.runTest {
+ val currentTime by collectLastValue(underTest.currentTime)
+
+ sendIntentActionBroadcast(Intent.ACTION_TIME_TICK)
+ val earlierTime = checkNotNull(currentTime)
+
+ advanceTimeBy(7.seconds)
+ runCurrent()
+
+ sendIntentActionBroadcast(Intent.ACTION_TIME_TICK)
+ val laterTime = checkNotNull(currentTime)
+
+ assertThat(differenceBetween(laterTime, earlierTime)).isEqualTo(7.seconds)
+ }
+
+ private fun differenceBetween(date1: Date, date2: Date): Duration {
+ return (date1.time - date2.time).milliseconds
+ }
+
+ private fun TestScope.sendIntentActionBroadcast(intentAction: String) {
+ kosmos.broadcastDispatcher.sendIntentToMatchingReceiversOnly(context, Intent(intentAction))
+ runCurrent()
+ }
}
private class IntentMatcherAction(private val action: String) : ArgumentMatcher<Intent> {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
index 061e04e..37b4688 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
@@ -25,12 +25,15 @@
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
+import com.android.systemui.shade.domain.interactor.shadeMode
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel.HeaderChipHighlight
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.argThat
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
@@ -43,6 +46,7 @@
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableSceneContainer
@@ -64,14 +68,15 @@
@Test
fun mobileSubIds_update() =
testScope.runTest {
- val mobileSubIds by collectLastValue(underTest.mobileSubIds)
mobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1)
+ runCurrent()
- assertThat(mobileSubIds).isEqualTo(listOf(1))
+ assertThat(underTest.mobileSubIds).isEqualTo(listOf(1))
mobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
+ runCurrent()
- assertThat(mobileSubIds).isEqualTo(listOf(1, 2))
+ assertThat(underTest.mobileSubIds).isEqualTo(listOf(1, 2))
}
@Test
@@ -116,13 +121,9 @@
@Test
fun onSystemIconChipClicked_lockedOnQsShade_collapsesShadeToLockscreen() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Lockscreen, overlay = Overlays.QuickSettingsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(false)
- setScene(Scenes.Lockscreen)
- setOverlay(Overlays.QuickSettingsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onSystemIconChipClicked()
runCurrent()
@@ -134,13 +135,9 @@
@Test
fun onSystemIconChipClicked_lockedOnNotifShade_expandsQsShade() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Lockscreen, overlay = Overlays.NotificationsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(false)
- setScene(Scenes.Lockscreen)
- setOverlay(Overlays.NotificationsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onSystemIconChipClicked()
runCurrent()
@@ -166,13 +163,9 @@
@Test
fun onSystemIconChipClicked_unlockedOnQsShade_collapsesShadeToGone() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Gone, overlay = Overlays.QuickSettingsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(true)
- setScene(Scenes.Gone)
- setOverlay(Overlays.QuickSettingsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onSystemIconChipClicked()
runCurrent()
@@ -184,13 +177,9 @@
@Test
fun onSystemIconChipClicked_unlockedOnNotifShade_expandsQsShade() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Gone, overlay = Overlays.NotificationsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(true)
- setScene(Scenes.Gone)
- setOverlay(Overlays.NotificationsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onSystemIconChipClicked()
runCurrent()
@@ -203,13 +192,9 @@
@Test
fun onNotificationIconChipClicked_lockedOnNotifShade_collapsesShadeToLockscreen() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Lockscreen, overlay = Overlays.NotificationsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(false)
- setScene(Scenes.Lockscreen)
- setOverlay(Overlays.NotificationsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onNotificationIconChipClicked()
runCurrent()
@@ -221,13 +206,9 @@
@Test
fun onNotificationIconChipClicked_lockedOnQsShade_expandsNotifShade() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Lockscreen, overlay = Overlays.QuickSettingsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(false)
- setScene(Scenes.Lockscreen)
- setOverlay(Overlays.QuickSettingsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onNotificationIconChipClicked()
runCurrent()
@@ -240,13 +221,9 @@
@Test
fun onNotificationIconChipClicked_unlockedOnNotifShade_collapsesShadeToGone() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Gone, overlay = Overlays.NotificationsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(true)
- setScene(Scenes.Gone)
- setOverlay(Overlays.NotificationsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onNotificationIconChipClicked()
runCurrent()
@@ -258,13 +235,9 @@
@Test
fun onNotificationIconChipClicked_unlockedOnQsShade_expandsNotifShade() =
testScope.runTest {
- kosmos.enableDualShade()
+ setupDualShadeState(scene = Scenes.Gone, overlay = Overlays.QuickSettingsShade)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
- setDeviceEntered(true)
- setScene(Scenes.Gone)
- setOverlay(Overlays.QuickSettingsShade)
- assertThat(currentOverlays).isNotEmpty()
underTest.onNotificationIconChipClicked()
runCurrent()
@@ -319,22 +292,13 @@
@Test
fun highlightChips_notifsOpenInDualShade_notifsStrongQuickSettingsWeak() =
testScope.runTest {
- kosmos.enableDualShade()
- val currentScene by collectLastValue(sceneInteractor.currentScene)
- val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
-
// Test the lockscreen scenario.
- setScene(Scenes.Lockscreen)
- setOverlay(Overlays.NotificationsShade)
+ setupDualShadeState(scene = Scenes.Lockscreen, overlay = Overlays.NotificationsShade)
assertThat(underTest.notificationsChipHighlight).isEqualTo(HeaderChipHighlight.Strong)
assertThat(underTest.quickSettingsChipHighlight).isEqualTo(HeaderChipHighlight.Weak)
// Test the unlocked scenario.
- setDeviceEntered(true)
- setScene(Scenes.Gone)
- setOverlay(Overlays.NotificationsShade)
- assertThat(currentScene).isEqualTo(Scenes.Gone)
- assertThat(currentOverlays).isNotEmpty()
+ setupDualShadeState(scene = Scenes.Gone, overlay = Overlays.NotificationsShade)
assertThat(underTest.notificationsChipHighlight).isEqualTo(HeaderChipHighlight.Strong)
assertThat(underTest.quickSettingsChipHighlight).isEqualTo(HeaderChipHighlight.Weak)
}
@@ -342,22 +306,13 @@
@Test
fun highlightChips_quickSettingsOpenInDualShade_notifsWeakQuickSettingsStrong() =
testScope.runTest {
- kosmos.enableDualShade()
- val currentScene by collectLastValue(sceneInteractor.currentScene)
- val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
-
// Test the lockscreen scenario.
- setScene(Scenes.Lockscreen)
- setOverlay(Overlays.QuickSettingsShade)
+ setupDualShadeState(scene = Scenes.Lockscreen, overlay = Overlays.QuickSettingsShade)
assertThat(underTest.notificationsChipHighlight).isEqualTo(HeaderChipHighlight.Weak)
assertThat(underTest.quickSettingsChipHighlight).isEqualTo(HeaderChipHighlight.Strong)
// Test the unlocked scenario.
- setDeviceEntered(true)
- setScene(Scenes.Gone)
- setOverlay(Overlays.QuickSettingsShade)
- assertThat(currentScene).isEqualTo(Scenes.Gone)
- assertThat(currentOverlays).isNotEmpty()
+ setupDualShadeState(scene = Scenes.Gone, overlay = Overlays.QuickSettingsShade)
assertThat(underTest.notificationsChipHighlight).isEqualTo(HeaderChipHighlight.Weak)
assertThat(underTest.quickSettingsChipHighlight).isEqualTo(HeaderChipHighlight.Strong)
}
@@ -365,21 +320,13 @@
@Test
fun highlightChips_noOverlaysInDualShade_bothNone() =
testScope.runTest {
- kosmos.enableDualShade()
- val currentScene by collectLastValue(sceneInteractor.currentScene)
- val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
-
// Test the lockscreen scenario.
- setScene(Scenes.Lockscreen)
- assertThat(currentOverlays).isEmpty()
+ setupDualShadeState(scene = Scenes.Lockscreen)
assertThat(underTest.notificationsChipHighlight).isEqualTo(HeaderChipHighlight.None)
assertThat(underTest.quickSettingsChipHighlight).isEqualTo(HeaderChipHighlight.None)
// Test the unlocked scenario.
- setDeviceEntered(true)
- setScene(Scenes.Gone)
- assertThat(currentScene).isEqualTo(Scenes.Gone)
- assertThat(currentOverlays).isEmpty()
+ setupDualShadeState(scene = Scenes.Gone)
assertThat(underTest.notificationsChipHighlight).isEqualTo(HeaderChipHighlight.None)
assertThat(underTest.quickSettingsChipHighlight).isEqualTo(HeaderChipHighlight.None)
}
@@ -401,6 +348,39 @@
)
}
+ private fun TestScope.setupDualShadeState(scene: SceneKey, overlay: OverlayKey? = null) {
+ kosmos.enableDualShade()
+ val shadeMode by collectLastValue(kosmos.shadeMode)
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ if (scene == Scenes.Gone) {
+ // Unlock the device, marking the device has been entered.
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ }
+ runCurrent()
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+
+ sceneInteractor.changeScene(scene, "test")
+ checkNotNull(currentOverlays).forEach { sceneInteractor.instantlyHideOverlay(it, "test") }
+ runCurrent()
+ overlay?.let { sceneInteractor.showOverlay(it, "test") }
+ sceneInteractor.setTransitionState(
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(scene, setOfNotNull(overlay))
+ )
+ )
+ runCurrent()
+
+ assertThat(currentScene).isEqualTo(scene)
+ if (overlay == null) {
+ assertThat(currentOverlays).isEmpty()
+ } else {
+ assertThat(currentOverlays).containsExactly(overlay)
+ }
+ }
+
private fun setScene(key: SceneKey) {
sceneInteractor.changeScene(key, "test")
sceneInteractor.setTransitionState(
@@ -409,17 +389,6 @@
testScope.runCurrent()
}
- private fun setOverlay(key: OverlayKey) {
- val currentOverlays = sceneInteractor.currentOverlays.value + key
- sceneInteractor.showOverlay(key, "test")
- sceneInteractor.setTransitionState(
- MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(sceneInteractor.currentScene.value, currentOverlays)
- )
- )
- testScope.runCurrent()
- }
-
private fun TestScope.setDeviceEntered(isEntered: Boolean) {
if (isEntered) {
// Unlock the device marking the device has entered.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java
index c6801f1..3d8da61 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -23,8 +23,8 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -35,14 +35,12 @@
import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
import android.os.Bundle;
-import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.view.KeyEvent;
import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
-import android.view.accessibility.Flags;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -385,30 +383,7 @@
}
@Test
- @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
- public void addQsTile_withA11yQsShortcutFlagOff() {
- ComponentName c = new ComponentName("testpkg", "testcls");
-
- mCommandQueue.addQsTile(c);
- waitForIdleSync();
-
- verify(mCallbacks).addQsTile(eq(c));
- }
-
- @Test
- @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
- public void addQsTileToFrontOrEnd_withA11yQsShortcutFlagOff_doNothing() {
- ComponentName c = new ComponentName("testpkg", "testcls");
-
- mCommandQueue.addQsTileToFrontOrEnd(c, true);
- waitForIdleSync();
-
- verifyNoMoreInteractions(mCallbacks);
- }
-
- @Test
- @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
- public void addQsTile_withA11yQsShortcutFlagOn() {
+ public void addQsTile() {
ComponentName c = new ComponentName("testpkg", "testcls");
mCommandQueue.addQsTile(c);
@@ -418,8 +393,7 @@
}
@Test
- @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
- public void addQsTileAtTheEnd_withA11yQsShortcutFlagOn() {
+ public void addQsTileAtTheEnd() {
ComponentName c = new ComponentName("testpkg", "testcls");
mCommandQueue.addQsTileToFrontOrEnd(c, true);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/DragDownHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
index 05d9495..a8aac39 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
@@ -74,7 +74,7 @@
dragDownHelper.cancelChildExpansion(expandableView, animationDuration = 0)
- verify(expandableView, atLeast(1)).actualHeight = collapsedHeight
+ verify(expandableView, atLeast(1)).setFinalActualHeight(collapsedHeight)
}
@Test
@@ -83,6 +83,6 @@
dragDownHelper.cancelChildExpansion(expandableView, animationDuration = 0)
- verify(expandableView, never()).actualHeight = anyInt()
+ verify(expandableView, never()).setFinalActualHeight(anyInt())
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
index cd66ef3..242da0b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
@@ -86,7 +86,7 @@
pulseExpansionHandler.reset(expandableView, animationDuration = 0)
- verify(expandableView, atLeast(1)).actualHeight = collapsedHeight
+ verify(expandableView, atLeast(1)).setFinalActualHeight(collapsedHeight)
}
@Test
@@ -95,6 +95,6 @@
pulseExpansionHandler.reset(expandableView, animationDuration = 0)
- verify(expandableView, never()).actualHeight = anyInt()
+ verify(expandableView, never()).setFinalActualHeight(anyInt())
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt
index e38ea30..9fd189f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractorTest.kt
@@ -20,11 +20,14 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
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.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.addOngoingCallState
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.removeOngoingCallState
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlinx.coroutines.test.runTest
@@ -33,22 +36,20 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class CallChipInteractorTest : SysuiTestCase() {
- val kosmos = Kosmos()
+ val kosmos = testKosmos().useUnconfinedTestDispatcher()
val repo = kosmos.ongoingCallRepository
val underTest = kosmos.callChipInteractor
@Test
- fun ongoingCallState_matchesRepo() =
- kosmos.testScope.runTest {
+ fun ongoingCallState_matchesState() =
+ kosmos.runTest {
val latest by collectLastValue(underTest.ongoingCallState)
- val inCall = inCallModel(startTimeMs = 1000)
- repo.setOngoingCallState(inCall)
- assertThat(latest).isEqualTo(inCall)
+ addOngoingCallState(key = "testKey")
+ assertThat(latest).isInstanceOf(OngoingCallModel.InCall::class.java)
- val noCall = OngoingCallModel.NoCall
- repo.setOngoingCallState(noCall)
- assertThat(latest).isEqualTo(noCall)
+ removeOngoingCallState(key = "testKey")
+ assertThat(latest).isEqualTo(OngoingCallModel.NoCall)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
index c7b3175..fda4ab0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
@@ -27,7 +27,9 @@
import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.plugins.activityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
@@ -35,17 +37,11 @@
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
-import com.android.systemui.statusbar.core.StatusBarRootModernization
-import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
-import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
-import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
-import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
-import com.android.systemui.statusbar.notification.shared.CallType
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
-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.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.addOngoingCallState
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.removeOngoingCallState
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -60,10 +56,7 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class CallChipViewModelTest : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val notificationListRepository = kosmos.activeNotificationListRepository
- private val testScope = kosmos.testScope
- private val repo = kosmos.ongoingCallRepository
+ private val kosmos = testKosmos().useUnconfinedTestDispatcher()
private val chipBackgroundView = mock<ChipBackgroundContainer>()
private val chipView =
@@ -82,53 +75,53 @@
@Test
fun chip_noCall_isHidden() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(OngoingCallModel.NoCall)
+ removeOngoingCallState("testKey")
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Inactive::class.java)
}
@Test
fun chip_inCall_zeroStartTime_isShownAsIconOnly() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(inCallModel(startTimeMs = 0))
+ addOngoingCallState(startTimeMs = 0)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
}
@Test
fun chip_inCall_negativeStartTime_isShownAsIconOnly() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(inCallModel(startTimeMs = -2))
+ addOngoingCallState(startTimeMs = -2)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
}
@Test
fun chip_inCall_positiveStartTime_isShownAsTimer() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(inCallModel(startTimeMs = 345))
+ addOngoingCallState(startTimeMs = 345)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
}
@Test
fun chip_inCall_startTimeConvertedToElapsedRealtime() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
kosmos.fakeSystemClock.setCurrentTimeMillis(3000)
kosmos.fakeSystemClock.setElapsedRealtime(400_000)
- repo.setOngoingCallState(inCallModel(startTimeMs = 1000))
+ addOngoingCallState(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
@@ -141,13 +134,11 @@
@Test
@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun chip_positiveStartTime_connectedDisplaysFlagOn_iconIsNotifIcon() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
val notifKey = "testNotifKey"
- repo.setOngoingCallState(
- inCallModel(startTimeMs = 1000, notificationIcon = null, notificationKey = notifKey)
- )
+ addOngoingCallState(startTimeMs = 1000, statusBarChipIconView = null, key = notifKey)
assertThat((latest as OngoingActivityChipModel.Active).icon)
.isInstanceOf(
@@ -163,16 +154,14 @@
@Test
@DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun chip_zeroStartTime_cdFlagOff_iconIsNotifIcon_withContentDescription() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
val notifIcon = createStatusBarIconViewOrNull()
- repo.setOngoingCallState(
- inCallModel(
- startTimeMs = 0,
- notificationIcon = notifIcon,
- appName = "Fake app name",
- )
+ addOngoingCallState(
+ startTimeMs = 0,
+ statusBarChipIconView = notifIcon,
+ appName = "Fake app name",
)
assertThat((latest as OngoingActivityChipModel.Active).icon)
@@ -190,16 +179,13 @@
@Test
@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun chip_zeroStartTime_cdFlagOn_iconIsNotifKeyIcon_withContentDescription() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(
- inCallModel(
- startTimeMs = 0,
- notificationIcon = createStatusBarIconViewOrNull(),
- notificationKey = "notifKey",
- appName = "Fake app name",
- )
+ addOngoingCallState(
+ key = "notifKey",
+ statusBarChipIconView = createStatusBarIconViewOrNull(),
+ appName = "Fake app name",
)
assertThat((latest as OngoingActivityChipModel.Active).icon)
@@ -219,10 +205,10 @@
@Test
@DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun chip_notifIconFlagOn_butNullNotifIcon_cdFlagOff_iconIsPhone() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(inCallModel(startTimeMs = 1000, notificationIcon = null))
+ addOngoingCallState(statusBarChipIconView = null)
assertThat((latest as OngoingActivityChipModel.Active).icon)
.isInstanceOf(OngoingActivityChipModel.ChipIcon.SingleColorIcon::class.java)
@@ -237,16 +223,13 @@
@Test
@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun chip_notifIconFlagOn_butNullNotifIcon_cdFlagOn_iconIsNotifKeyIcon_withContentDescription() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(
- inCallModel(
- startTimeMs = 1000,
- notificationIcon = null,
- notificationKey = "notifKey",
- appName = "Fake app name",
- )
+ addOngoingCallState(
+ key = "notifKey",
+ statusBarChipIconView = null,
+ appName = "Fake app name",
)
assertThat((latest as OngoingActivityChipModel.Active).icon)
@@ -265,10 +248,10 @@
@Test
fun chip_positiveStartTime_colorsAreAccentThemed() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(inCallModel(startTimeMs = 1000, promotedContent = null))
+ addOngoingCallState(startTimeMs = 1000, promotedContent = null)
assertThat((latest as OngoingActivityChipModel.Active).colors)
.isEqualTo(ColorsModel.AccentThemed)
@@ -276,10 +259,10 @@
@Test
fun chip_zeroStartTime_colorsAreAccentThemed() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(inCallModel(startTimeMs = 0, promotedContent = null))
+ addOngoingCallState(startTimeMs = 0, promotedContent = null)
assertThat((latest as OngoingActivityChipModel.Active).colors)
.isEqualTo(ColorsModel.AccentThemed)
@@ -287,19 +270,19 @@
@Test
fun chip_resetsCorrectly() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
kosmos.fakeSystemClock.setCurrentTimeMillis(3000)
kosmos.fakeSystemClock.setElapsedRealtime(400_000)
// Start a call
- repo.setOngoingCallState(inCallModel(startTimeMs = 1000))
+ addOngoingCallState(key = "testKey", startTimeMs = 1000)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java)
assertThat((latest as OngoingActivityChipModel.Active.Timer).startTimeMs)
.isEqualTo(398_000)
// End the call
- repo.setOngoingCallState(OngoingCallModel.NoCall)
+ removeOngoingCallState(key = "testKey")
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Inactive::class.java)
// Let 100_000ms elapse
@@ -307,31 +290,31 @@
kosmos.fakeSystemClock.setElapsedRealtime(500_000)
// Start a new call, which started 1000ms ago
- repo.setOngoingCallState(inCallModel(startTimeMs = 102_000))
+ addOngoingCallState(key = "testKey", startTimeMs = 102_000)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java)
assertThat((latest as OngoingActivityChipModel.Active.Timer).startTimeMs)
.isEqualTo(499_000)
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_inCall_nullIntent_nullClickListener() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- repo.setOngoingCallState(inCallModel(startTimeMs = 1000, intent = null))
+ addOngoingCallState(contentIntent = null)
assertThat((latest as OngoingActivityChipModel.Active).onClickListenerLegacy).isNull()
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_inCall_positiveStartTime_validIntent_clickListenerLaunchesIntent() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
val pendingIntent = mock<PendingIntent>()
- repo.setOngoingCallState(inCallModel(startTimeMs = 1000, intent = pendingIntent))
+ addOngoingCallState(startTimeMs = 1000, contentIntent = pendingIntent)
val clickListener = (latest as OngoingActivityChipModel.Active).onClickListenerLegacy
assertThat(clickListener).isNotNull()
@@ -343,13 +326,13 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_inCall_zeroStartTime_validIntent_clickListenerLaunchesIntent() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
val pendingIntent = mock<PendingIntent>()
- repo.setOngoingCallState(inCallModel(startTimeMs = 0, intent = pendingIntent))
+ addOngoingCallState(startTimeMs = 0, contentIntent = pendingIntent)
val clickListener = (latest as OngoingActivityChipModel.Active).onClickListenerLegacy
assertThat(clickListener).isNotNull()
@@ -362,33 +345,25 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_inCall_nullIntent_noneClickBehavior() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
- postOngoingCallNotification(
- repository = notificationListRepository,
- startTimeMs = 1000L,
- intent = null,
- )
+ addOngoingCallState(startTimeMs = 1000, contentIntent = null)
assertThat((latest as OngoingActivityChipModel.Active).clickBehavior)
.isInstanceOf(OngoingActivityChipModel.ClickBehavior.None::class.java)
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_inCall_positiveStartTime_validIntent_clickBehaviorLaunchesIntent() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
val pendingIntent = mock<PendingIntent>()
- postOngoingCallNotification(
- repository = notificationListRepository,
- startTimeMs = 1000L,
- intent = pendingIntent,
- )
+ addOngoingCallState(startTimeMs = 1000, contentIntent = pendingIntent)
val clickBehavior = (latest as OngoingActivityChipModel.Active).clickBehavior
assertThat(clickBehavior)
@@ -403,17 +378,13 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_inCall_zeroStartTime_validIntent_clickBehaviorLaunchesIntent() =
- testScope.runTest {
+ kosmos.runTest {
val latest by collectLastValue(underTest.chip)
val pendingIntent = mock<PendingIntent>()
- postOngoingCallNotification(
- repository = notificationListRepository,
- startTimeMs = 0L,
- intent = pendingIntent,
- )
+ addOngoingCallState(startTimeMs = 0, contentIntent = pendingIntent)
val clickBehavior = (latest as OngoingActivityChipModel.Active).clickBehavior
assertThat(clickBehavior)
@@ -435,27 +406,6 @@
mock<StatusBarIconView>()
}
- fun postOngoingCallNotification(
- repository: ActiveNotificationListRepository,
- startTimeMs: Long,
- intent: PendingIntent?,
- ) {
- repository.activeNotifications.value =
- ActiveNotificationsStore.Builder()
- .apply {
- addIndividualNotif(
- activeNotificationModel(
- key = "notif1",
- whenTime = startTimeMs,
- callType = CallType.Ongoing,
- statusBarChipIcon = null,
- contentIntent = intent,
- )
- )
- }
- .build()
- }
-
private val PROMOTED_CONTENT_WITH_COLOR =
PromotedNotificationContentModel.Builder("notif")
.apply {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
index cd3c8cd..ccc844a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel
import android.content.DialogInterface
-import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -48,10 +47,10 @@
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
-import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import com.android.systemui.statusbar.policy.CastDevice
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -438,7 +437,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_projectionStateEntireScreen_clickListenerShowsScreenCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -454,7 +453,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_projectionStateSingleTask_clickListenerShowsScreenCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -475,7 +474,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_routerStateCasting_clickListenerShowsGenericCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -505,7 +504,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_projectionStateCasting_clickListenerHasCuj() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -525,7 +524,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_routerStateCasting_clickListenerHasCuj() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -554,7 +553,7 @@
}
@Test
- @EnableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_routerStateCasting_hasClickBehavior() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -575,7 +574,7 @@
}
@Test
- @EnableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_projectionStateCasting_hasClickBehavior() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -588,7 +587,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_projectionStateEntireScreen_clickBehaviorShowsScreenCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -605,7 +604,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_projectionStateSingleTask_clickBehaviorShowsScreenCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -627,7 +626,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_routerStateCasting_clickBehaviorShowsGenericCastDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 7cf817a..4993b56 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -38,16 +38,17 @@
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
-import com.android.systemui.statusbar.core.StatusBarRootModernization
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.UnconfinedFakeHeadsUpRowRepository
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.headsup.PinnedStatus
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -295,11 +296,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
this.shortCriticalText = "Arrived"
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 30.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 30.minutes.inWholeMilliseconds)
}
setNotifs(
listOf(
@@ -351,11 +348,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
this.wasPromotedAutomatically = true
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 30.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 30.minutes.inWholeMilliseconds)
}
setNotifs(
listOf(
@@ -383,11 +376,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
this.wasPromotedAutomatically = false
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 30.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 30.minutes.inWholeMilliseconds)
}
setNotifs(
listOf(
@@ -414,11 +403,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 13.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 13.minutes.inWholeMilliseconds)
}
setNotifs(
@@ -446,11 +431,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 500,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 500)
}
setNotifs(
@@ -478,11 +459,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime)
}
setNotifs(
@@ -510,11 +487,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime - 2.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime - 2.minutes.inWholeMilliseconds)
}
setNotifs(
@@ -543,11 +516,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 3.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 3.minutes.inWholeMilliseconds)
}
setNotifs(
@@ -579,13 +548,16 @@
val currentTime = 30.minutes.inWholeMilliseconds
fakeSystemClock.setCurrentTimeMillis(currentTime)
+ val currentElapsed =
+ currentTime + fakeSystemClock.elapsedRealtime() -
+ fakeSystemClock.currentTimeMillis()
+
+ val whenElapsed = currentElapsed - 1.minutes.inWholeMilliseconds
+
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 10.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.CountUp,
- )
+ When.Chronometer(elapsedRealtimeMillis = whenElapsed, isCountDown = false)
}
setNotifs(
listOf(
@@ -599,6 +571,8 @@
assertThat(latest).hasSize(1)
assertThat(latest!![0]).isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
+ assertThat((latest!![0] as OngoingActivityChipModel.Active.Timer).startTimeMs)
+ .isEqualTo(whenElapsed)
}
@Test
@@ -609,13 +583,16 @@
val currentTime = 30.minutes.inWholeMilliseconds
fakeSystemClock.setCurrentTimeMillis(currentTime)
+ val currentElapsed =
+ currentTime + fakeSystemClock.elapsedRealtime() -
+ fakeSystemClock.currentTimeMillis()
+
+ val whenElapsed = currentElapsed + 10.minutes.inWholeMilliseconds
+
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 10.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.CountDown,
- )
+ When.Chronometer(elapsedRealtimeMillis = whenElapsed, isCountDown = true)
}
setNotifs(
listOf(
@@ -629,6 +606,8 @@
assertThat(latest).hasSize(1)
assertThat(latest!![0]).isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
+ assertThat((latest!![0] as OngoingActivityChipModel.Active.Timer).startTimeMs)
+ .isEqualTo(whenElapsed)
}
@Test
@@ -641,11 +620,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 10.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 10.minutes.inWholeMilliseconds)
}
setNotifs(
listOf(
@@ -675,11 +650,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 10.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 10.minutes.inWholeMilliseconds)
}
setNotifs(
listOf(
@@ -716,19 +687,11 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 10.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 10.minutes.inWholeMilliseconds)
}
val otherPromotedContentBuilder =
PromotedNotificationContentModel.Builder("other notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 10.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 10.minutes.inWholeMilliseconds)
}
val icon = createStatusBarIconViewOrNull()
val otherIcon = createStatusBarIconViewOrNull()
@@ -772,11 +735,7 @@
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
- this.time =
- PromotedNotificationContentModel.When(
- time = currentTime + 10.minutes.inWholeMilliseconds,
- mode = PromotedNotificationContentModel.When.Mode.BasicTime,
- )
+ this.time = When.Time(currentTime + 10.minutes.inWholeMilliseconds)
}
setNotifs(
listOf(
@@ -802,11 +761,8 @@
}
@Test
- @DisableFlags(
- FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY,
- StatusBarRootModernization.FLAG_NAME,
- StatusBarChipsModernization.FLAG_NAME,
- )
+ @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
+ @DisableChipsModernization
fun chips_chipsModernizationDisabled_clickingChipNotifiesInteractor() =
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
@@ -834,7 +790,7 @@
@Test
@DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chips_chipsModernizationEnabled_clickingChipNotifiesInteractor() =
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
index 6cfad85..005af36 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
@@ -17,8 +17,6 @@
package com.android.systemui.statusbar.chips.screenrecord.ui.viewmodel
import android.content.DialogInterface
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -44,10 +42,10 @@
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
-import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -282,7 +280,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_notProjecting_clickListenerShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -299,7 +297,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_projectingEntireScreen_clickListenerShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -317,7 +315,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_projectingSingleTask_clickListenerShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -339,7 +337,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_clickListenerHasCujLegacy() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -359,7 +357,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_recordingState_hasClickBehavior() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -370,7 +368,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_notProjecting_expandActionBehaviorShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -386,7 +384,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_projectingEntireScreen_expandActionBehaviorShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -401,7 +399,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_projectingSingleTask_expandActionBehaviorShowsDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
index e708382..d6b10a8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
@@ -49,10 +49,10 @@
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
-import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -506,7 +506,7 @@
@Test
@EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_noScreen_clickListenerShowsGenericShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -527,7 +527,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_entireScreen_clickListenerShowsScreenShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -548,7 +548,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_singleTask_clickListenerShowsScreenShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -573,7 +573,7 @@
}
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun chip_clickListenerHasCuj() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -597,7 +597,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_noScreen_hasClickBehavior() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -609,7 +609,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_entireScreen_hasClickBehavior() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -621,7 +621,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_singleTask_hasClickBehavior() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -637,11 +637,8 @@
}
@Test
- @EnableFlags(
- FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP,
- StatusBarRootModernization.FLAG_NAME,
- StatusBarChipsModernization.FLAG_NAME,
- )
+ @EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
+ @EnableChipsModernization
fun chip_noScreen_clickBehaviorShowsGenericShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -657,7 +654,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_entireScreen_clickBehaviorShowsScreenShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -673,7 +670,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun chip_singleTask_clickBehaviorShowsScreenShareDialog() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt
index fc3af11..39b19d3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipViewModelTest.kt
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.chips.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -31,9 +29,9 @@
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickCallback
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
-import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import kotlin.test.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
@@ -64,7 +62,7 @@
mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
@Test
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
fun createDialogLaunchOnClickListener_showsDialogOnClick() {
val cuj = DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Test")
val clickListener =
@@ -82,7 +80,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun createDialogLaunchOnClickCallback_showsDialogOnClick() {
val cuj = DialogCuj(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP, tag = "Test")
val clickCallback =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
index 626dcd5..719924c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
@@ -22,15 +22,18 @@
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
import com.android.systemui.mediaprojection.taskswitcher.FakeActivityTaskManager.Companion.createTask
@@ -48,16 +51,13 @@
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
-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.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.addOngoingCallState
+import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.removeOngoingCallState
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -72,15 +72,14 @@
/** Tests for [OngoingActivityChipsViewModel] when the [StatusBarNotifChips] flag is disabled. */
@SmallTest
@RunWith(AndroidJUnit4::class)
+@EnableFlags(StatusBarChipsModernization.FLAG_NAME)
@DisableFlags(StatusBarNotifChips.FLAG_NAME)
class OngoingActivityChipsViewModelTest : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
+ private val kosmos = testKosmos().useUnconfinedTestDispatcher()
private val systemClock = kosmos.fakeSystemClock
private val screenRecordState = kosmos.screenRecordRepository.screenRecordState
private val mediaProjectionState = kosmos.fakeMediaProjectionRepository.mediaProjectionState
- private val callRepo = kosmos.ongoingCallRepository
private val mockSystemUIDialog = mock<SystemUIDialog>()
private val chipBackgroundView = mock<ChipBackgroundContainer>()
@@ -96,7 +95,7 @@
private val mockExpandable: Expandable =
mock<Expandable>().apply { whenever(dialogTransitionController(any())).thenReturn(mock()) }
- private val underTest = kosmos.ongoingActivityChipsViewModel
+ private val Kosmos.underTest by Kosmos.Fixture { ongoingActivityChipsViewModel }
@Before
fun setUp() {
@@ -111,10 +110,10 @@
@Test
fun primaryChip_allHidden_hidden() =
- testScope.runTest {
+ kosmos.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value = MediaProjectionState.NotProjecting
- callRepo.setOngoingCallState(OngoingCallModel.NoCall)
+ removeOngoingCallState("testKey")
val latest by collectLastValue(underTest.primaryChip)
@@ -123,10 +122,10 @@
@Test
fun primaryChip_screenRecordShow_restHidden_screenRecordShown() =
- testScope.runTest {
+ kosmos.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value = MediaProjectionState.NotProjecting
- callRepo.setOngoingCallState(OngoingCallModel.NoCall)
+ removeOngoingCallState("testKey")
val latest by collectLastValue(underTest.primaryChip)
@@ -135,10 +134,10 @@
@Test
fun primaryChip_screenRecordShowAndCallShow_screenRecordShown() =
- testScope.runTest {
+ kosmos.runTest {
screenRecordState.value = ScreenRecordModel.Recording
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ addOngoingCallState()
val latest by collectLastValue(underTest.primaryChip)
@@ -147,11 +146,11 @@
@Test
fun primaryChip_screenRecordShowAndShareToAppShow_screenRecordShown() =
- testScope.runTest {
+ kosmos.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- callRepo.setOngoingCallState(OngoingCallModel.NoCall)
+ removeOngoingCallState("testKey")
val latest by collectLastValue(underTest.primaryChip)
@@ -160,11 +159,11 @@
@Test
fun primaryChip_shareToAppShowAndCallShow_shareToAppShown() =
- testScope.runTest {
+ kosmos.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ addOngoingCallState()
val latest by collectLastValue(underTest.primaryChip)
@@ -173,15 +172,13 @@
@Test
fun primaryChip_screenRecordAndShareToAppAndCastToOtherHideAndCallShown_callShown() =
- testScope.runTest {
+ kosmos.runTest {
val notificationKey = "call"
screenRecordState.value = ScreenRecordModel.DoingNothing
// MediaProjection covers both share-to-app and cast-to-other-device
mediaProjectionState.value = MediaProjectionState.NotProjecting
- callRepo.setOngoingCallState(
- inCallModel(startTimeMs = 34, notificationKey = notificationKey)
- )
+ addOngoingCallState(key = notificationKey)
val latest by collectLastValue(underTest.primaryChip)
@@ -190,12 +187,10 @@
@Test
fun primaryChip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
- testScope.runTest {
+ kosmos.runTest {
// Start with just the lowest priority chip shown
val callNotificationKey = "call"
- callRepo.setOngoingCallState(
- inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
- )
+ addOngoingCallState(key = callNotificationKey)
// And everything else hidden
mediaProjectionState.value = MediaProjectionState.NotProjecting
screenRecordState.value = ScreenRecordModel.DoingNothing
@@ -224,15 +219,13 @@
@Test
fun primaryChip_highestPriorityChipRemoved_showsNextPriorityChip() =
- testScope.runTest {
+ kosmos.runTest {
// WHEN all chips are active
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
val callNotificationKey = "call"
- callRepo.setOngoingCallState(
- inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
- )
+ addOngoingCallState(key = callNotificationKey)
val latest by collectLastValue(underTest.primaryChip)
@@ -255,17 +248,15 @@
/** Regression test for b/347726238. */
@Test
fun primaryChip_timerDoesNotResetAfterSubscribersRestart() =
- testScope.runTest {
+ kosmos.runTest {
var latest: OngoingActivityChipModel? = null
- val job1 = underTest.primaryChip.onEach { latest = it }.launchIn(this)
+ val job1 = underTest.primaryChip.onEach { latest = it }.launchIn(kosmos.testScope)
// Start a chip with a timer
systemClock.setElapsedRealtime(1234)
screenRecordState.value = ScreenRecordModel.Recording
- runCurrent()
-
assertThat((latest as OngoingActivityChipModel.Active.Timer).startTimeMs)
.isEqualTo(1234)
@@ -276,9 +267,7 @@
systemClock.setElapsedRealtime(5678)
// WHEN we re-subscribe to the chip flow
- val job2 = underTest.primaryChip.onEach { latest = it }.launchIn(this)
-
- runCurrent()
+ val job2 = underTest.primaryChip.onEach { latest = it }.launchIn(kosmos.testScope)
// THEN the old start time is still used
assertThat((latest as OngoingActivityChipModel.Active.Timer).startTimeMs)
@@ -289,14 +278,14 @@
@Test
fun primaryChip_screenRecordStoppedViaDialog_chipHiddenWithoutAnimation() =
- testScope.runTest {
+ kosmos.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(
NORMAL_PACKAGE,
hostDeviceName = "Recording Display",
)
- callRepo.setOngoingCallState(OngoingCallModel.NoCall)
+ removeOngoingCallState("testKey")
val latest by collectLastValue(underTest.primaryChip)
@@ -319,11 +308,11 @@
@Test
fun primaryChip_projectionStoppedViaDialog_chipHiddenWithoutAnimation() =
- testScope.runTest {
+ kosmos.runTest {
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
screenRecordState.value = ScreenRecordModel.DoingNothing
- callRepo.setOngoingCallState(OngoingCallModel.NoCall)
+ removeOngoingCallState("testKey")
val latest by collectLastValue(underTest.primaryChip)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
index 20637cd..2887de3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
@@ -22,7 +22,6 @@
import android.content.res.mainResources
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
-import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -57,7 +56,6 @@
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.assertIsScreenRecordChip
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.assertIsShareToAppChip
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
-import com.android.systemui.statusbar.core.StatusBarRootModernization
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
@@ -66,7 +64,8 @@
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.addOngoingCallState
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.removeOngoingCallState
import com.android.systemui.testKosmos
@@ -138,7 +137,7 @@
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Inactive::class.java)
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_allHidden_bothPrimaryAndSecondaryHidden() =
kosmos.runTest {
@@ -155,7 +154,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_allInactive() =
kosmos.runTest {
@@ -184,7 +183,7 @@
assertIsScreenRecordChip(latest)
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_screenRecordShow_restHidden_primaryIsScreenRecordSecondaryIsHidden() =
kosmos.runTest {
@@ -201,7 +200,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_screenRecordActive_restInactive() =
kosmos.runTest {
@@ -230,7 +229,7 @@
assertIsScreenRecordChip(latest)
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_screenRecordShowAndCallShow_primaryIsScreenRecordSecondaryIsCall() =
kosmos.runTest {
@@ -246,7 +245,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_screenRecordAndCallActive_inThatOrder() =
kosmos.runTest {
@@ -265,7 +264,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_oneChip_notSquished() =
kosmos.runTest {
@@ -278,7 +277,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_oneChip_notSquished() =
kosmos.runTest {
@@ -291,7 +290,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
}
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_twoTimerChips_isSmallPortrait_bothSquished() =
kosmos.runTest {
@@ -307,7 +306,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
}
- @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_twoTimerChips_isSmallPortrait_bothSquished() =
kosmos.runTest {
@@ -323,7 +322,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
}
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_countdownChipAndTimerChip_countdownNotSquished_butTimerSquished() =
kosmos.runTest {
@@ -340,7 +339,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
}
- @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_countdownChipAndTimerChip_countdownNotSquished_butTimerSquished() =
kosmos.runTest {
@@ -357,7 +356,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
}
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_numberOfChipsChanges_chipsGetSquishedAndUnsquished() =
kosmos.runTest {
@@ -393,7 +392,7 @@
.isInstanceOf(OngoingActivityChipModel.Inactive::class.java)
}
- @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_numberOfChipsChanges_chipsGetSquishedAndUnsquished() =
kosmos.runTest {
@@ -425,7 +424,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
}
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_twoChips_isLandscape_notSquished() =
kosmos.runTest {
@@ -448,7 +447,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
}
- @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_twoChips_isLandscape_notSquished() =
kosmos.runTest {
@@ -471,7 +470,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
}
- @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_twoChips_isLargeScreen_notSquished() =
kosmos.runTest {
@@ -490,7 +489,7 @@
.isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
}
- @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_twoChips_isLargeScreen_notSquished() =
kosmos.runTest {
@@ -522,7 +521,7 @@
assertIsScreenRecordChip(latest)
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_screenRecordShowAndShareToAppShow_primaryIsScreenRecordSecondaryIsHidden() =
kosmos.runTest {
@@ -542,7 +541,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_screenRecordAndShareToApp_screenRecordIsActiveShareToAppIsInOverflow() =
kosmos.runTest {
@@ -577,7 +576,7 @@
assertIsShareToAppChip(latest)
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_shareToAppShowAndCallShow_primaryIsShareToAppSecondaryIsCall() =
kosmos.runTest {
@@ -595,7 +594,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_shareToAppAndCallActive() =
kosmos.runTest {
@@ -631,7 +630,7 @@
assertIsCallChip(latest, callNotificationKey)
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_onlyCallShown_primaryIsCallSecondaryIsHidden() =
kosmos.runTest {
@@ -651,7 +650,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_callActive_restInactive() =
kosmos.runTest {
@@ -671,7 +670,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_singlePromotedNotif_primaryIsNotifSecondaryIsHidden() =
kosmos.runTest {
@@ -695,7 +694,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_singlePromotedNotif() =
kosmos.runTest {
@@ -720,7 +719,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_twoPromotedNotifs_primaryAndSecondaryAreNotifsInOrder() =
kosmos.runTest {
@@ -751,7 +750,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_twoPromotedNotifs_bothActiveInOrder() =
kosmos.runTest {
@@ -785,7 +784,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_threePromotedNotifs_topTwoShown() =
kosmos.runTest {
@@ -823,7 +822,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_threePromotedNotifs_topTwoActiveThirdInOverflow() =
kosmos.runTest {
@@ -865,7 +864,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_callAndPromotedNotifs_primaryIsCallSecondaryIsNotif() =
kosmos.runTest {
@@ -898,7 +897,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_callAndPromotedNotifs_callAndFirstNotifActiveSecondNotifInOverflow() =
kosmos.runTest {
@@ -935,7 +934,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModelLegacy())
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_screenRecordAndCallAndPromotedNotifs_notifsNotShown() =
kosmos.runTest {
@@ -958,7 +957,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_screenRecordAndCallAndPromotedNotif_notifInOverflow() =
kosmos.runTest {
@@ -1076,7 +1075,7 @@
assertIsNotifChip(latest, context, notifIcon, "notif")
}
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_movesChipsAroundAccordingToPriority() =
kosmos.runTest {
@@ -1152,7 +1151,7 @@
assertThat(unused).isEqualTo(MultipleOngoingActivityChipsModel())
}
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_movesChipsAroundAccordingToPriority() =
kosmos.runTest {
@@ -1291,7 +1290,7 @@
}
/** Regression test for b/347726238. */
- @DisableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @DisableChipsModernization
@Test
fun chipsLegacy_timerDoesNotResetAfterSubscribersRestart() =
kosmos.runTest {
@@ -1327,7 +1326,7 @@
}
/** Regression test for b/347726238. */
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
@Test
fun chips_timerDoesNotResetAfterSubscribersRestart() =
kosmos.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
index ab475c5..2f6bedb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
@@ -37,6 +37,8 @@
import com.android.systemui.statusbar.layout.LetterboxAppearanceCalculator
import com.android.systemui.statusbar.layout.StatusBarBoundsProvider
import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent
+import com.android.systemui.statusbar.phone.ongoingcall.DisableChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
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
@@ -387,6 +389,7 @@
}
@Test
+ @DisableChipsModernization
fun statusBarMode_ongoingCallAndFullscreen_semiTransparent() =
testScope.runTest {
val latest by collectLastValue(underTest.statusBarAppearance)
@@ -398,6 +401,19 @@
}
@Test
+ @EnableChipsModernization
+ fun statusBarMode_ongoingProcessRequiresStatusBarVisible_andFullscreen_semiTransparent() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.statusBarAppearance)
+
+ underTest.setOngoingProcessRequiresStatusBarVisible(true)
+ onSystemBarAttributesChanged(requestedVisibleTypes = WindowInsets.Type.navigationBars())
+
+ assertThat(latest!!.mode).isEqualTo(StatusBarMode.SEMI_TRANSPARENT)
+ }
+
+ @Test
+ @DisableChipsModernization
fun statusBarMode_ongoingCallButNotFullscreen_matchesAppearance() =
testScope.runTest {
val latest by collectLastValue(underTest.statusBarAppearance)
@@ -413,6 +429,23 @@
}
@Test
+ @EnableChipsModernization
+ fun statusBarMode_ongoingProcessRequiresStatusBarVisible_butNotFullscreen_matchesAppearance() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.statusBarAppearance)
+
+ underTest.setOngoingProcessRequiresStatusBarVisible(true)
+
+ onSystemBarAttributesChanged(
+ requestedVisibleTypes = WindowInsets.Type.statusBars(),
+ appearance = APPEARANCE_OPAQUE_STATUS_BARS,
+ )
+
+ assertThat(latest!!.mode).isEqualTo(StatusBarMode.OPAQUE)
+ }
+
+ @Test
+ @DisableChipsModernization
fun statusBarMode_fullscreenButNotOngoingCall_matchesAppearance() =
testScope.runTest {
val latest by collectLastValue(underTest.statusBarAppearance)
@@ -427,6 +460,21 @@
}
@Test
+ @EnableChipsModernization
+ fun statusBarMode_fullscreen_butNotOngoingProcessRequiresStatusBarVisible_matchesAppearance() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.statusBarAppearance)
+
+ underTest.setOngoingProcessRequiresStatusBarVisible(false)
+ onSystemBarAttributesChanged(
+ requestedVisibleTypes = WindowInsets.Type.navigationBars(),
+ appearance = APPEARANCE_OPAQUE_STATUS_BARS,
+ )
+
+ assertThat(latest!!.mode).isEqualTo(StatusBarMode.OPAQUE)
+ }
+
+ @Test
fun statusBarMode_transientShown_semiTransparent() =
testScope.runTest {
val latest by collectLastValue(underTest.statusBarAppearance)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
index a1772e3..510167d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
@@ -10,6 +10,7 @@
import com.android.systemui.jank.interactionJankMonitor
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.data.repository.NotificationLaunchAnimationRepository
@@ -165,7 +166,10 @@
.setSummary(summary)
.addChild(notification.entry)
.build()
- assertSame(summary, notification.entry.parent?.summary)
+
+ val parentSummary = if (notification.entry.parent is GroupEntry)
+ (notification.entry.parent as GroupEntry).summary else null
+ assertSame(summary, parentSummary)
`when`(headsUpManager.isHeadsUpEntry(notificationKey)).thenReturn(false)
`when`(headsUpManager.isHeadsUpEntry(summary.key)).thenReturn(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
new file mode 100644
index 0000000..56cd72e
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.statusbar.notification
+
+import android.util.FloatProperty
+import android.util.Property
+import android.view.View
+import androidx.dynamicanimation.animation.DynamicAnimation
+import androidx.test.annotation.UiThreadTest
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.stack.AnimationProperties
+import com.android.systemui.statusbar.notification.stack.ViewState
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.kotlin.any
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@UiThreadTest
+class PhysicsPropertyAnimatorTest : SysuiTestCase() {
+ private var view: View = View(context)
+ private val effectiveProperty =
+ object : FloatProperty<View>("TEST") {
+ private var _value: Float = 100f
+
+ override fun setValue(view: View, value: Float) {
+ this._value = value
+ }
+
+ override fun get(`object`: View): Float {
+ return _value
+ }
+ }
+ private val property: PhysicsProperty =
+ PhysicsProperty(R.id.scale_x_animator_tag, effectiveProperty)
+ private var finishListener: DynamicAnimation.OnAnimationEndListener? = null
+ private val animationProperties: AnimationProperties = AnimationProperties()
+
+ @Before
+ fun setUp() {
+ finishListener = Mockito.mock(DynamicAnimation.OnAnimationEndListener::class.java)
+ }
+
+ @Test
+ fun testAnimationStarted() {
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ true, /* animate */
+ )
+ Assert.assertTrue(PhysicsPropertyAnimator.isAnimating(view, property))
+ }
+
+ @Test
+ fun testNoAnimationStarted() {
+ PhysicsPropertyAnimator.setProperty(view, property, 200f, animationProperties, false)
+ Assert.assertFalse(PhysicsPropertyAnimator.isAnimating(view, property))
+ }
+
+ @Test
+ fun testEndValueUpdated() {
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ true, /* animate */
+ )
+ Assert.assertEquals(
+ (ViewState.getChildTag(view, property.tag) as PropertyData).finalValue,
+ 200f,
+ )
+ }
+
+ @Test
+ fun testOffset() {
+ effectiveProperty.setValue(view, 100f)
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ true, /* animate */
+ )
+ val propertyData = ViewState.getChildTag(view, property.tag) as PropertyData
+ Assert.assertEquals(propertyData.finalValue, 200f)
+ Assert.assertEquals(propertyData.offset, -100f)
+ }
+
+ @Test
+ fun testValueIsSetUnAnimated() {
+ effectiveProperty.setValue(view, 100f)
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ false, /* animate */
+ )
+ Assert.assertEquals(200f, effectiveProperty[view])
+ }
+
+ @Test
+ fun testAnimationToRightValueUpdated() {
+ effectiveProperty.setValue(view, 100f)
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ true, /* animate */
+ )
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 220f,
+ animationProperties,
+ false, /* animate */
+ )
+ Assert.assertTrue(PhysicsPropertyAnimator.isAnimating(view, property))
+ Assert.assertEquals(120f, effectiveProperty[view])
+ Assert.assertEquals(
+ (ViewState.getChildTag(view, property.tag) as PropertyData).finalValue,
+ 220f,
+ )
+ }
+
+ @Test
+ fun testAnimationToRightValueUpdateAnimated() {
+ effectiveProperty.setValue(view, 100f)
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ true, /* animate */
+ )
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 220f,
+ animationProperties,
+ true, /* animate */
+ )
+ Assert.assertTrue(PhysicsPropertyAnimator.isAnimating(view, property))
+ Assert.assertEquals(100f, effectiveProperty[view])
+ val propertyData = ViewState.getChildTag(view, property.tag) as PropertyData
+ Assert.assertEquals(propertyData.finalValue, 220f)
+ Assert.assertEquals(propertyData.offset, -120f)
+ }
+
+ @Test
+ fun testUsingDelay() {
+ effectiveProperty.setValue(view, 100f)
+ animationProperties.setDelay(200)
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ true, /* animate */
+ )
+ val propertyData = ViewState.getChildTag(view, property.tag) as PropertyData
+ Assert.assertNotNull(propertyData.delayRunnable)
+ Assert.assertFalse(propertyData.animator?.isRunning ?: true)
+ }
+
+ @Test
+ fun testUsingListener() {
+ PhysicsPropertyAnimator.setProperty(
+ view,
+ property,
+ 200f,
+ animationProperties,
+ true,
+ finishListener,
+ )
+ val propertyData = ViewState.getChildTag(view, property.tag) as PropertyData
+ propertyData.animator?.cancel()
+ Mockito.verify(finishListener!!).onAnimationEnd(any(), any(), any(), any())
+ }
+
+ @Test
+ fun testUsingListenerProperties() {
+ val finishListener2 = Mockito.mock(DynamicAnimation.OnAnimationEndListener::class.java)
+ val animationProperties: AnimationProperties =
+ object : AnimationProperties() {
+ override fun getAnimationEndListener(
+ property: Property<*, *>?
+ ): DynamicAnimation.OnAnimationEndListener {
+ return finishListener2
+ }
+ }
+ PhysicsPropertyAnimator.setProperty(view, property, 200f, animationProperties, true)
+ val propertyData = ViewState.getChildTag(view, property.tag) as PropertyData
+ propertyData.animator?.cancel()
+ Mockito.verify(finishListener2).onAnimationEnd(any(), any(), any(), any())
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/BundleEntryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/BundleEntryTest.kt
index 426af26..83e26c4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/BundleEntryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/BundleEntryTest.kt
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.collection
+import android.app.Notification
+import android.graphics.Color
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import android.testing.TestableLooper.RunWithLooper
@@ -72,4 +74,35 @@
fun getKey_adapter() {
assertThat(underTest.entryAdapter.key).isEqualTo("key")
}
+
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ fun isClearable_adapter() {
+ assertThat(underTest.entryAdapter.isClearable).isTrue()
+ }
+
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ fun getSummarization_adapter() {
+ assertThat(underTest.entryAdapter.summarization).isNull()
+ }
+
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ fun getContrastedColor_adapter() {
+ assertThat(underTest.entryAdapter.getContrastedColor(context, false, Color.WHITE))
+ .isEqualTo(Notification.COLOR_DEFAULT)
+ }
+
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ fun canPeek_adapter() {
+ assertThat(underTest.entryAdapter.canPeek()).isFalse()
+ }
+
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ fun getWhen_adapter() {
+ assertThat(underTest.entryAdapter.`when`).isEqualTo(0)
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
similarity index 89%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index 19d1224..1f5c672 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -163,9 +163,10 @@
@Test
public void testIsExemptFromDndVisualSuppression_media() {
+ MediaSession session = new MediaSession(mContext, "test");
Notification.Builder n = new Notification.Builder(mContext, "")
.setStyle(new Notification.MediaStyle()
- .setMediaSession(mock(MediaSession.Token.class)))
+ .setMediaSession(session.getSessionToken()))
.setSmallIcon(R.drawable.ic_person)
.setContentTitle("Title")
.setContentText("Text");
@@ -593,6 +594,76 @@
assertThat(entry.getEntryAdapter().getGroupRoot()).isEqualTo(parent.getEntryAdapter());
}
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ public void isClearable_adapter() {
+ ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+ Notification notification = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .build();
+
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_NAME)
+ .setOpPkg(TEST_PACKAGE_NAME)
+ .setUid(TEST_UID)
+ .setChannel(mChannel)
+ .setId(mId++)
+ .setNotification(notification)
+ .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+ .build();
+ entry.setRow(row);
+
+ assertThat(entry.getEntryAdapter().isClearable()).isEqualTo(entry.isClearable());
+ }
+
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ public void getSummarization_adapter() {
+ ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+ Notification notification = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .build();
+
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_NAME)
+ .setOpPkg(TEST_PACKAGE_NAME)
+ .setUid(TEST_UID)
+ .setChannel(mChannel)
+ .setId(mId++)
+ .setNotification(notification)
+ .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+ .build();
+ Ranking ranking = new RankingBuilder(entry.getRanking())
+ .setSummarization("hello")
+ .build();
+ entry.setRanking(ranking);
+ entry.setRow(row);
+
+ assertThat(entry.getEntryAdapter().getSummarization()).isEqualTo("hello");
+ }
+
+ @Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ public void getIcons_adapter() {
+ ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+ Notification notification = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .build();
+
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_NAME)
+ .setOpPkg(TEST_PACKAGE_NAME)
+ .setUid(TEST_UID)
+ .setChannel(mChannel)
+ .setId(mId++)
+ .setNotification(notification)
+ .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+ .build();
+ entry.setRow(row);
+
+ assertThat(entry.getEntryAdapter().getIcons()).isEqualTo(entry.getIcons());
+ }
+
private Notification.Action createContextualAction(String title) {
return new Notification.Action.Builder(
Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt
index 7781df1..43cb957 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt
@@ -16,8 +16,11 @@
package com.android.systemui.statusbar.notification.collection.coordinator
import android.app.Notification
+import android.app.Notification.MediaStyle
+import android.media.session.MediaSession
import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
+import android.service.notification.StatusBarNotification
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.dumpManager
@@ -36,6 +39,7 @@
import com.android.systemui.scene.data.repository.setTransition
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -217,6 +221,16 @@
mock<ExpandableNotificationRow>().apply {
whenever(isMediaRow).thenReturn(true)
}
+ sbn = SbnBuilder().setNotification(
+ Notification.Builder(context, "channel").setStyle(
+ MediaStyle().setMediaSession(
+ MediaSession(
+ context,
+ "tag"
+ ).sessionToken
+ )
+ ).build()
+ ).build()
}
collectionListener.onEntryAdded(fakeEntry)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
index 99bd4fc..d9c9177 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.getAttachState
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
@@ -409,7 +410,7 @@
): NotifSection {
return NotifSection(object : NotifSectioner("Section $index (bucket=$bucket)", bucket) {
- override fun isInSection(entry: ListEntry?): Boolean {
+ override fun isInSection(entry: PipelineEntry?): Boolean {
throw NotImplementedError("This should never be called")
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
index e6fbc72..4a05804 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
@@ -24,6 +24,7 @@
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
@@ -40,6 +41,7 @@
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions
+import java.nio.channels.Pipe
@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -198,7 +200,7 @@
)
private class FakeNotifViewRenderer : NotifViewRenderer {
- override fun onRenderList(notifList: List<ListEntry>) {}
+ override fun onRenderList(notifList: List<PipelineEntry>) {}
override fun getGroupController(group: GroupEntry): NotifGroupController = mock()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
index a3fde5a..216fd2d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
@@ -39,18 +39,24 @@
import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When
import com.android.systemui.statusbar.notification.row.RowImageInflater
import com.android.systemui.testKosmos
+import com.android.systemui.util.time.fakeSystemClock
+import com.android.systemui.util.time.systemClock
import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.minutes
import org.junit.Test
import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
- private val kosmos = testKosmos()
+ private val kosmos = testKosmos().apply { systemClock = fakeSystemClock }
private val underTest = kosmos.promotedNotificationContentExtractor
+ private val systemClock = kosmos.fakeSystemClock
private val rowImageInflater = RowImageInflater.newInstance(previousIndex = null)
private val imageModelProvider by lazy { rowImageInflater.useForContentModel() }
@@ -177,7 +183,176 @@
@Test
@EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
- fun extractsContent_fromBaseStyle() {
+ fun extractTime_none() {
+ assertExtractedTime(hasTime = false, hasChronometer = false, expected = ExpectedTime.Null)
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_basicTimeNow() {
+ assertExtractedTime(
+ hasTime = true,
+ hasChronometer = false,
+ whenOffset = Duration.ZERO,
+ expected = ExpectedTime.Time,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_basicTimePast() {
+ assertExtractedTime(
+ hasTime = true,
+ hasChronometer = false,
+ whenOffset = (-5).minutes,
+ expected = ExpectedTime.Time,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_basicTimeFuture() {
+ assertExtractedTime(
+ hasTime = true,
+ hasChronometer = false,
+ whenOffset = 5.minutes,
+ expected = ExpectedTime.Time,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_countUpNow() {
+ assertExtractedTime(
+ hasTime = false,
+ hasChronometer = true,
+ isCountDown = false,
+ whenOffset = Duration.ZERO,
+ expected = ExpectedTime.CountUp,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_countUpPast() {
+ assertExtractedTime(
+ hasTime = false,
+ hasChronometer = true,
+ isCountDown = false,
+ whenOffset = (-5).minutes,
+ expected = ExpectedTime.CountUp,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_countUpFuture() {
+ assertExtractedTime(
+ hasTime = false,
+ hasChronometer = true,
+ isCountDown = false,
+ whenOffset = 5.minutes,
+ expected = ExpectedTime.CountUp,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_countDownNow() {
+ assertExtractedTime(
+ hasTime = false,
+ hasChronometer = true,
+ isCountDown = true,
+ whenOffset = Duration.ZERO,
+ expected = ExpectedTime.CountDown,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_countDownPast() {
+ assertExtractedTime(
+ hasTime = false,
+ hasChronometer = true,
+ isCountDown = true,
+ whenOffset = (-5).minutes,
+ expected = ExpectedTime.CountDown,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_countDownFuture() {
+ assertExtractedTime(
+ hasTime = false,
+ hasChronometer = true,
+ isCountDown = true,
+ whenOffset = 5.minutes,
+ expected = ExpectedTime.CountDown,
+ )
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractTime_prefersChronometerToWhen() {
+ assertExtractedTime(hasTime = true, hasChronometer = true, expected = ExpectedTime.CountUp)
+ }
+
+ private enum class ExpectedTime {
+ Null,
+ Time,
+ CountUp,
+ CountDown,
+ }
+
+ private fun assertExtractedTime(
+ hasTime: Boolean = false,
+ hasChronometer: Boolean = false,
+ isCountDown: Boolean = false,
+ whenOffset: Duration = Duration.ZERO,
+ expected: ExpectedTime,
+ ) {
+ // Set the two timebases to different (arbitrary) numbers, so we can verify whether the
+ // extractor is doing the timebase adjustment correctly.
+ systemClock.setCurrentTimeMillis(1_739_570_992_579L)
+ systemClock.setElapsedRealtime(1_380_967_080L)
+
+ val whenCurrentTime = systemClock.currentTimeMillis() + whenOffset.inWholeMilliseconds
+ val whenElapsedRealtime = systemClock.elapsedRealtime() + whenOffset.inWholeMilliseconds
+
+ val entry = createEntry {
+ setShowWhen(hasTime)
+ setUsesChronometer(hasChronometer)
+ setChronometerCountDown(isCountDown)
+ setWhen(whenCurrentTime)
+ }
+
+ val content = extractContent(entry)
+
+ assertThat(content).isNotNull()
+
+ when (expected) {
+ ExpectedTime.Null -> assertThat(content?.time).isNull()
+
+ ExpectedTime.Time -> {
+ val actual = content?.time as? When.Time
+ assertThat(actual).isNotNull()
+ assertThat(actual?.currentTimeMillis).isEqualTo(whenCurrentTime)
+ }
+
+ ExpectedTime.CountDown,
+ ExpectedTime.CountUp -> {
+ val actual = content?.time as? When.Chronometer
+ assertThat(actual).isNotNull()
+ assertThat(actual?.elapsedRealtimeMillis).isEqualTo(whenElapsedRealtime)
+ assertThat(actual?.isCountDown).isEqualTo(expected == ExpectedTime.CountDown)
+ }
+ }
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractContent_fromBaseStyle() {
val entry = createEntry { setStyle(null) }
val content = extractContent(entry)
@@ -188,7 +363,7 @@
@Test
@EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
- fun extractsContent_fromBigPictureStyle() {
+ fun extractContent_fromBigPictureStyle() {
val entry = createEntry { setStyle(BigPictureStyle()) }
val content = extractContent(entry)
@@ -261,7 +436,7 @@
@Test
@EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
- fun extractsContent_fromOldProgressDeterminate() {
+ fun extractContent_fromOldProgressDeterminate() {
val entry = createEntry {
setProgress(TEST_PROGRESS_MAX, TEST_PROGRESS, /* indeterminate= */ false)
}
@@ -282,7 +457,7 @@
@Test
@EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
- fun extractsContent_fromOldProgressIndeterminate() {
+ fun extractContent_fromOldProgressIndeterminate() {
val entry = createEntry {
setProgress(TEST_PROGRESS_MAX, TEST_PROGRESS, /* indeterminate= */ true)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.kt
index 4c1f4f1..1b8d64d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.kt
@@ -80,9 +80,6 @@
import com.android.systemui.testKosmos
import com.android.systemui.util.kotlin.JavaAdapter
import com.android.systemui.wmshell.BubblesManager
-import java.util.Optional
-import kotlin.test.assertNotNull
-import kotlin.test.fail
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
@@ -110,6 +107,9 @@
import org.mockito.kotlin.whenever
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
+import java.util.Optional
+import kotlin.test.assertNotNull
+import kotlin.test.fail
/** Tests for [NotificationGutsManager]. */
@SmallTest
@@ -509,7 +509,6 @@
.setImportance(NotificationManager.IMPORTANCE_HIGH)
.build()
- whenever(row.isNonblockable).thenReturn(false)
whenever(highPriorityProvider.isHighPriority(entry)).thenReturn(true)
val statusBarNotification = entry.sbn
gutsManager.initializeNotificationInfo(row, notificationInfoView)
@@ -546,7 +545,6 @@
NotificationEntryHelper.modifyRanking(row.entry)
.setUserSentiment(NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE)
.build()
- whenever(row.isNonblockable).thenReturn(false)
val statusBarNotification = row.entry.sbn
val entry = row.entry
@@ -586,7 +584,6 @@
NotificationEntryHelper.modifyRanking(row.entry)
.setUserSentiment(NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE)
.build()
- whenever(row.isNonblockable).thenReturn(false)
val statusBarNotification = row.entry.sbn
val entry = row.entry
@@ -641,7 +638,7 @@
): NotificationMenuRowPlugin.MenuItem {
val menuRow: NotificationMenuRowPlugin =
NotificationMenuRow(mContext, peopleNotificationIdentifier)
- menuRow.createMenu(row, row.entry.sbn)
+ menuRow.createMenu(row)
val menuItem = menuRow.getLongpressMenuItem(mContext)
assertNotNull(menuItem)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index 027e899..9fdfca1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -72,7 +72,7 @@
public void testAttachDetach() {
NotificationMenuRowPlugin row =
new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
ViewUtils.attachView(row.getMenuView());
TestableLooper.get(this).processAllMessages();
ViewUtils.detachView(row.getMenuView());
@@ -83,9 +83,9 @@
public void testRecreateMenu() {
NotificationMenuRowPlugin row =
new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
assertTrue(row.getMenuView() != null);
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
assertTrue(row.getMenuView() != null);
}
@@ -103,7 +103,7 @@
Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 0);
NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
ViewGroup container = (ViewGroup) row.getMenuView();
// noti blocking
@@ -116,7 +116,7 @@
Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 0);
NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
ViewGroup container = (ViewGroup) row.getMenuView();
// just for noti blocking
@@ -129,7 +129,7 @@
Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 0);
NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
ViewGroup container = (ViewGroup) row.getMenuView();
// one for snooze and one for noti blocking
@@ -142,7 +142,7 @@
Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 1);
NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
ViewGroup container = (ViewGroup) row.getMenuView();
// Clear menu
@@ -417,7 +417,7 @@
public void testOnTouchMove() {
NotificationMenuRow row = Mockito.spy(
new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
- row.createMenu(mRow, null);
+ row.createMenu(mRow);
doReturn(50f).when(row).getDismissThreshold();
doReturn(true).when(row).canBeDismissed();
doReturn(mView).when(row).getMenuView();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapperTest.kt
index 9a6a699..081f52c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapperTest.kt
@@ -135,6 +135,7 @@
.thenReturn(mock())
whenever(requireViewById<View>(R.id.app_name_text)).thenReturn(mock())
whenever(requireViewById<View>(R.id.conversation_text)).thenReturn(mock())
+ whenever(requireViewById<View>(R.id.title)).thenReturn(mock())
}
return mockView
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt
index e5cb0fb..885e71e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt
@@ -32,6 +32,7 @@
import com.google.android.msdl.data.model.MSDLToken
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -49,7 +50,7 @@
private val sectionsManager = mock<NotificationSectionsManager>()
private val msdlPlayer = kosmos.fakeMSDLPlayer
private var canRowBeDismissed = true
- private var magneticAnimationsCancelled = false
+ private var magneticAnimationsCancelled = MutableList(childrenNumber) { false }
private val underTest = kosmos.magneticNotificationRowManagerImpl
@@ -64,8 +65,10 @@
NotificationTestHelper(mContext, mDependency, kosmos.testableLooper, featureFlags)
children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
swipedRow = children.attachedChildren[childrenNumber / 2]
- configureMagneticRowListener(swipedRow)
- magneticAnimationsCancelled = false
+ children.attachedChildren.forEachIndexed { index, row ->
+ row.magneticRowListener = row.magneticRowListener.asTestableListener(index)
+ }
+ magneticAnimationsCancelled.replaceAll { false }
}
@Test
@@ -259,14 +262,14 @@
underTest.onMagneticInteractionEnd(swipedRow, velocity = null)
// THEN magnetic animations are cancelled
- assertThat(magneticAnimationsCancelled).isTrue()
+ assertThat(magneticAnimationsCancelled[childrenNumber / 2]).isTrue()
}
@Test
fun onMagneticInteractionEnd_forMagneticNeighbor_cancelsMagneticAnimations() =
kosmos.testScope.runTest {
- val neighborRow = children.attachedChildren[childrenNumber / 2 - 1]
- configureMagneticRowListener(neighborRow)
+ val neighborIndex = childrenNumber / 2 - 1
+ val neighborRow = children.attachedChildren[neighborIndex]
// GIVEN that targets are set
setTargets()
@@ -275,9 +278,15 @@
underTest.onMagneticInteractionEnd(neighborRow, null)
// THEN magnetic animations are cancelled
- assertThat(magneticAnimationsCancelled).isTrue()
+ assertThat(magneticAnimationsCancelled[neighborIndex]).isTrue()
}
+ @After
+ fun tearDown() {
+ // We reset the manager so that all MagneticRowListener can cancel all animations
+ underTest.reset()
+ }
+
private fun setDetachedState() {
val threshold = 100f
underTest.setSwipeThresholdPx(threshold)
@@ -302,27 +311,33 @@
originalTranslation *
MagneticNotificationRowManagerImpl.MAGNETIC_REDUCTION
- private fun configureMagneticRowListener(row: ExpandableNotificationRow) {
- val listener =
- object : MagneticRowListener {
- override fun setMagneticTranslation(translation: Float) {
- row.translation = translation
- }
-
- override fun triggerMagneticForce(
- endTranslation: Float,
- springForce: SpringForce,
- startVelocity: Float,
- ) {}
-
- override fun cancelMagneticAnimations() {
- magneticAnimationsCancelled = true
- }
-
- override fun cancelTranslationAnimations() {}
-
- override fun canRowBeDismissed(): Boolean = canRowBeDismissed
+ private fun MagneticRowListener.asTestableListener(rowIndex: Int): MagneticRowListener {
+ val delegate = this
+ return object : MagneticRowListener {
+ override fun setMagneticTranslation(translation: Float) {
+ delegate.setMagneticTranslation(translation)
}
- row.magneticRowListener = listener
+
+ override fun triggerMagneticForce(
+ endTranslation: Float,
+ springForce: SpringForce,
+ startVelocity: Float,
+ ) {
+ delegate.triggerMagneticForce(endTranslation, springForce, startVelocity)
+ }
+
+ override fun cancelMagneticAnimations() {
+ magneticAnimationsCancelled[rowIndex] = true
+ delegate.cancelMagneticAnimations()
+ }
+
+ override fun cancelTranslationAnimations() {
+ delegate.cancelTranslationAnimations()
+ }
+
+ override fun canRowBeDismissed(): Boolean {
+ return canRowBeDismissed
+ }
+ }
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
index 3a77d82..52f903e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
@@ -31,7 +31,7 @@
fun testUpdateClipping_updatesClipHeight() {
assertTrue(mediaContainerView.clipHeight == 0)
- mediaContainerView.actualHeight = 10
+ mediaContainerView.setFinalActualHeight(10)
mediaContainerView.updateClipping()
assertTrue(mediaContainerView.clipHeight == 10)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
index 51de9d5..87cd728 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
@@ -14,6 +14,7 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.whenever
/** Tests for {@link NotificationTargetsHelper}. */
@SmallTest
@@ -21,7 +22,7 @@
@RunWithLooper
class NotificationTargetsHelperTest : SysuiTestCase() {
private val featureFlags = FakeFeatureFlagsClassic()
- lateinit var notificationTestHelper: NotificationTestHelper
+ private lateinit var notificationTestHelper: NotificationTestHelper
private val sectionsManager: NotificationSectionsManager = mock()
private val stackScrollLayout: NotificationStackScrollLayout = mock()
@@ -107,7 +108,12 @@
// THEN all the views that surround it become targets with the swiped view at the middle
val actual =
notificationTargetsHelper()
- .findMagneticTargets(viewSwiped = swiped, stackScrollLayout = stackScrollLayout, 5)
+ .findMagneticTargets(
+ viewSwiped = swiped,
+ stackScrollLayout = stackScrollLayout,
+ sectionsManager,
+ totalMagneticTargets = 5,
+ )
assertMagneticTargetsForChildren(actual, children.attachedChildren)
}
@@ -123,7 +129,12 @@
// to the left
val actual =
notificationTargetsHelper()
- .findMagneticTargets(viewSwiped = swiped, stackScrollLayout = stackScrollLayout, 5)
+ .findMagneticTargets(
+ viewSwiped = swiped,
+ stackScrollLayout = stackScrollLayout,
+ sectionsManager,
+ totalMagneticTargets = 5,
+ )
val expectedRows =
listOf(null, null, swiped, children.attachedChildren[1], children.attachedChildren[2])
assertMagneticTargetsForChildren(actual, expectedRows)
@@ -141,7 +152,12 @@
// to the right
val actual =
notificationTargetsHelper()
- .findMagneticTargets(viewSwiped = swiped, stackScrollLayout = stackScrollLayout, 5)
+ .findMagneticTargets(
+ viewSwiped = swiped,
+ stackScrollLayout = stackScrollLayout,
+ sectionsManager,
+ totalMagneticTargets = 5,
+ )
val expectedRows =
listOf(
children.attachedChildren[childrenNumber - 3],
@@ -153,6 +169,54 @@
assertMagneticTargetsForChildren(actual, expectedRows)
}
+ @Test
+ fun findMagneticTargets_doesNotCrossSectionAtTop() {
+ val childrenNumber = 5
+ val children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
+
+ // WHEN the second child is swiped and the first one begins a new section
+ val swiped = children.attachedChildren[1]
+ whenever(sectionsManager.beginsSection(swiped, children.attachedChildren[0])).then { true }
+
+ // THEN the neighboring views become targets, with the swiped view at the middle and nulls
+ // to the left since the top view relative to swiped begins a new section
+ val actual =
+ notificationTargetsHelper()
+ .findMagneticTargets(
+ viewSwiped = swiped,
+ stackScrollLayout = stackScrollLayout,
+ sectionsManager,
+ totalMagneticTargets = 5,
+ )
+ val expectedRows =
+ listOf(null, null, swiped, children.attachedChildren[2], children.attachedChildren[3])
+ assertMagneticTargetsForChildren(actual, expectedRows)
+ }
+
+ @Test
+ fun findMagneticTargets_doesNotCrossSectionAtBottom() {
+ val childrenNumber = 5
+ val children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
+
+ // WHEN the fourth child is swiped and the last one begins a new section
+ val swiped = children.attachedChildren[3]
+ whenever(sectionsManager.beginsSection(children.attachedChildren[4], swiped)).then { true }
+
+ // THEN the neighboring views become targets, with the swiped view at the middle and nulls
+ // to the right since the bottom view relative to swiped begins a new section
+ val actual =
+ notificationTargetsHelper()
+ .findMagneticTargets(
+ viewSwiped = swiped,
+ stackScrollLayout = stackScrollLayout,
+ sectionsManager,
+ totalMagneticTargets = 5,
+ )
+ val expectedRows =
+ listOf(children.attachedChildren[1], children.attachedChildren[2], swiped, null, null)
+ assertMagneticTargetsForChildren(actual, expectedRows)
+ }
+
private fun assertMagneticTargetsForChildren(
targets: List<MagneticRowListener?>,
children: List<ExpandableNotificationRow?>,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 01ba4df..7603eec 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -146,6 +146,20 @@
}
@Test
+ @EnableSceneContainer
+ fun resetViewStates_defaultHun_hasShadow() {
+ val headsUpTop = 200f
+ ambientState.headsUpTop = headsUpTop
+
+ whenever(notificationRow.isPinned).thenReturn(true)
+ whenever(notificationRow.isHeadsUp).thenReturn(true)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, 0)
+
+ assertThat(notificationRow.viewState.zTranslation).isGreaterThan(baseZ)
+ }
+
+ @Test
@DisableSceneContainer
fun resetViewStates_defaultHunWhenShadeIsOpening_yTranslationIsInset() {
whenever(notificationRow.isPinned).thenReturn(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
index e4dd29a..67415de 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
@@ -81,7 +81,7 @@
stackStateAnimator.startAnimationForEvents(arrayListOf(event), 0)
- verify(view).setActualHeight(VIEW_HEIGHT, false)
+ verify(view).setFinalActualHeight(VIEW_HEIGHT)
verify(view, description("should animate from the top")).translationY = expectedStartY
verify(view)
.performAddAnimation(
@@ -104,7 +104,7 @@
stackStateAnimator.startAnimationForEvents(arrayListOf(event), 0)
- verify(view).setActualHeight(VIEW_HEIGHT, false)
+ verify(view).setFinalActualHeight(VIEW_HEIGHT)
verify(view, description("should animate from the bottom")).translationY = expectedStartY
verify(view)
.performAddAnimation(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
index e493420..ef415c9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
@@ -16,21 +16,28 @@
package com.android.systemui.statusbar.notification.stack
+import android.animation.ValueAnimator
+import android.view.View
+import androidx.test.annotation.UiThreadTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.assertDoesNotLogWtf
import com.android.systemui.log.assertLogsWtf
-import kotlin.math.log2
-import kotlin.math.sqrt
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.TAG_ANIMATOR_TRANSLATION_Y
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.Y_TRANSLATION
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
+import kotlin.math.log2
+import kotlin.math.sqrt
@RunWith(AndroidJUnit4::class)
@SmallTest
+@UiThreadTest
class ViewStateTest : SysuiTestCase() {
- private val viewState = ViewState()
+ private val viewState = ViewState(true /* usePhysicsForMovement */)
@Suppress("DIVISION_BY_ZERO")
@Test
@@ -64,4 +71,37 @@
assertLogsWtf { viewState.scaleY = Float.POSITIVE_INFINITY * 0 }
Assert.assertEquals(viewState.scaleY, 0.25f)
}
+
+ @Test
+ fun testUsingPhysics() {
+ val animatedView = View(context)
+ viewState.setUsePhysicsForMovement(true)
+ viewState.applyToView(animatedView)
+ viewState.yTranslation = 100f
+ val animationFilter = AnimationFilter().animateY()
+ val animationProperties = object : AnimationProperties() {
+ override fun getAnimationFilter(): AnimationFilter {
+ return animationFilter
+ }
+ }
+ viewState.animateTo(animatedView, animationProperties)
+ Assert.assertTrue(PhysicsPropertyAnimator.isAnimating(animatedView, Y_TRANSLATION))
+ }
+
+ @Test
+ fun testNotUsingPhysics() {
+ val animatedView = View(context)
+ viewState.setUsePhysicsForMovement(false)
+ viewState.applyToView(animatedView)
+ viewState.yTranslation = 100f
+ val animationFilter = AnimationFilter().animateY()
+ val animationProperties = object : AnimationProperties() {
+ override fun getAnimationFilter(): AnimationFilter {
+ return animationFilter
+ }
+ }
+ viewState.animateTo(animatedView, animationProperties)
+ val tag = animatedView.getTag(TAG_ANIMATOR_TRANSLATION_Y)
+ Assert.assertTrue(tag is ValueAnimator)
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 21297e3..c630a1c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -17,14 +17,15 @@
package com.android.systemui.statusbar.notification.stack.ui.viewmodel
+import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
-import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.common.shared.model.NotificationContainerBounds
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
-import com.android.systemui.communal.data.repository.communalSceneRepository
+import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
@@ -54,11 +55,14 @@
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
import com.android.systemui.keyguard.ui.viewmodel.aodBurnInViewModel
import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.scene.data.repository.Idle
import com.android.systemui.scene.data.repository.Transition
import com.android.systemui.scene.data.repository.setTransition
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
@@ -125,7 +129,6 @@
kosmos.sharedNotificationContainerInteractor
}
private val largeScreenHeaderHelper by lazy { kosmos.mockLargeScreenHeaderHelper }
- private val communalSceneRepository by lazy { kosmos.communalSceneRepository }
lateinit var underTest: SharedNotificationContainerViewModel
@@ -591,6 +594,25 @@
}
@Test
+ @DisableSceneContainer
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun isOnLockscreenFalseWhenCommunalShowing() =
+ kosmos.runTest {
+ val isOnLockscreen by collectLastValue(underTest.isOnLockscreen)
+
+ setTransition(
+ sceneTransition = Idle(Scenes.Bouncer),
+ stateTransition = TransitionStep(from = LOCKSCREEN, to = PRIMARY_BOUNCER),
+ )
+ assertThat(isOnLockscreen).isTrue()
+
+ testScope.showCommunalScene()
+
+ // If bouncer is showing over the hub, it should not be considered on lockscreen
+ assertThat(isOnLockscreen).isFalse()
+ }
+
+ @Test
fun isOnLockscreenWithoutShade() =
testScope.runTest {
val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade)
@@ -1472,20 +1494,24 @@
}
private fun TestScope.showCommunalScene() {
- val transitionState =
- MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(CommunalScenes.Communal)
- )
- communalSceneRepository.setTransitionState(transitionState)
+ val targetScene =
+ if (SceneContainerFlag.isEnabled) {
+ Scenes.Communal
+ } else {
+ CommunalScenes.Communal
+ }
+ kosmos.communalSceneInteractor.changeScene(targetScene, "test")
runCurrent()
}
private fun TestScope.hideCommunalScene() {
- val transitionState =
- MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(CommunalScenes.Blank)
- )
- communalSceneRepository.setTransitionState(transitionState)
+ val targetScene =
+ if (SceneContainerFlag.isEnabled) {
+ Scenes.Lockscreen
+ } else {
+ CommunalScenes.Blank
+ }
+ kosmos.communalSceneInteractor.changeScene(targetScene, "test")
runCurrent()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt
index c48287c..bab349a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone.ongoingcall.domain.interactor
import android.app.PendingIntent
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -31,9 +30,8 @@
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.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.addOngoingCallState
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallTestHelper.removeOngoingCallState
@@ -51,10 +49,9 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-@EnableFlags(StatusBarChipsModernization.FLAG_NAME)
+@EnableChipsModernization
class OngoingCallInteractorTest : SysuiTestCase() {
private val kosmos = Kosmos().useUnconfinedTestDispatcher()
- private val repository = kosmos.activeNotificationListRepository
private val underTest = kosmos.ongoingCallInteractor
@Before
@@ -69,18 +66,19 @@
}
@Test
- fun ongoingCallNotification_setsAllFields() =
+ fun ongoingCallNotification_setsAllFields_withAppHidden() =
kosmos.runTest {
val latest by collectLastValue(underTest.ongoingCallState)
// Set up notification with icon view and intent
+ val key = "promotedCall"
+ val startTimeMs = 1000L
val testIconView: StatusBarIconView = mock()
val testIntent: PendingIntent = mock()
- val testPromotedContent =
- PromotedNotificationContentModel.Builder("promotedCall").build()
+ val testPromotedContent = PromotedNotificationContentModel.Builder(key).build()
addOngoingCallState(
- key = "promotedCall",
- startTimeMs = 1000L,
+ key = key,
+ startTimeMs = startTimeMs,
statusBarChipIconView = testIconView,
contentIntent = testIntent,
promotedContent = testPromotedContent,
@@ -89,8 +87,41 @@
// Verify model is InCall and has the correct icon, intent, and promoted content.
assertThat(latest).isInstanceOf(OngoingCallModel.InCall::class.java)
val model = latest as OngoingCallModel.InCall
+ assertThat(model.startTimeMs).isEqualTo(startTimeMs)
assertThat(model.notificationIconView).isSameInstanceAs(testIconView)
assertThat(model.intent).isSameInstanceAs(testIntent)
+ assertThat(model.notificationKey).isEqualTo(key)
+ assertThat(model.promotedContent).isSameInstanceAs(testPromotedContent)
+ }
+
+ @Test
+ fun ongoingCallNotification_setsAllFields_withAppVisible() =
+ kosmos.runTest {
+ kosmos.activityManagerRepository.fake.startingIsAppVisibleValue = true
+ val latest by collectLastValue(underTest.ongoingCallState)
+
+ // Set up notification with icon view and intent
+ val key = "promotedCall"
+ val startTimeMs = 1000L
+ val testIconView: StatusBarIconView = mock()
+ val testIntent: PendingIntent = mock()
+ val testPromotedContent = PromotedNotificationContentModel.Builder(key).build()
+ addOngoingCallState(
+ key = key,
+ startTimeMs = startTimeMs,
+ statusBarChipIconView = testIconView,
+ contentIntent = testIntent,
+ promotedContent = testPromotedContent,
+ )
+
+ // Verify model is InCallWithVisibleApp and has the correct icon, intent, and promoted
+ // content.
+ assertThat(latest).isInstanceOf(OngoingCallModel.InCallWithVisibleApp::class.java)
+ val model = latest as OngoingCallModel.InCallWithVisibleApp
+ assertThat(model.startTimeMs).isEqualTo(startTimeMs)
+ assertThat(model.notificationIconView).isSameInstanceAs(testIconView)
+ assertThat(model.intent).isSameInstanceAs(testIntent)
+ assertThat(model.notificationKey).isEqualTo(key)
assertThat(model.promotedContent).isSameInstanceAs(testPromotedContent)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index 4009144..8c70da7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -719,7 +719,6 @@
job.cancel()
}
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@Test
fun satBasedIcon_isUsedWhenNonTerrestrial() =
testScope.runTest {
@@ -733,7 +732,6 @@
assertThat(latest).isInstanceOf(SignalIconModel.Satellite::class.java)
}
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
// See b/346904529 for more context
@@ -756,10 +754,7 @@
assertThat(latest!!.level).isEqualTo(4)
}
- @EnableFlags(
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
- )
+ @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
// See b/346904529 for more context
fun satBasedIcon_doesNotInflateSignalStrength_flagOn() =
@@ -781,7 +776,6 @@
assertThat(latest!!.level).isEqualTo(4)
}
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
fun satBasedIcon_usesPrimaryLevel_flagOff() =
@@ -799,10 +793,7 @@
assertThat(latest!!.level).isEqualTo(4)
}
- @EnableFlags(
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
- )
+ @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
fun satBasedIcon_usesSatelliteLevel_flagOn() =
testScope.runTest {
@@ -823,7 +814,6 @@
* Context (b/377518113), this test will not be needed after FLAG_CARRIER_ROAMING_NB_IOT_NTN is
* rolled out. The new API should report 0 automatically if not in service.
*/
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
fun satBasedIcon_reportsLevelZeroWhenOutOfService() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index d17abd7..6066a38 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
import android.os.ParcelUuid
+import android.platform.test.annotations.EnableFlags
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING
import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
@@ -33,9 +34,12 @@
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.core.NewStatusBarIcons
+import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fake
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.mobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.mobileConnectionsRepositoryLogbufferName
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
@@ -897,6 +901,71 @@
assertThat(latest).isEqualTo(2)
}
+ @Test
+ @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ fun isStackable_tracksNumberOfSubscriptions() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.isStackable)
+
+ connectionsRepository.setSubscriptions(listOf(SUB_1))
+ assertThat(latest).isFalse()
+
+ connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
+ assertThat(latest).isTrue()
+
+ connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2, SUB_3_OPP))
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ fun isStackable_checksForTerrestrialConnections() =
+ kosmos.runTest {
+ val exclusivelyNonTerrestrialSub =
+ SubscriptionModel(
+ isExclusivelyNonTerrestrial = true,
+ subscriptionId = 5,
+ carrierName = "Carrier 5",
+ profileClass = PROFILE_CLASS_UNSET,
+ )
+
+ val latest by collectLastValue(underTest.isStackable)
+
+ connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
+ assertThat(latest).isTrue()
+
+ connectionsRepository.setSubscriptions(listOf(SUB_1, exclusivelyNonTerrestrialSub))
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ fun isStackable_checksForNumberOfBars() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.isStackable)
+
+ // Number of levels is the same for both
+ connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
+ setNumberOfLevelsForSubId(SUB_1_ID, 5)
+ setNumberOfLevelsForSubId(SUB_2_ID, 5)
+
+ assertThat(latest).isTrue()
+
+ // Change the number of levels to be different than SUB_2
+ setNumberOfLevelsForSubId(SUB_1_ID, 6)
+
+ assertThat(latest).isFalse()
+ }
+
+ private fun setNumberOfLevelsForSubId(subId: Int, numberOfLevels: Int) {
+ with(kosmos) {
+ (fakeMobileConnectionsRepository.getRepoForSubId(subId)
+ as FakeMobileConnectionRepository)
+ .numberOfLevels
+ .value = numberOfLevels
+ }
+ }
+
/**
* Convenience method for creating a pair of subscriptions to test the filteredSubscriptions
* flow.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index 61ed04c..8ea888e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -856,7 +856,6 @@
.isEqualTo(Icon.Resource(R.drawable.mobile_network_type_background, null))
}
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@Test
fun nonTerrestrial_defaultProperties() =
testScope.runTest {
@@ -877,7 +876,6 @@
assertThat(activityContainerVisible).isFalse()
}
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@Test
fun nonTerrestrial_ignoresDefaultProperties() =
testScope.runTest {
@@ -905,7 +903,6 @@
assertThat(activityContainerVisible).isFalse()
}
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
fun nonTerrestrial_usesSatelliteIcon_flagOff() =
@@ -940,10 +937,7 @@
assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)
}
- @EnableFlags(
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
- )
+ @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
fun nonTerrestrial_usesSatelliteIcon_flagOn() =
testScope.runTest {
@@ -972,7 +966,6 @@
assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)
}
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
fun satelliteIcon_ignoresInflateSignalStrength_flagOff() =
@@ -1010,10 +1003,7 @@
assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)
}
- @EnableFlags(
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
- com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
- )
+ @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
@Test
fun satelliteIcon_ignoresInflateSignalStrength_flagOn() =
testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelTest.kt
new file mode 100644
index 0000000..20bdebd
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelTest.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
+
+import android.platform.test.annotations.EnableFlags
+import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.lifecycle.activateIn
+import com.android.systemui.statusbar.core.NewStatusBarIcons
+import com.android.systemui.statusbar.core.StatusBarRootModernization
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class StackedMobileIconViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos().useUnconfinedTestDispatcher()
+ private val testScope = kosmos.testScope
+
+ private val Kosmos.underTest: StackedMobileIconViewModel by Fixture {
+ stackedMobileIconViewModel
+ }
+
+ @Before
+ fun setUp() {
+ kosmos.fakeFeatureFlagsClassic.set(Flags.NEW_NETWORK_SLICE_UI, false)
+ kosmos.underTest.activateIn(testScope)
+ }
+
+ @Test
+ @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ fun dualSim_filtersOutNonDualConnections() =
+ kosmos.runTest {
+ fakeMobileIconsInteractor.filteredSubscriptions.value = listOf()
+ assertThat(underTest.dualSim).isNull()
+
+ fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1)
+ assertThat(underTest.dualSim).isNull()
+
+ fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2, SUB_3)
+ assertThat(underTest.dualSim).isNull()
+
+ fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
+ assertThat(underTest.dualSim).isNotNull()
+ }
+
+ @Test
+ @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ fun dualSim_filtersOutNonCellularIcons() =
+ kosmos.runTest {
+ fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1)
+ assertThat(underTest.dualSim).isNull()
+
+ fakeMobileIconsInteractor
+ .getInteractorForSubId(SUB_1.subscriptionId)!!
+ .signalLevelIcon
+ .value =
+ SignalIconModel.Satellite(
+ level = 0,
+ icon = Icon.Resource(res = 0, contentDescription = null),
+ )
+ fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
+ assertThat(underTest.dualSim).isNull()
+ }
+
+ @Test
+ @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+ fun dualSim_tracksActiveSubId() =
+ kosmos.runTest {
+ // Active sub id is null, order is unchanged
+ fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
+ setIconLevel(SUB_1.subscriptionId, 1)
+ setIconLevel(SUB_2.subscriptionId, 2)
+
+ assertThat(underTest.dualSim!!.primary.level).isEqualTo(1)
+ assertThat(underTest.dualSim!!.secondary.level).isEqualTo(2)
+
+ // Active sub is 2, order is swapped
+ fakeMobileIconsInteractor.activeMobileDataSubscriptionId.value = SUB_2.subscriptionId
+
+ assertThat(underTest.dualSim!!.primary.level).isEqualTo(2)
+ assertThat(underTest.dualSim!!.secondary.level).isEqualTo(1)
+ }
+
+ private fun setIconLevel(subId: Int, level: Int) {
+ with(kosmos.fakeMobileIconsInteractor.getInteractorForSubId(subId)!!) {
+ signalLevelIcon.value =
+ (signalLevelIcon.value as SignalIconModel.Cellular).copy(level = level)
+ }
+ }
+
+ companion object {
+ private val SUB_1 =
+ SubscriptionModel(
+ subscriptionId = 1,
+ isOpportunistic = false,
+ carrierName = "Carrier 1",
+ profileClass = PROFILE_CLASS_UNSET,
+ )
+ private val SUB_2 =
+ SubscriptionModel(
+ subscriptionId = 2,
+ isOpportunistic = false,
+ carrierName = "Carrier 2",
+ profileClass = PROFILE_CLASS_UNSET,
+ )
+ private val SUB_3 =
+ SubscriptionModel(
+ subscriptionId = 3,
+ isOpportunistic = false,
+ carrierName = "Carrier 3",
+ profileClass = PROFILE_CLASS_UNSET,
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
index eb961bd..f91e3a6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
@@ -64,6 +64,8 @@
override val isHomeStatusBarAllowedByScene = MutableStateFlow(false)
+ override val canShowOngoingActivityChips: Flow<Boolean> = MutableStateFlow(false)
+
override val batteryViewModelFactory: BatteryViewModel.Factory =
object : BatteryViewModel.Factory {
override fun create(): BatteryViewModel = mock(BatteryViewModel::class.java)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
index cd8ca23..8a796fc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
@@ -86,6 +86,7 @@
import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher
import com.android.systemui.statusbar.phone.data.repository.fakeDarkIconRepository
+import com.android.systemui.statusbar.phone.ongoingcall.EnableChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.pipeline.shared.domain.interactor.setHomeStatusBarIconBlockList
import com.android.systemui.statusbar.pipeline.shared.domain.interactor.setHomeStatusBarInteractorShowOperatorName
@@ -677,6 +678,60 @@
}
@Test
+ fun canShowOngoingActivityChips_statusBarHidden_noSecureCamera_noHun_false() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.canShowOngoingActivityChips)
+
+ // home status bar not allowed
+ kosmos.sceneContainerRepository.snapToScene(Scenes.Lockscreen)
+ kosmos.keyguardOcclusionRepository.setShowWhenLockedActivityInfo(false, taskInfo = null)
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ fun canShowOngoingActivityChips_statusBarNotHidden_noSecureCamera_noHun_true() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.canShowOngoingActivityChips)
+
+ transitionKeyguardToGone()
+
+ assertThat(latest).isTrue()
+ }
+
+ @Test
+ fun canShowOngoingActivityChips_statusBarNotHidden_secureCamera_noHun_false() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.canShowOngoingActivityChips)
+
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ testScope = testScope,
+ )
+ kosmos.keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP)
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
+ fun canShowOngoingActivityChips_statusBarNotHidden_noSecureCamera_hun_false() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.canShowOngoingActivityChips)
+
+ transitionKeyguardToGone()
+
+ headsUpNotificationRepository.setNotifications(
+ UnconfinedFakeHeadsUpRowRepository(
+ key = "key",
+ pinnedStatus = MutableStateFlow(PinnedStatus.PinnedByUser),
+ )
+ )
+
+ assertThat(latest).isFalse()
+ }
+
+ @Test
fun isClockVisible_allowedByDisableFlags_visible() =
kosmos.runTest {
val latest by collectLastValue(underTest.isClockVisible)
@@ -835,7 +890,7 @@
}
@Test
- @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ @EnableChipsModernization
fun isNotificationIconContainerVisible_anyChipShowing_ChipsModernizationOn() =
kosmos.runTest {
val latest by collectLastValue(underTest.isNotificationIconContainerVisible)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java
index 8593f6a..605e4a4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/RotationLockControllerImplTest.java
@@ -37,15 +37,19 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper
@SmallTest
public class RotationLockControllerImplTest extends SysuiTestCase {
- private static final String[] DEFAULT_SETTINGS = new String[] {"0:0", "1:2"};
+ private static final String[] DEFAULT_SETTINGS = new String[]{"0:0", "1:2"};
- @Mock RotationPolicyWrapper mRotationPolicyWrapper;
- @Mock DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
+ @Mock
+ RotationPolicyWrapper mRotationPolicyWrapper;
+ @Mock
+ DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
private ArgumentCaptor<RotationPolicy.RotationPolicyListener> mRotationPolicyListenerCaptor;
@@ -93,7 +97,7 @@
private void createRotationLockController(String[] deviceStateRotationLockDefaults) {
new RotationLockControllerImpl(
mRotationPolicyWrapper,
- mDeviceStateRotationLockSettingController,
+ Optional.of(mDeviceStateRotationLockSettingController),
deviceStateRotationLockDefaults);
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
index 799e957..bab5a2d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy
import android.app.IActivityManager
+import android.app.role.RoleManager
import android.content.pm.PackageManager
import android.media.projection.MediaProjectionManager
import android.os.Handler
@@ -48,6 +49,7 @@
@Mock private lateinit var mediaProjectionManager: MediaProjectionManager
@Mock private lateinit var packageManager: PackageManager
@Mock private lateinit var telephonyManager: TelephonyManager
+ @Mock private lateinit var roleManager: RoleManager
private lateinit var controller: SensitiveNotificationProtectionControllerImpl
@Before
@@ -62,9 +64,10 @@
activityManager,
packageManager,
telephonyManager,
+ roleManager,
handler,
FakeExecutor(FakeSystemClock()),
- logger
+ logger,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
index 36e18e6..92bec70 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
@@ -173,15 +173,13 @@
runCurrent()
setDeviceState(UNFOLDED)
- verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
- val loggedEvent = loggerArgumentCaptor.value
val expectedLoggedEvent =
- DisplaySwitchLatencyEvent(
+ successfulEvent(
latencyMs = 250,
fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
toFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
)
- assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent)
}
}
@@ -225,15 +223,13 @@
runCurrent()
setDeviceState(UNFOLDED)
- verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
- val loggedEvent = loggerArgumentCaptor.value
val expectedLoggedEvent =
- DisplaySwitchLatencyEvent(
+ successfulEvent(
latencyMs = 50,
fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
toFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
)
- assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent)
}
}
@@ -258,15 +254,13 @@
runCurrent()
setDeviceState(UNFOLDED)
- verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
- val loggedEvent = loggerArgumentCaptor.value
val expectedLoggedEvent =
- DisplaySwitchLatencyEvent(
+ successfulEvent(
latencyMs = 50,
fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
toFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
)
- assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent)
}
}
@@ -287,15 +281,13 @@
powerInteractor.setScreenPowerState(SCREEN_ON)
runCurrent()
- verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
- val loggedEvent = loggerArgumentCaptor.value
val expectedLoggedEvent =
- DisplaySwitchLatencyEvent(
+ successfulEvent(
latencyMs = 200,
fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
)
- assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent)
}
}
@@ -317,16 +309,14 @@
powerInteractor.setScreenPowerState(SCREEN_ON)
runCurrent()
- verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
- val loggedEvent = loggerArgumentCaptor.value
val expectedLoggedEvent =
- DisplaySwitchLatencyEvent(
+ successfulEvent(
latencyMs = 200,
fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD,
)
- assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent)
}
}
@@ -369,16 +359,14 @@
powerInteractor.setScreenPowerState(SCREEN_OFF)
runCurrent()
- verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
- val loggedEvent = loggerArgumentCaptor.value
val expectedLoggedEvent =
- DisplaySwitchLatencyEvent(
+ successfulEvent(
latencyMs = 0,
fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF,
)
- assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent)
}
}
@@ -555,6 +543,23 @@
}
@Test
+ fun interruptedDisplaySwitchFinished_coolDownPassed_eventWithCorruptedResultSent() {
+ testScope.runTest {
+ startInFoldedState(displaySwitchLatencyTracker)
+
+ startUnfolding()
+ startFolding()
+ systemClock.advanceTime(5000) // clock for measuring latency
+ advanceTimeBy(COOL_DOWN_DURATION.plus(10.milliseconds)) // clock for triggering timeout
+
+ val event = capturedLogEvent()
+ assertThat(event.trackingResult)
+ .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__CORRUPTED)
+ assertThat(event.latencyMs).isEqualTo(5000)
+ }
+ }
+
+ @Test
fun displaySwitchInterrupted_coolDownExtendedByStartEvents() {
testScope.runTest {
startInFoldedState(displaySwitchLatencyTracker)
@@ -605,6 +610,27 @@
}
@Test
+ fun displaySwitchTimedOut_eventLoggedWithTimeOut() {
+ testScope.runTest {
+ startInFoldedState(displaySwitchLatencyTracker)
+
+ startUnfolding()
+ advanceTimeBy(SCREEN_EVENT_TIMEOUT + 10.milliseconds)
+ finishUnfolding()
+
+ val event = capturedLogEvent()
+ assertThat(event.trackingResult)
+ .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__TIMED_OUT)
+ assertThat(event.latencyMs).isEqualTo(SCREEN_EVENT_TIMEOUT.inWholeMilliseconds)
+ }
+ }
+
+ private fun capturedLogEvent(): DisplaySwitchLatencyEvent {
+ verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
+ return loggerArgumentCaptor.value
+ }
+
+ @Test
fun foldingStarted_screenStillOn_eventSentOnlyAfterScreenSwitches() {
// can happen for both folding and unfolding (with animations off) but it's more likely to
// happen when folding as waiting for screen on is the default case then
@@ -625,6 +651,21 @@
}
}
+ private fun successfulEvent(
+ latencyMs: Int,
+ fromFoldableDeviceState: Int,
+ toFoldableDeviceState: Int,
+ toState: Int = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__UNKNOWN,
+ ): DisplaySwitchLatencyEvent {
+ return DisplaySwitchLatencyEvent(
+ latencyMs = latencyMs,
+ fromFoldableDeviceState = fromFoldableDeviceState,
+ toFoldableDeviceState = toFoldableDeviceState,
+ toState = toState,
+ trackingResult = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__SUCCESS,
+ )
+ }
+
private suspend fun TestScope.startInFoldedState(tracker: DisplaySwitchLatencyTracker) {
setDeviceState(FOLDED)
tracker.start()
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 d3218ad..a0bf7f0 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
@@ -203,6 +203,8 @@
*/
void setIsNotificationPanelFullWidth(boolean isFullWidth);
+ default void setQSExpandingOrCollapsing(boolean isQSExpandingOrCollapsing) {}
+
/**
* Callback for when QSPanel container is scrolled
*/
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index 94fdbae..9b961d2 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -122,7 +122,7 @@
public void setAppName(String appName);
- public void createMenu(ViewGroup parent, StatusBarNotification sbn);
+ public void createMenu(ViewGroup parent);
public void resetMenu();
@@ -215,9 +215,8 @@
/**
* Callback used to signal the menu that its parent notification has been updated.
- * @param sbn
*/
- public void onNotificationUpdated(StatusBarNotification sbn);
+ public void onNotificationUpdated();
/**
* Callback used to signal the menu that a user is moving the parent notification.
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index ea3cbcf..739e868 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -27,7 +27,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Въведете паролата си"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"Въведете паролата"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Картата е невалидна."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Заредена"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Заредено"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се безжично"</string>
<string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 226d193..0da0636 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -27,7 +27,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introdueix la contrasenya"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"Introdueix la contrasenya"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"La targeta no és vàlida."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Bateria carregada"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Carregat"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant sense fil"</string>
<string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index 0b8ad02..0913f72 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -62,9 +62,9 @@
<string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Proovige uuesti või sisestage PIN-kood"</string>
<string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Proovige uuesti või sisestage parool"</string>
<string name="kg_bio_try_again_or_pattern" msgid="4867893307468801501">"Proovige uuesti või joonistage muster"</string>
- <string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"PIN-koodi nõutakse pärast liiga paljusid katseid"</string>
+ <string name="kg_bio_too_many_attempts_pin" msgid="5850845723433047605">"PIN-koodi nõutakse pärast liiga paljusid katseid."</string>
<string name="kg_bio_too_many_attempts_password" msgid="5551690347827728042">"Parool on nõutav pärast liiga paljusid katseid"</string>
- <string name="kg_bio_too_many_attempts_pattern" msgid="736884689355181602">"Muster on nõutav pärast liiga paljusid katseid"</string>
+ <string name="kg_bio_too_many_attempts_pattern" msgid="736884689355181602">"Muster on nõutav pärast liiga paljusid katseid."</string>
<string name="kg_unlock_with_pin_or_fp" msgid="5635161174698729890">"Avage PIN-koodi või sõrmejäljega"</string>
<string name="kg_unlock_with_password_or_fp" msgid="2251295907826814237">"Avage parooli või sõrmejäljega"</string>
<string name="kg_unlock_with_pattern_or_fp" msgid="2391870539909135046">"Avage mustri või sõrmejäljega"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 103f8ad..c3fccf2 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -36,7 +36,7 @@
<string name="keyguard_plugged_in_charging_limited" msgid="5369697538556777542">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау мақсатында зарядтау кідіртілді."</string>
<string name="keyguard_plugged_in_incompatible_charger" msgid="6384203333154532125">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядтау құрылғысын тексеріңіз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
- <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM картасы жоқ."</string>
+ <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM картасы жоқ"</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM картасын пайдалану мүмкін емес."</string>
<string name="keyguard_sim_locked_message" msgid="7095293254587575270">"SIM картасы құлыпталған."</string>
<string name="keyguard_sim_puk_locked_message" msgid="2503428315518592542">"SIM картасы PUK кодымен құлыпталды."</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 9a26f7d..1bdfd42 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -27,7 +27,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduza a palavra-passe"</string>
<string name="keyguard_enter_password" msgid="6483623792371009758">"Introduza a palavra-passe"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Carregada"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Bateria carregada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar sem fios"</string>
<string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index cf2057c..cab9cb9 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -36,7 +36,7 @@
<string name="keyguard_plugged_in_charging_limited" msgid="5369697538556777542">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка приостановлена для защиты батареи."</string>
<string name="keyguard_plugged_in_incompatible_charger" msgid="6384203333154532125">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Проверьте зарядное устройство."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string>
- <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM-карта отсутствует"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Нет SIM-карты"</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-карту невозможно использовать."</string>
<string name="keyguard_sim_locked_message" msgid="7095293254587575270">"SIM-карта заблокирована."</string>
<string name="keyguard_sim_puk_locked_message" msgid="2503428315518592542">"SIM-карта заблокирована с помощью PUK-кода."</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index bc047be..6dcc65e 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -46,9 +46,9 @@
<string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM 卡 PIN 區"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM 卡 PUK 區"</string>
<string name="keyboardview_keycode_delete" msgid="8489719929424895174">"刪除"</string>
- <string name="disable_carrier_button_text" msgid="7153361131709275746">"停用 eSIM 卡"</string>
- <string name="error_disable_esim_title" msgid="3802652622784813119">"無法停用 eSIM 卡"</string>
- <string name="error_disable_esim_msg" msgid="2441188596467999327">"發生錯誤,因此無法停用 eSIM 卡。"</string>
+ <string name="disable_carrier_button_text" msgid="7153361131709275746">"停用 eSIM"</string>
+ <string name="error_disable_esim_title" msgid="3802652622784813119">"無法停用 eSIM"</string>
+ <string name="error_disable_esim_msg" msgid="2441188596467999327">"發生錯誤,因此無法停用 eSIM。"</string>
<string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter 鍵"</string>
<string name="kg_wrong_pattern" msgid="5907301342430102842">"圖案錯誤"</string>
<string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"解鎖圖案錯誤,請再試一次。"</string>
@@ -86,7 +86,7 @@
<string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{請於 # 秒後再試一次。}other{請於 # 秒後再試一次。}}"</string>
<string name="kg_sim_pin_instructions" msgid="1942424305184242951">"輸入 SIM 卡的 PIN 碼。"</string>
<string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"輸入「<xliff:g id="CARRIER">%1$s</xliff:g>」SIM 卡的 PIN 碼。"</string>
- <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g>停用 eSIM 卡即可在沒有行動服務的情況下使用裝置。"</string>
+ <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g>停用 eSIM 即可在沒有行動服務的情況下使用裝置。"</string>
<string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM 卡已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與電信業者聯絡。"</string>
<string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM 卡「<xliff:g id="CARRIER">%1$s</xliff:g>」現已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與電信業者聯絡。"</string>
<string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"輸入所需的 PIN 碼"</string>
diff --git a/packages/SystemUI/res/color/media_player_outline_button_bg.xml b/packages/SystemUI/res/color/media_player_outline_button_bg.xml
deleted file mode 100644
index ba7848a..0000000
--- a/packages/SystemUI/res/color/media_player_outline_button_bg.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <item android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/media_player_solid_button_bg.xml b/packages/SystemUI/res/color/media_player_solid_button_bg.xml
index 69c9711..cc54fa3 100644
--- a/packages/SystemUI/res/color/media_player_solid_button_bg.xml
+++ b/packages/SystemUI/res/color/media_player_solid_button_bg.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <item android:color="?androidprv:attr/colorAccentPrimary"/>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_primary_dark"/>
</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_media_art_background.xml b/packages/SystemUI/res/drawable/qs_media_art_background.xml
index 95a1870..e59f82b 100644
--- a/packages/SystemUI/res/drawable/qs_media_art_background.xml
+++ b/packages/SystemUI/res/drawable/qs_media_art_background.xml
@@ -15,6 +15,7 @@
~ limitations under the License
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <corners android:radius="@dimen/qs_media_album_radius"/>
+ android:shape="rectangle">
+ <solid android:color="#FF000000" />
+ <corners android:radius="@dimen/notification_corner_radius"/>
</shape>
diff --git a/packages/SystemUI/res/layout/bindable_status_bar_compose_icon.xml b/packages/SystemUI/res/layout/bindable_status_bar_compose_icon.xml
index fa9318b..6b55ac2 100644
--- a/packages/SystemUI/res/layout/bindable_status_bar_compose_icon.xml
+++ b/packages/SystemUI/res/layout/bindable_status_bar_compose_icon.xml
@@ -27,7 +27,6 @@
android:layout_height="@dimen/status_bar_bindable_icon_size"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
- android:padding="4sp"
/>
</com.android.systemui.statusbar.pipeline.shared.ui.view.SingleBindableStatusBarComposeIconView>
diff --git a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
index 1f93717..795b7b4 100644
--- a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
+++ b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
@@ -121,8 +121,8 @@
android:contentDescription="@string/turn_on_bluetooth"
android:switchMinWidth="@dimen/settingslib_switch_track_width"
android:theme="@style/MainSwitch.Settingslib"
- android:thumb="@drawable/settingslib_thumb_selector"
- android:track="@drawable/settingslib_track_selector"
+ android:thumb="@drawable/settingslib_switch_thumb"
+ android:track="@drawable/settingslib_switch_track"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bluetooth_toggle_title"
app:layout_constraintTop_toTopOf="parent" />
@@ -163,8 +163,8 @@
android:contentDescription="@string/turn_on_bluetooth_auto_tomorrow"
android:switchMinWidth="@dimen/settingslib_switch_track_width"
android:theme="@style/MainSwitch.Settingslib"
- android:thumb="@drawable/settingslib_thumb_selector"
- android:track="@drawable/settingslib_track_selector"
+ android:thumb="@drawable/settingslib_switch_thumb"
+ android:track="@drawable/settingslib_switch_track"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/bluetooth_auto_on_toggle_title"
app:layout_constraintTop_toBottomOf="@+id/bluetooth_toggle" />
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 889aefe..f41eaec 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -13,14 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/volume_dialog"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0"
- android:clipChildren="false"
- app:layoutDescription="@xml/volume_dialog_scene">
+ android:clipChildren="false">
<View
android:id="@+id/volume_dialog_background"
@@ -52,7 +51,17 @@
<include
android:id="@+id/volume_dialog_main_slider_container"
- layout="@layout/volume_dialog_slider" />
+ layout="@layout/volume_dialog_slider"
+ android:layout_width="@dimen/volume_dialog_slider_width"
+ android:layout_height="0dp"
+ android:layout_marginTop="@dimen/volume_dialog_slider_vertical_margin"
+ android:layout_marginEnd="@dimen/volume_dialog_window_margin"
+ android:layout_marginBottom="@dimen/volume_dialog_slider_vertical_margin"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHeight_max="@dimen/volume_dialog_slider_height"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="0.5" />
<FrameLayout
android:id="@+id/volume_dialog_bottom_section_container"
@@ -88,4 +97,4 @@
app:layout_constraintEnd_toStartOf="@id/volume_dialog_background"
app:layout_constraintTop_toTopOf="@id/volume_dialog_main_slider_container" />
-</androidx.constraintlayout.motion.widget.MotionLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index b8b69b6..b4c5eed 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Invoer"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Gehoortoestelle"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Skakel tans aan …"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kan nie helderheid verstel nie omdat dit\n deur die topapp beheer word"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kan nie helderheid verstel nie omdat dit deur die topapp beheer word"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Outodraai"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Outodraai skerm"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ligging"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ontkies legstuk"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Verminder hoogte"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Vermeerder hoogte"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Wys volgende"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Wys vorige"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> steun nie gesprekskenmerke nie"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Terugvoer"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Maak toe"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Moenie weer wys nie"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Hierdie kennisgewings kan nie gewysig word nie."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Oproepkennisgewings kan nie gewysig word nie."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Hierdie groep kennisgewings kan nie hier opgestel word nie"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Voubare toestel word ontvou"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Voubare toestel word omgekeer"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Voorste skerm is aangeskakel"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Gly om binneskerm te gebruik"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"gevou"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"oopgevou"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml
index fbeefc8..3d0dbb5 100644
--- a/packages/SystemUI/res/values-af/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Af"</item>
<item msgid="5908720590832378783">"Aan"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index c89ea75..8a1ba62 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ግቤት"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"መስሚያ አጋዥ መሣሪያዎች"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"በማብራት ላይ..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ከላይ ባለው መተግበሪያ ቁጥጥር ላይ ስለሆነ\n ብሩህነትን ማስተካከል አልተቻለም"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ከላይ ባለው መተግበሪያ ቁጥጥር ላይ ስለሆነ ብሩህነትን ማስተካከል አልተቻለም"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"በራስ ሰር አሽከርክር"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ማያ ገጽን በራስ-አሽከርክር"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"አካባቢ"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ምግብር አትምረጥ"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ቁመት ቀንስ"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ቁመት ጨምር"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"ቀጣይ አሳይ"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"ቀዳሚ አሳይ"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> የውይይት ባህሪያትን አይደግፍም"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ግብረመልስ"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"አሰናብት"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ዳግም አታሳይ"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"እነዚህ ማሳወቂያዎች ሊሻሻሉ አይችሉም።"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"የጥሪ ማሳወቂያዎች ሊቀየሩ አይችሉም።"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"የማሳወቂያዎች ይህ ቡድን እዚህ ላይ ሊዋቀር አይችልም"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"መታጠፍ የሚችል መሣሪያ እየተዘረጋ ነው"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"መታጠፍ የሚችል መሣሪያ እየተገለበጠ ነው"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"የፊት ለፊት ማያ ገፅ በርቷል"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"ውስጣዊ ማያ ገፅን ለመጠቀም ያንሸራትቱ"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"የታጠፈ"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"የተዘረጋ"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml
index b98fe57..31a7d96 100644
--- a/packages/SystemUI/res/values-am/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ጠፍቷል"</item>
<item msgid="5908720590832378783">"በርቷል"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 962f1c9..538c961 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"الإدخال"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"سماعات الأذن الطبية"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"جارٍ التفعيل…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"لا يمكن ضبط مستوى السطوع لأنّ\n التطبيق الأول يتحكّم فيه"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"لا يمكن ضبط مستوى السطوع لأنّ التطبيق الأول يتحكّم فيه"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"التدوير التلقائي"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"التدوير التلقائي للشاشة"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"الموقع الجغرافي"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"إلغاء اختيار التطبيق المصغّر"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"تقليل الارتفاع"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"زيادة الارتفاع"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"عرض التالي"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"عرض السابق"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"لا يدعم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> ميزات المحادثات."</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"الملاحظات"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"إغلاق"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"عدم الإظهار مرة أخرى"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"يتعذّر تعديل هذه الإشعارات."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"لا يمكن تعديل إشعارات المكالمات."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"يتعذّر ضبط مجموعة الإشعارات هذه هنا."</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"جهاز قابل للطي يجري فتحه"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"جهاز قابل للطي يجري قلبه"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"تم تفعيل الشاشة الأمامية"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"يُرجى التمرير لاستخدام الشاشة الداخلية"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"مطوي"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"غير مطوي"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
@@ -1525,7 +1531,7 @@
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"الإضاءة الخلفية للوحة المفاتيح"</string>
<string name="keyboard_backlight_value" msgid="7336398765584393538">"مستوى الإضاءة: %1$d من %2$d"</string>
<string name="home_controls_dream_label" msgid="6567105701292324257">"إدارة المنزل آليًّا"</string>
- <string name="home_controls_dream_description" msgid="4644150952104035789">"يمكنك إدارة المنزل آليًّا بشكل سريع من شاشة الاستراحة"</string>
+ <string name="home_controls_dream_description" msgid="4644150952104035789">"يمكنك إدارة المنزل آليًّا بسرعة من شاشة الاستراحة."</string>
<string name="volume_undo_action" msgid="5815519725211877114">"تراجع"</string>
<string name="back_edu_toast_content" msgid="4530314597378982956">"للرجوع، مرِّر سريعًا لليمين أو لليسار على لوحة اللمس باستخدام 3 أصابع"</string>
<string name="home_edu_toast_content" msgid="3381071147871955415">"للانتقال إلى الشاشة الرئيسية، مرِّر سريعًا للأعلى على لوحة اللمس باستخدام 3 أصابع"</string>
diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
index 0be4367..abb0d85 100644
--- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"متوقّفة"</item>
<item msgid="5908720590832378783">"مفعّلة"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index b88e9e9..74c4e3e 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ৱিজেট বাছনিৰ পৰা আঁতৰাওক"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"উচ্চতা হ্ৰাস কৰক"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"উচ্চতা বৃদ্ধি কৰক"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"পিছৰটো দেখুৱাওক"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"পূৰ্বৰটো দেখুৱাওক"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বাৰ্তালাপৰ সুবিধাসমূহ সমৰ্থন নকৰে"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"মতামত"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"অগ্ৰাহ্য কৰক"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"পুনৰাই নেদেখুৱাব"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"এই জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"কলৰ জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"এই ধৰণৰ জাননীবোৰ ইয়াত কনফিগাৰ কৰিব পৰা নাযায়"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"জপাব পৰা ডিভাইচৰ জাপ খুলি থকা হৈছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"জপাব পৰা ডিভাইচৰ ওলোটাই থকা হৈছে"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"সন্মুখৰ স্ক্ৰীনখন অন কৰা হৈছে"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"ভিতৰৰ স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ স্লাইড কৰক"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"ফ’ল্ড কৰা"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"আনফ’ল্ড কৰা"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml
index da237e5..68212e0 100644
--- a/packages/SystemUI/res/values-as/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"অফ আছে"</item>
<item msgid="5908720590832378783">"অন আছে"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index e629969..e6b3023 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Giriş"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Eşitmə aparatları"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiv edilir..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Yuxarıdakı tətbiq tərəfindən idarə olunduğu üçün\n parlaqlığı tənzimləmək mümkün deyil"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Yuxarıdakı tətbiq tərəfindən idarə olunduğu üçün parlaqlığı tənzimləmək mümkün deyil"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Avtodönüş"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranın avtomatik dönməsi"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Məkan"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"vidcet seçimini silin"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Hündürlüyü azaldın"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Hündürlüyü artırın"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Növbətini göstərin"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Əvvəlkini göstərin"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> söhbət funksiyalarını dəstəkləmir"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Rəy"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Rədd edin"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Yenidən göstərməyin"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirişlər dəyişdirilə bilməz."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Zəng bildirişləri dəyişdirilə bilməz."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Bu bildiriş qrupunu burada konfiqurasiya etmək olmaz"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Qatlana bilən cihaz açılır"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Qatlana bilən cihaz fırladılır"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Ön ekran aktiv edildi"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Daxili ekrandan istifadə etmək üçün sürüşdürün"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"qatlanmış"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"açıq"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml
index 0203fb0..696fad2 100644
--- a/packages/SystemUI/res/values-az/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Deaktiv"</item>
<item msgid="5908720590832378783">"Aktiv"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 1970144..19e4076 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Unos"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Slušni aparati"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Uključuje se..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ne možete da prilagodite osvetljenost jer je\n kontroliše aplikacija u vrhu"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ne možete da prilagodite osvetljenost jer je kontroliše aplikacija u vrhu"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatska rotacija"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko rotiranje ekrana"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništi izbor vidžeta"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Smanji visinu"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Povećaj visinu"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Prikažite sledeće"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Prikažite prethodno"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava funkcije konverzacije"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Povratne informacije"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Odbaci"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ne prikazuj ponovo"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ova obaveštenja ne mogu da se menjaju."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obaveštenja o pozivima ne mogu da se menjaju."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ova grupa obaveštenja ne može da se konfiguriše ovde"</string>
@@ -1370,7 +1377,7 @@
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Promenite izlaz"</string>
<string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Nepoznato"</string>
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"s:min"</string>
- <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"č:min"</string>
+ <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Želite da dozvolite da <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> pristupa svim evidencijama uređaja?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Dozvoli jednokratan pristup"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ne dozvoli"</string>
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 2401e4a..3b99019 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
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Isključeno"</item>
<item msgid="5908720590832378783">"Uključeno"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index afbac9f..aaed55b 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Увод"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Слыхавыя апараты"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Уключэнне…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не ўдаецца адрэгуляваць яркасць, бо яна\nкантралюецца асноўнай праграмай"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не ўдаецца адрэгуляваць яркасць, бо янакантралюецца асноўнай праграмай"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Аўтапаварот"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Аўтаматычны паварот экрана"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Месцазнаходжанне"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"скасаваць выбар віджэта"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Паменшыць вышыню"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Павялічыць вышыню"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Паказаць наступны"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Паказаць папярэдні"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не падтрымлівае функцыі размовы"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Водгук"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Закрыць"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Больш не паказваць"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Гэтыя апавяшчэнні нельга змяніць."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Апавяшчэнні пра выклікі нельга змяніць."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Тут канфігурыраваць гэту групу апавяшчэнняў забаронена"</string>
diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml
index 2dc7057..9f520da9 100644
--- a/packages/SystemUI/res/values-be/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Выключана"</item>
<item msgid="5908720590832378783">"Уключана"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 77542de..22e30e2 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Вход"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Слухови апарати"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Включва се..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Яркостта не може да се коригира, защото се контролира\n от приложението на екрана"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Яркостта не може да се коригира, защото се контролира от приложението на екрана"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Авт. ориентация"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматично завъртане на екрана"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Местоположение"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"премахване на избора от приспособлението"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Намаляване на височината"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Увеличаване на височината"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Показване на следващия"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Показване на предишния"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддържа функциите за разговор"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Отзиви"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Отхвърляне"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Да не се показва отново"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Тези известия не могат да бъдат променяни."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Известията за обаждания не могат да бъдат променяни."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Тази група от известия не може да бъде конфигурирана тук"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Разгъване на сгъваемо устройство"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Обръщане на сгъваемо устройство"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Предният екран е включен"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Плъзнете, за да използвате вътрешния екран"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"затворено"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"отворено"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
index cc632db7..e598f928 100644
--- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Изкл."</item>
<item msgid="5908720590832378783">"Вкл."</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 6bd1e0c..f0ae2ae 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ইনপুট"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"হিয়ারিং এড"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"চালু করা হচ্ছে…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"উজ্জ্বলতা টপ অ্যাপ নিয়ন্ত্রণ করায়\n এটিকে অ্যাডজাস্ট করা যাচ্ছে না"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"উজ্জ্বলতা টপ অ্যাপ নিয়ন্ত্রণ করায় এটিকে অ্যাডজাস্ট করা যাচ্ছে না"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"নিজে থেকে ঘুরবে"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"অটো-রোটেট স্ক্রিন"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"লোকেশন"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"উইজেট বাদ দিন"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"উচ্চতা কমান"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"উচ্চতা বাড়ান"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"পরেরটি দেখুন"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"আগেরটি দেখুন"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এ কথোপকথন ফিচার কাজ করে না"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"মতামত"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"বাতিল করুন"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"আর দেখতে চাই না"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"এই বিজ্ঞপ্তিগুলি পরিবর্তন করা যাবে না।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"কল বিজ্ঞপ্তি পরিবর্তন করা যাবে না।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"এই সমস্ত বিজ্ঞপ্তিকে এখানে কনফিগার করা যাবে না"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ফোল্ড করা যায় এমন ডিভাইস খোলা হচ্ছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ফোল্ড করা যায় এমন ডিভাইস উল্টানো হচ্ছে"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"ফ্রন্ট স্ক্রিন চালু আছে"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"ভেতরের স্ক্রিন ব্যবহার করতে স্লাইড করুন"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"ফোল্ড করা রয়েছে"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"ফোল্ড করা নেই"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
index e213928..38d9ee7 100644
--- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"বন্ধ আছে"</item>
<item msgid="5908720590832378783">"চালু আছে"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 4ccc38a..a2df671 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ulaz"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Slušni aparati"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Uključivanje…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nije moguće podesiti osvijetljenost\n jer njome upravlja aplikacija pri vrhu"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nije moguće podesiti osvijetljenost jer njome upravlja aplikacija pri vrhu"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatsko rotiranje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko rotiranje ekrana"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništavanje odabira vidžeta"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Smanjenje visine"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Povećanje visine"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Prikaz sljedećeg"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Prikaz prethodnog"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Vidžeti na zaključanom ekranu"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava funkcije razgovora"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Povratne informacije"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Odbaci"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ne prikazuj ponovo"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ta obavještenja se ne mogu izmijeniti."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Nije moguće izmijeniti obavještenja o pozivima."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ovu grupu obavještenja nije moguće konfigurirati ovdje"</string>
@@ -1394,7 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Sklopivi uređaj se rasklapa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Sklopivi uređaj se obrće"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Prednji ekran je uključen"</string>
- <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Kliznite za upotrebu unutarnjeg zaslona"</string>
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Kliznite da koristite unutrašnji ekran"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"sklopljeno"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"otklopljeno"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
index 2401e4a..3b99019 100644
--- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Isključeno"</item>
<item msgid="5908720590832378783">"Uključeno"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 80558a9..933ac96 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Audiòfons"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"S\'està activant…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"No es pot ajustar la brillantor perquè\n està controlada per l\'aplicació superior"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"No es pot ajustar la brillantor perquè està controlada per l\'aplicació superior"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Gira automàticament"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Gira la pantalla automàticament"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ubicació"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desselecciona el widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Redueix l\'alçada"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Augmenta l\'alçada"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostra el següent"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostra l\'anterior"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admet les funcions de converses"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Suggeriments"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Ignora"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"No ho tornis a mostrar"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Aquestes notificacions no es poden modificar."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Les notificacions de trucades no es poden modificar."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Aquest grup de notificacions no es pot configurar aquí"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositiu plegable desplegant-se"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositiu plegable girant"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"La pantalla frontal està activada"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Llisca per utilitzar la pantalla interior"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"plegat"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"desplegat"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
@@ -1474,7 +1480,7 @@
<string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"barra inclinada"</string>
<string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Ansa per arrossegar"</string>
<string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Configuració del teclat"</string>
- <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Configura la drecera"</string>
+ <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Configura"</string>
<string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Suprimeix"</string>
<string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Sí, restableix"</string>
<string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Cancel·la"</string>
diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
index 94d5545..e0c3fb9 100644
--- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Desactivat"</item>
<item msgid="5908720590832378783">"Activat"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ee32107..6c66fee 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vstup"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Naslouchátka"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Zapínání…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Jas nelze upravit, protože ho\n řídí hlavní aplikace"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Jas nelze upravit, protože ho řídí hlavní aplikace"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. otáčení"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatické otáčení obrazovky"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Poloha"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"zrušit výběr widgetu"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Snížit výšku"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Zvýšit výšku"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Zobrazit další"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Zobrazit předchozí"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> funkce konverzace nepodporuje"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Zpětná vazba"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Zavřít"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Už nezobrazovat"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Tato oznámení nelze upravit."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornění na hovor nelze upravit."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Tuto skupinu oznámení tady nelze nakonfigurovat"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozkládání rozkládacího zařízení"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Otáčení rozkládacího zařízení"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Přední obrazovka je zapnutá"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Pokud chcete použít vnitřní obrazovku, přejeďte prstem"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"složené"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"rozložené"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
index a02ed76..ea62773 100644
--- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Vypnuto"</item>
<item msgid="5908720590832378783">"Zapnuto"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 323b9d8..35c07a7 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Høreapparater"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiverer…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Lysstyrken kan ikke justeres, fordi den\n styres af den øverste app"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Lysstyrken kan ikke justeres, fordi den styres af den øverste app"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Roter automatisk"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Roter skærmen automatisk"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokation"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"fjern markering af widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Reducer højden"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Forøg højden"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Vis næste"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Vis forrige"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> understøtter ikke samtalefunktioner"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Luk"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Vis ikke igen"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Disse notifikationer kan ikke redigeres."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Opkaldsnotifikationer kan ikke redigeres."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Du kan ikke konfigurere denne gruppe notifikationer her"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldbar enhed foldes ud"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldbar enhed vendes om"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Frontskærmen er aktiveret"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Skub for at bruge den indre skærm"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"foldet"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"foldet ud"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml
index 8b536a2..2b1dbcf 100644
--- a/packages/SystemUI/res/values-da/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Fra"</item>
<item msgid="5908720590832378783">"Til"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3c8be75..badceeb 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Eingabe"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hörgerät"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Wird aktiviert…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Die Helligkeit kann nicht angepasst werden, weil sie\n von der obersten App gesteuert wird"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Die Helligkeit kann nicht angepasst werden, weil sie von der obersten App gesteuert wird"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. drehen"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Bildschirm automatisch drehen"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Standort"</string>
@@ -463,7 +463,7 @@
<string name="zen_mode_off" msgid="1736604456618147306">"Aus"</string>
<string name="zen_mode_set_up" msgid="8231201163894922821">"Nicht festgelegt"</string>
<string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"In den Einstellungen verwalten"</string>
- <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Keine aktiven Modi}=1{{mode} aktiv}other{# aktiv}}"</string>
+ <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Kein Modus aktiv}=1{{mode} aktiv}other{# aktiv}}"</string>
<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>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Anpassen"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"Auswahl für Widget aufheben"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Höhe verringern"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Höhe vergrößern"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Nächstes Element anzeigen"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Vorheriges Element anzeigen"</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>
@@ -541,7 +543,7 @@
<string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Hub-Modus entdecken"</string>
<string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Du kannst während des Ladevorgangs auf deine bevorzugten Widgets und Bildschirmschoner zugreifen."</string>
<string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Los gehts"</string>
- <string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"Beim Laden deine bevorzugten Bildschirmschoner anzeigen"</string>
+ <string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"Beim Laden werden deine Lieblings-Bildschirmschoner angezeigt"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Pull-down-Menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> unterstützt keine Funktionen für Unterhaltungen"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Schließen"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Nicht mehr anzeigen"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Diese Benachrichtigungen können nicht geändert werden."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Anrufbenachrichtigungen können nicht geändert werden."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Die Benachrichtigungsgruppe kann hier nicht konfiguriert werden"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Faltbares Gerät wird geöffnet"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Faltbares Gerät wird umgeklappt"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Frontdisplay aktiviert"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Ziehen, um das innere Display zu verwenden"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"zugeklappt"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"aufgeklappt"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml
index bb39b4e..ded7efd 100644
--- a/packages/SystemUI/res/values-de/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Aus"</item>
<item msgid="5908720590832378783">"An"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 470dd2c..e41c366 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Είσοδος"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Βοηθήματα ακοής"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Ενεργοποίηση…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Δεν είναι δυνατή η προσαρμογή της φωτεινότητας, επειδή\n ελέγχεται από την εφαρμογή στην κορυφή"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Δεν είναι δυνατή η προσαρμογή της φωτεινότητας, επειδή ελέγχεται από την εφαρμογή στην κορυφή"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Αυτόματη περιστροφή"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Αυτόματη περιστροφή οθόνης"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Τοποθεσία"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"αποεπιλογή γραφικού στοιχείου"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Μείωση του ύψους"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Αύξηση του ύψους"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Εμφάνιση επόμενου"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Εμφάνιση προηγούμενου"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν υποστηρίζει τις λειτουργίες συζήτησης"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Σχόλια"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Παράβλεψη"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Να μην εμφανιστεί ξανά"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Δεν είναι δυνατή η τροποποίηση αυτών των ειδοποιήσεων"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Δεν είναι δυνατή η τροποποίηση των ειδοποιήσεων κλήσεων."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Δεν είναι δυνατή η διαμόρφωση αυτής της ομάδας ειδοποιήσεων εδώ"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Αναδιπλούμενη συσκευή που ξεδιπλώνει"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Αναδιπλούμενη συσκευή που διπλώνει"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Η μπροστινή οθόνη ενεργοποιήθηκε"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Σύρετε για χρήση της εσωτερικής οθόνης"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"διπλωμένη"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"ξεδιπλωμένη"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml
index 5ce4b8c..398bf13 100644
--- a/packages/SystemUI/res/values-el/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml
@@ -64,7 +64,7 @@
<string-array name="tile_states_rotation">
<item msgid="4578491772376121579">"Μη διαθέσιμο"</item>
<item msgid="5776427577477729185">"Ανενεργό"</item>
- <item msgid="7105052717007227415">"Ενεργό"</item>
+ <item msgid="7105052717007227415">"Ενεργή"</item>
</string-array>
<string-array name="tile_states_bt">
<item msgid="5330252067413512277">"Μη διαθέσιμο"</item>
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Ανενεργό"</item>
<item msgid="5908720590832378783">"Ενεργό"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 0c161a7..ac1f233 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being\n controlled by the top app"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being controlled by the top app"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Decrease height"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Increase height"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Show next"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Show previous"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Dismiss"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Don\'t show again"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Front screen turned on"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Slide to use inner screen"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"folded"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"unfolded"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
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 1b60921..d62f2e5 100644
--- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Off"</item>
<item msgid="5908720590832378783">"On"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 3a7440b..e9e4e6e 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being\n controlled by the top app"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being controlled by the top app"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Decrease height"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Increase height"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Show next"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Show previous"</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 it’s you. Also, keep 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>
@@ -806,7 +808,9 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Dismiss"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Don\'t show again"</string>
+ <string name="notification_inline_disable_promotion" msgid="3551682588314376921">"Don\'t show as pinned"</string>
+ <string name="live_notifications_title" msgid="1586553354601345379">"Showing Live Updates"</string>
+ <string name="live_notifications_desc" msgid="7470787001768372152">"Pinned notifications display live info from apps, and always appear on the status bar and lock screen"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</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 1b60921..d62f2e5 100644
--- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Off"</item>
<item msgid="5908720590832378783">"On"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 0c161a7..ac1f233 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being\n controlled by the top app"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being controlled by the top app"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Decrease height"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Increase height"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Show next"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Show previous"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Dismiss"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Don\'t show again"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Front screen turned on"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Slide to use inner screen"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"folded"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"unfolded"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
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 1b60921..d62f2e5 100644
--- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Off"</item>
<item msgid="5908720590832378783">"On"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 0c161a7..ac1f233 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being\n controlled by the top app"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Can\'t adjust brightness because it\'s being controlled by the top app"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"unselect widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Decrease height"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Increase height"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Show next"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Show previous"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Dismiss"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Don\'t show again"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Front screen turned on"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Slide to use inner screen"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"folded"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"unfolded"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
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 1b60921..d62f2e5 100644
--- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Off"</item>
<item msgid="5908720590832378783">"On"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index dd8f735..7b66997 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Audífonos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activando…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"La app superior controla el brillo,\npor lo que no se puede ajustar"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"La app superior controla el brillo,por lo que no se puede ajustar"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Girar la pantalla automáticamente"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ubicación"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anular la selección del widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Reducir la altura"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Aumentar la altura"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostrar siguiente"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostrar anterior"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite funciones de conversación"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Comentarios"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Descartar"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"No volver a mostrar"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"No se pueden modificar estas notificaciones."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"No se pueden modificar las notificaciones de llamada."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"No se puede configurar aquí este grupo de notificaciones"</string>
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 1c587d6..d835483 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Desactivado"</item>
<item msgid="5908720590832378783">"Activado"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a2fcc5c..e3dbc11 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Audífonos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activando…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"No se puede ajustar el brillo porque la aplicación superior lo está\n controlando"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"No se puede ajustar el brillo porque la aplicación superior lo está controlando"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Girar pantalla automáticamente"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ubicación"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deseleccionar widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Reducir altura"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Aumentar altura"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostrar siguiente"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostrar anterior"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite funciones de conversación"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Comentarios"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Cerrar"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"No volver a mostrar"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Estas notificaciones no se pueden modificar."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Las notificaciones de llamada no se pueden modificar."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Este grupo de notificaciones no se puede configurar aquí"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable desplegándose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable mostrado desde varios ángulos"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Pantalla frontal encendida"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Desliza para usar la pantalla interior"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"plegado"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"desplegado"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index 5c4f36a..ea75e52 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Desactivado"</item>
<item msgid="5908720590832378783">"Activado"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index bca7491..f13295a 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Sisend"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Kuuldeaparaadid"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Sisselülitamine …"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Heledust ei saa reguleerida, kuna seda\n juhib ülemine rakendus"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Heledust ei saa reguleerida, kuna seda juhib ülemine rakendus"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. pööramine"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Kuva automaatne pööramine"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Asukoht"</string>
@@ -504,8 +504,8 @@
<string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Lukustuskuva vidinad"</string>
<string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g> lisati lukustuskuvale"</string>
<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>
+ <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Kohanda"</string>
+ <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Loobu"</string>
<string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Lisage ja eemaldage vidinaid ning muutke nende järjestust"</string>
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lisage rohkem vidinaid"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Vajutage pikalt vidinate kohandamiseks"</string>
@@ -530,10 +530,12 @@
<string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"eemaldage vidin"</string>
<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>
+ <string name="communal_widget_picker_description" msgid="490515450110487871">"Igaüks saab vaadata lukustuskuval olevaid vidinaid, isegi kui tahvelarvuti on lukus."</string>
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"tühistage vidina valimine"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Vähenda kõrgust"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Suurenda kõrgust"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Kuva järgmine"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Kuva eelmine"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei toeta vestlusfunktsioone"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Tagasiside"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Loobu"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ära enam näita"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Neid märguandeid ei saa muuta."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Kõnemärguandeid ei saa muuta."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Seda märguannete rühma ei saa siin seadistada"</string>
diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml
index f995128..a9f0880 100644
--- a/packages/SystemUI/res/values-et/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Väljas"</item>
<item msgid="5908720590832378783">"Sees"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index f447dc6..7c047c0 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Sarrera"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Audifonoak"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktibatzen…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ezin da doitu argitasuna,\ngaineko aplikazioak kontrolatzen duelako"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ezin da doitu argitasuna,gaineko aplikazioak kontrolatzen duelako"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Biratze automatikoa"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Biratu pantaila automatikoki"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Kokapena"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desautatu widgeta"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Txikitu altuera"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Handitu altuera"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Erakutsi hurrengoa"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Erakutsi aurrekoa"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez ditu onartzen elkarrizketetarako eginbideak"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Iritzia"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Baztertu"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ez erakutsi berriro"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Jakinarazpen horiek ezin dira aldatu."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Deien jakinarazpenak ezin dira aldatu."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Jakinarazpen talde hau ezin da konfiguratu hemen"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Gailu tolesgarria zabaltzen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Gailu tolesgarria biratzen"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Aurreko pantaila piztuta dago"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Lerratu hau barneko pantaila erabiltzeko"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"tolestuta"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"tolestu gabe"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
index 5d4672f..62bbc27 100644
--- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Desaktibatuta"</item>
<item msgid="5908720590832378783">"Aktibatuta"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 800bf78..e837ed3 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -125,7 +125,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>
@@ -133,7 +133,7 @@
<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" 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>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ورودی"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"سمعک"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"روشن کردن…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"نمیتوان روشنایی را تنظیم کرد زیرا\n برنامه بالایی آن را کنترل میکند"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"نمیتوان روشنایی را تنظیم کرد زیرا برنامه بالایی آن را کنترل میکند"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"چرخش خودکار"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"چرخش خودکار صفحهنمایش"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"مکان"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"لغو انتخاب ابزاره"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"کاهش ارتفاع"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"افزایش ارتفاع"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"نمایش بعدی"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"نمایش قبلی"</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>
@@ -542,7 +544,7 @@
<string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"در حین شارژ، به ابزارهها و محافظهای صفحهنمایش دلخواهتان دسترسی داشته باشید."</string>
<string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"بیایید شروع کنیم"</string>
<string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"نمایش محافظهای صفحهنمایش دلخواه درحین شارژ"</string>
- <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تغییر کاربر"</string>
+ <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تعویض کاربر"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"منوی پایینپر"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامهها و دادههای این جلسه حذف خواهد شد."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"مهمان گرامی، بازگشتتان را خوش آمد میگوییم!"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ویژگیهای مکالمه پشتیبانی نمیکند"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"بازخورد"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"بستن"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"دیگر نشان داده نشود"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"این اعلانها قابل اصلاح نیستند."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"این اعلانها قابلاصلاح نیستند."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"نمیتوانید این گروه اعلانها را در اینجا پیکربندی کنید"</string>
diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
index 1f9d6c6..edc2d41 100644
--- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"خاموش"</item>
<item msgid="5908720590832378783">"روشن"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index fdf18a3..ab551b3 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -330,7 +330,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Syöttölaite"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Kuulolaitteet"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Otetaan käyttöön…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kirkkautta ei voi säätää, koska \n ensisijainen sovellus ohjaa sitä"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kirkkautta ei voi säätää, koska ensisijainen sovellus ohjaa sitä"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automaattinen kääntö"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Käännä näyttöä automaattisesti."</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Sijainti"</string>
@@ -536,6 +536,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poista widgetin valinta"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Vähennä korkeutta"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Lisää korkeutta"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Näytä seuraava"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Näytä edellinen"</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>
@@ -808,7 +810,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei tue keskusteluominaisuuksia"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Palaute"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Hylkää"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Älä näytä uudelleen"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Näitä ilmoituksia ei voi muokata"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Puheluilmoituksia ei voi muokata."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Tätä ilmoitusryhmää ei voi määrittää tässä"</string>
@@ -1396,8 +1403,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Taitettava laite taitetaan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Taitettava laite käännetään ympäri"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Etunäyttö päällä"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Liu\'uta käyttääksesi sisäistä näyttöä"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"taitettu"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"taittamaton"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
index 96750ef..6b1a8ed 100644
--- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Pois päältä"</item>
<item msgid="5908720590832378783">"Päällä"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index dde9b64..bd3a7628 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrée"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Prothèses auditives"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activation en cours…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Impossible de régler la luminosité, car elle est\n contrôlée par l\'appli principale"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Impossible de régler la luminosité, car elle est contrôlée par l\'appli principale"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotation auto"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotation automatique de l\'écran"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localisation"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"désélectionner le widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Diminuer la hauteur"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Augmenter la hauteur"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Afficher le suivant"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Afficher le précédent"</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 voir les widgets, 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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne prend pas en charge les fonctionnalités de conversation"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Commentaires"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Fermer"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ne plus afficher"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ces notifications ne peuvent pas être modifiées"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Les notifications d\'appel ne peuvent pas être modifiées."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ce groupe de notifications ne peut pas être configuré ici"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable en cours de dépliage"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable en train d\'être retourné"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Écran avant activé"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Faites glisser pour utiliser l\'écran intérieur"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"plié"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"déplié"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
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 ffacde2..4734d86 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Désactivée"</item>
<item msgid="5908720590832378783">"Activée"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 53dbfea..be21ba9 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrée"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Appareils auditifs"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activation…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Impossible d\'ajuster la luminosité, car celle-ci\n est contrôlée par l\'appli principale"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Impossible d\'ajuster la luminosité, car celle-ci est contrôlée par l\'appli principale"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotation auto"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotation automatique de l\'écran"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localisation"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"désélectionner le widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Diminuer la hauteur"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Augmenter la hauteur"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Afficher le suivant"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Afficher le précédent"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas compatible avec les fonctionnalités de conversation"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Commentaires"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Ignorer"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ne plus afficher"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Impossible de modifier ces notifications."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Impossible de modifier les notifications d\'appel."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Vous ne pouvez pas configurer ce groupe de notifications ici"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable qui est déplié"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable qui est retourné"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Écran avant activé"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Faites glisser pour utiliser l\'écran intérieur"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"plié"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"déplié"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index ffceb0d..cefc9a2 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Désactivé"</item>
<item msgid="5908720590832378783">"Activé"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 03ec2b0..462b07a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -125,7 +125,7 @@
<string name="screenrecord_continue" msgid="4055347133700593164">"Iniciar"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Gravando pantalla"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Gravando pantalla e audio"</string>
- <string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar a localización dos toques na pantalla"</string>
+ <string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar localización dos toques na pantalla"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Deter"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"Gravación da pantalla gardada"</string>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Audiófonos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activando…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Non se pode axustar o brillo\n porque o controla a aplicación principal"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Non se pode axustar o brillo porque o controla a aplicación principal"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Xirar automaticamente"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Xirar pantalla automaticamente"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localización"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anular a selección do widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Reducir a altura"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Aumentar a altura"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostrar seguinte"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostrar anterior"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da pantalla de bloqueo"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir unha aplicación mediante un widget, tes que verificar a túa identidade. Ten en conta que pode velos calquera persoa, mesmo coa tableta bloqueada. Pode ser que algúns widgets non estean pensados para a túa pantalla de bloqueo, polo que talvez non sexa seguro engadilos aquí."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non admite funcións de conversa"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Comentarios"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Pechar"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Non volver mostrar"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Estas notificacións non se poden modificar."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"As notificacións de chamadas non se poden modificar."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Aquí non se pode configurar este grupo de notificacións"</string>
@@ -1349,7 +1356,7 @@
<string name="clipboard_image_preview" msgid="2156475174343538128">"Vista previa da imaxe"</string>
<string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Engadir"</string>
- <string name="manage_users" msgid="1823875311934643849">"Usuarios"</string>
+ <string name="manage_users" msgid="1823875311934643849">"Xestionar usuarios"</string>
<string name="drag_split_not_supported" msgid="7173481676120546121">"Esta notificación non pode arrastrarse á pantalla dividida"</string>
<string name="dream_overlay_location_active" msgid="6484763493158166618">"Localización activa"</string>
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"A wifi non está dispoñible"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pregable abríndose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pregable xirando"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Activouse a pantalla dianteira"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Pasa o dedo para usar a pantalla interior"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"dispositivo pregado"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"dispositivo despregado"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
index 7889983..bfd6a12 100644
--- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Opción desactivada"</item>
<item msgid="5908720590832378783">"Opción activada"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 0c27927..5b86eab 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ઇનપુટ"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"સાંભળવામાં મદદ આપતા યંત્રો"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ચાલુ કરી રહ્યાં છીએ…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"બ્રાઇટનેસ ગોઠવી શકતા નથી કારણ કે તે\n લોકપ્રિય ઍપ દ્વારા નિયંત્રિત કરવામાં આવી રહી છે"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"બ્રાઇટનેસ ગોઠવી શકતા નથી કારણ કે તે લોકપ્રિય ઍપ દ્વારા નિયંત્રિત કરવામાં આવી રહી છે"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ઑટો રોટેટ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ઑટો રોટેટ સ્ક્રીન"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"લોકેશન"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"વિજેટ નાપસંદ કરો"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ઊંચાઈ ઘટાડો"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ઊંચાઈ વધારો"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"આગલું બતાવો"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"પાછલું બતાવો"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> વાતચીતની સુવિધાઓને સપોર્ટ આપતી નથી"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"પ્રતિસાદ"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"છોડી દો"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ફરી બતાવશો નહીં"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"આ નોટિફિકેશનમાં કોઈ ફેરફાર થઈ શકશે નહીં."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"કૉલના નોટિફિકેશનમાં કોઈ ફેરફાર કરી શકાતો નથી."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"નોટિફિકેશનના આ ગ્રૂપની ગોઠવણી અહીં કરી શકાશે નહીં"</string>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index 17b47cc..c6e204d 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"બંધ છે"</item>
<item msgid="5908720590832378783">"ચાલુ"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f2daffe..b45d3e9 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"इनपुट"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"कान की मशीनें"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ब्लूटूथ चालू हो रहा है…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"स्क्रीन की रोशनी को एडजस्ट नहीं किया जा सकता, क्योंकि\n इसे टॉप ऐप्लिकेशन कंट्रोल कर रहा है"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"स्क्रीन की रोशनी को एडजस्ट नहीं किया जा सकता, क्योंकि इसे टॉप ऐप्लिकेशन कंट्रोल कर रहा है"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ऑटो-रोटेट"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"स्क्रीन का अपने-आप दिशा बदलना (ऑटो-रोटेट)"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"जगह की जानकारी"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"विजेट से चुने हुए का निशान हटाएं"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ऊंचाई घटाएं"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ऊंचाई बढ़ाएं"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"अगला दिखाएं"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"पिछला दिखाएं"</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>
@@ -542,7 +544,7 @@
<string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"चार्जिंग के दौरान, अपने पसंदीदा विजेट और स्क्रीन सेवर को ऐक्सेस करें."</string>
<string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"आइए शुरू करें"</string>
<string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"चार्ज करते समय अपने पसंदीदा स्क्रीन सेवर दिखाएं"</string>
- <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"उपयोगकर्ता बदलें"</string>
+ <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"दूसरे खाते पर स्विच करें"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेन्यू"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सेशन के सभी ऐप्लिकेशन और डेटा को हटा दिया जाएगा."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"मेहमान, आपका फिर से स्वागत है!"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर बातचीत की सुविधाएं काम नहीं करतीं"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"सुझाव/राय दें या शिकायत करें"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"खारिज करें"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"फिर से न दिखाएं"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ये सूचनाएं नहीं बदली जा सकती हैं."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कॉल से जुड़ी सूचनाओं को ब्लॉक नहीं किया जा सकता."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"सूचनाओं के इस समूह को यहां कॉन्फ़िगर नहीं किया जा सकता"</string>
diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
index 69a4e4d..65046cc 100644
--- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"बंद है"</item>
<item msgid="5908720590832378783">"चालू है"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 5222e80..1b351bd 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Unos"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Slušna pomagala"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Uključivanje…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Svjetlina se ne može prilagoditi jer njome\n upravlja aplikacija pri vrhu"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Svjetlina se ne može prilagoditi jer njome upravlja aplikacija pri vrhu"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatsko zakretanje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko zakretanje zaslona"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"poništavanje odabira widgeta"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Smanjenje visine"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Povećanje visine"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Prikazivanje sljedećeg"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Prikazivanje prethodnog"</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>
@@ -731,7 +733,7 @@
<string name="volume_panel_hint_muted" msgid="1124844870181285320">"isključen zvuk"</string>
<string name="volume_panel_hint_vibrate" msgid="4136223145435914132">"vibriranje"</string>
<string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> se reproducira na"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Zvuk će se reproducirati na"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Za reprodukciju zvuka koristi se"</string>
<string name="media_output_title_ongoing_call" msgid="208426888064112006">"Pozivanje na uređaju"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Ugađanje korisničkog sučelja sustava"</string>
<string name="status_bar" msgid="4357390266055077437">"Traka statusa"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava značajke razgovora"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Povratne informacije"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Odbaci"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ne prikazuj ponovo"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Te se obavijesti ne mogu izmijeniti."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obavijesti o pozivima ne mogu se izmijeniti."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ta se grupa obavijesti ne može konfigurirati ovdje"</string>
diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
index 2401e4a..3b99019 100644
--- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Isključeno"</item>
<item msgid="5908720590832378783">"Uključeno"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 109c52f..ca32832 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Bevitel"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hallókészülék"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Bekapcsolás…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nem lehet módosítani a fényerőt, mert a felső alkalmazás\n vezérli"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nem lehet módosítani a fényerőt, mert a felső alkalmazás vezérli"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatikus elforgatás"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatikus képernyőforgatás"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Tartózkodási hely"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"modul kijelölésének megszüntetése"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Magasság csökkentése"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Magasság növelése"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Következő mutatása"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Előző mutatása"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> nem támogatja a beszélgetési funkciókat"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Visszajelzés"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Elvetés"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ne jelenjen meg újra"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ezeket az értesítéseket nem lehet módosítani."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"A hívásértesítéseket nem lehet módosítani."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Az értesítések jelen csoportját itt nem lehet beállítani"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Összehajtható eszköz kihajtása"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Összehajtható eszköz körbeforgatása"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Előlapi képernyő bekapcsolva"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Csúsztatás a belső képernyő használatához"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"összehajtva"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"kihajtva"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
index 8911fe9..06bf4f2 100644
--- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Ki"</item>
<item msgid="5908720590832378783">"Be"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 914d2cd..b619708 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Մուտքագրում"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Լսողական սարք"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Միացում…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Հնարավոր չէ կարգավորել պայծառությունը, քանի որ այն\n կառավարվում է գլխավոր հավելվածի կողմից"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Հնարավոր չէ կարգավորել պայծառությունը, քանի որ այն կառավարվում է գլխավոր հավելվածի կողմից"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Ինքնապտտում"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ավտոմատ պտտել էկրանը"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Տեղորոշում"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"չեղարկել վիջեթի ընտրությունը"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Նվազեցնել բարձրությունը"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Ավելացնել բարձրությունը"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Ցույց տալ հաջորդը"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Ցույց տալ նախորդը"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը զրույցի գործառույթներ չի աջակցում"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Կարծիք հայտնել"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Փակել"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Այլևս ցույց չտալ"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Այս ծանուցումները չեն կարող փոփոխվել:"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Զանգերի մասին ծանուցումները հնարավոր չէ փոփոխել։"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ծանուցումների տվյալ խումբը հնարավոր չէ կարգավորել այստեղ"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ծալովի սարք՝ բացված վիճակում"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Ծալովի սարք՝ շրջված վիճակում"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Առջևի էկրանը միացված է"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Սահեցրեք՝ ներքին էկրանն օգտագործելու համար"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"ծալված"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"բացված"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
index f2b09e0..dc8bbb1 100644
--- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Անջատված է"</item>
<item msgid="5908720590832378783">"Միացված է"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 62e3476..2a24134 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -250,8 +250,8 @@
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Persentase baterai tidak diketahui."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Terhubung ke <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Terhubung ke <xliff:g id="CAST">%s</xliff:g>."</string>
- <string name="accessibility_expand_group" msgid="521237935987978624">"Meluaskan grup."</string>
- <string name="accessibility_open_application" msgid="1749126077501259712">"Membuka aplikasi."</string>
+ <string name="accessibility_expand_group" msgid="521237935987978624">"Luaskan grup."</string>
+ <string name="accessibility_open_application" msgid="1749126077501259712">"Buka aplikasi."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Tidak terhubung."</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Nonaktif"</string>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Alat bantu dengar"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Mengaktifkan…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Tidak dapat menyesuaikan kecerahan karena sedang\n dikontrol oleh aplikasi atas"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Tidak dapat menyesuaikan kecerahan karena sedang dikontrol oleh aplikasi atas"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Putar Otomatis"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Putar layar otomatis"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokasi"</string>
@@ -345,7 +345,7 @@
<string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Jaringan tidak tersedia"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Tidak ada jaringan Wi-Fi yang tersedia"</string>
<string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Mengaktifkan…"</string>
- <string name="quick_settings_cast_title" msgid="3033553249449938182">"Cast"</string>
+ <string name="quick_settings_cast_title" msgid="3033553249449938182">"Transmisikan"</string>
<string name="quick_settings_casting" msgid="1435880708719268055">"Melakukan transmisi"</string>
<string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Perangkat tanpa nama"</string>
<string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Perangkat tak tersedia"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"batalkan pilihan widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Kurangi tinggi"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Tambah tinggi"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Tampilkan berikutnya"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Tampilkan sebelumnya"</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>
@@ -542,7 +544,7 @@
<string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Akses widget dan screensaver favorit Anda saat mengisi daya."</string>
<string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Mulai"</string>
<string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"Tampilkan screensaver favorit saat mengisi daya"</string>
- <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
+ <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Ganti pengguna"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pulldown"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat datang kembali, tamu!"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak mendukung fitur percakapan"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Masukan"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Tutup"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Jangan tampilkan lagi"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Notifikasi ini tidak dapat diubah."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Notifikasi panggilan tidak dapat diubah."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Grup notifikasi ini tidak dapat dikonfigurasi di sini"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Perangkat foldable sedang dibentangkan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Perangkat foldable sedang dibalik"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Layar depan diaktifkan"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Geser untuk menggunakan layar dalam"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"ditutup"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"dibuka"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml
index 7462ff6..b48a587 100644
--- a/packages/SystemUI/res/values-in/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Nonaktif"</item>
<item msgid="5908720590832378783">"Aktif"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 4e486d0..5b33fdd 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Inntak"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Heyrnartæki"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Kveikir…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ekki er hægt að breyta birtustiginu vegna þess að \n efsta forritið stjórnar því"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ekki er hægt að breyta birtustiginu vegna þess að efsta forritið stjórnar því"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Sjálfvirkur snúningur"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Snúa skjá sjálfkrafa"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Staðsetning"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"afturkalla val á græju"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Lækka"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Hækka"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Sýna næsta"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Sýna fyrra"</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>
@@ -731,7 +733,7 @@
<string name="volume_panel_hint_muted" msgid="1124844870181285320">"þaggað"</string>
<string name="volume_panel_hint_vibrate" msgid="4136223145435914132">"titringur"</string>
<string name="media_output_label_title" msgid="872824698593182505">"Í spilun í <xliff:g id="LABEL">%s</xliff:g>"</string>
- <string name="media_output_title_without_playing" msgid="3825663683169305013">"Hljóð heldur áfram að spilast"</string>
+ <string name="media_output_title_without_playing" msgid="3825663683169305013">"Hljóð heldur áfram að spilast í"</string>
<string name="media_output_title_ongoing_call" msgid="208426888064112006">"Símtal í gangi"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Fínstillingar kerfisviðmóts"</string>
<string name="status_bar" msgid="4357390266055077437">"Stöðustika"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> styður ekki samtalseiginleika"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Ábendingar"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Loka"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ekki sýna aftur"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ekki er hægt að breyta þessum tilkynningum."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Ekki er hægt að breyta tilkynningum um símtöl."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ekki er hægt að stilla þessar tilkynningar hér"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Samanbrjótanlegt tæki opnað"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Samanbrjótanlegu tæki snúið við"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Kveikt á fremri skjá"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Renndu til að opna innri skjá"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"samanbrotið"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"opið"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml
index df3bcf9..92f07b6 100644
--- a/packages/SystemUI/res/values-is/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Slökkt"</item>
<item msgid="5908720590832378783">"Kveikt"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 786254b..4858cb0 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ingresso"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Apparecchi acustici"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Attivazione…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Impossibile regolare la luminosità perché è\n controllata dall\'app in primo piano"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Impossibile regolare la luminosità perché è controllata dall\'app in primo piano"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotazione automatica"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotazione automatica dello schermo"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Posizione"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deseleziona widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Riduci altezza"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Aumenta altezza"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostra successivo"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostra precedente"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non supporta le funzionalità delle conversazioni"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Ignora"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Non mostrare più"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Impossibile modificare queste notifiche."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Impossibile modificare gli avvisi di chiamata."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Qui non è possibile configurare questo gruppo di notifiche"</string>
@@ -1396,7 +1403,7 @@
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Schermo frontale attivato"</string>
<string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Scorri per usare lo schermo interno"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"Piegato"</string>
- <string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"Non piegato"</string>
+ <string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"Aperto"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
<string name="stylus_battery_low_percentage" msgid="2564243323894629626">"Batteria dello stilo: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connetti lo stilo a un caricabatterie"</string>
diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml
index 9d26859..7e11d0b 100644
--- a/packages/SystemUI/res/values-it/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Off"</item>
<item msgid="5908720590832378783">"On"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 5000885..ad5fe65 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"קלט"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"מכשירי שמיעה"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ההפעלה מתבצעת…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"לא ניתן להתאים את הבהירות כי היא\n נשלטת על ידי האפליקציה העליונה"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"לא ניתן להתאים את הבהירות כי היא נשלטת על ידי האפליקציה העליונה"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"סיבוב אוטומטי"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"סיבוב אוטומטי של המסך"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"מיקום"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ביטול הבחירה בווידג\'ט"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"הקטנת הגובה"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"הגדלת הגובה"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"לפריט הבא"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"לפריט הקודם"</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>
@@ -804,10 +806,14 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"מוצגת בחלק העליון של קטע התראות השיחה וכתמונת פרופיל במסך הנעילה, מופיעה בבועה צפה ומפריעה במצב \'נא לא להפריע\'"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"בעדיפות גבוהה"</string>
<string name="no_shortcut" msgid="8257177117568230126">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא תומכת בתכונות השיחה"</string>
- <!-- no translation found for notification_guts_bundle_feedback (7581587973879656500) -->
- <skip />
+ <string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"משוב"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"סגירה"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"לא להציג את זה שוב"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"לא ניתן לשנות את ההתראות האלה."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"לא ניתן לשנות את התראות השיחה."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"לא ניתן להגדיר כאן את קבוצת ההתראות הזו"</string>
@@ -1395,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"מכשיר מתקפל עובר למצב לא מקופל"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"מכשיר מתקפל עובר למצב מהופך"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"המסך הקדמי מופעל"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"כדי להשתמש במסך הפנימי, צריך להסיט"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"מצב מקופל"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"מצב לא מקופל"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
index 1a5b8fb..2f8ec0a 100644
--- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"מושבת"</item>
<item msgid="5908720590832378783">"מצב פעיל"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index fd98fe8..bc3555a 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"入力"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"補聴器"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ON にしています…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"明るさはトップ アプリによって\n制御されているため、調整できません"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"明るさはトップ アプリによって制御されているため、調整できません"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"自動回転"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"画面を自動回転します"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"位置情報"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ウィジェットの選択を解除する"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"高さを低くする"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"高さを高くする"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"次を表示"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"前を表示"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>は会話機能に対応していません"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"フィードバック"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"閉じる"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"次回から表示しない"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"これらの通知は変更できません。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"着信通知は変更できません。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"このグループの通知はここでは設定できません"</string>
diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
index 81c10e7..1282f57 100644
--- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"OFF"</item>
<item msgid="5908720590832378783">"ON"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 18522da..b599220 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ვიჯეტის არჩევის გაუქმება"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"სიმაღლის შემცირება"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"სიმაღლის გაზრდა"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"შემდეგის ჩვენება"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"წინას ჩვენება"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ს არ აქვს მიმოწერის ფუნქციების მხარდაჭერა"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"გამოხმაურება"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"დახურვა"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"აღარ მაჩვენო"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ამ შეტყობინებების შეცვლა შეუძლებელია."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ზარის შეტყობინებების შეცვლა შეუძლებელია."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"შეტყობინებების ამ ჯგუფის კონფიგურირება აქ შეუძლებელია"</string>
diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
index 6e62ed4e..81fc54d 100644
--- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"გამორთული"</item>
<item msgid="5908720590832378783">"ჩართული"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 83af7c8..5c1b563 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -114,7 +114,7 @@
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Осы экранды жазу"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s экранын жазу"</string>
<string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Бүкіл экранды жазған кезде, онда көрінетін барлық нәрсе жазылады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string>
- <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Қолданбаны жазған кезде, онда көрінетін не ойнатылатын барлық нәрсе жазылады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string>
+ <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Қолданбаны жазған кезде, онда көрінетін не ойнатылатын барлық нәрсе жазылады. Сондықтан құпия сөздерге, төлем туралы мәліметке, хабарларға, фотосуреттерге, дыбыстар мен бейнелерге сақ болыңыз."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Экранды жазу"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Жазатын қолданба экранын таңдау"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Аудио жазу"</string>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Кіріс"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Есту аппараттары"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Қосылып жатыр…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Жарықтықты реттеу мүмкін емес, себебі ол\n жетекші қолданба арқылы басқарылады."</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Жарықтықты реттеу мүмкін емес, себебі ол жетекші қолданба арқылы басқарылады."</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоматты түрде бұру"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматты айналатын экран"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Локация"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетті таңдаудан алу"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Биіктігін төмендету"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Биіктігін арттыру"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Келесіні көрсету"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Алдыңғыны көрсету"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> әңгіме функцияларын қолдамайды."</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Пікір"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Жабу"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Қайта көрсетілмесін"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Бұл хабарландыруларды өзгерту мүмкін емес."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Қоңырау туралы хабарландыруларды өзгерту мүмкін емес."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Мұндай хабарландырулар бұл жерде конфигурацияланбайды."</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Бүктемелі құрылғы ашылып жатыр."</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Бүктемелі құрылғы аударылып жатыр."</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Алдыңғы экран қосылды."</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Ішкі экранды пайдалану үшін жылжытыңыз."</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"жабық"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"ашық"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
index 66deff6..32562c6 100644
--- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Өшірулі"</item>
<item msgid="5908720590832378783">"Қосулы"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 569ecd3..0c2e9c2 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"បញ្ចូល"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"ឧបករណ៍ជំនួយការស្ដាប់"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"កំពុងបើក..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"មិនអាចកែតម្រូវកម្រិតពន្លឺបានទេ ដោយសារវាកំពុងស្ថិតក្រោម\nការគ្រប់គ្រងរបស់កម្មវិធីខាងលើគេ"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"មិនអាចកែតម្រូវកម្រិតពន្លឺបានទេ ដោយសារវាកំពុងស្ថិតក្រោមការគ្រប់គ្រងរបស់កម្មវិធីខាងលើគេ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"បង្វិលស្វ័យប្រវត្តិ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"បង្វិលអេក្រង់ស្វ័យប្រវត្តិ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ទីតាំង"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ដកការជ្រើសរើសធាតុក្រាហ្វិក"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"បន្ថយកម្ពស់"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"បង្កើនកម្ពស់"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"បង្ហាញកម្មវិធីចាក់មេឌៀបន្ទាប់"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"បង្ហាញកម្មវិធីចាក់មេឌៀមុន"</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>
@@ -542,7 +544,7 @@
<string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"ចូលប្រើប្រាស់ធាតុក្រាហ្វិក និងធាតុរក្សាអេក្រង់ដែលអ្នកពេញចិត្តពេលសាកថ្ម។"</string>
<string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"ចាប់ផ្ដើម"</string>
<string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"បង្ហាញធាតុរក្សាអេក្រង់សំណព្វរបស់អ្នក ពេលកំពុងសាកថ្ម"</string>
- <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរអ្នកប្រើ"</string>
+ <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរអ្នកប្រើប្រាស់"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ម៉ឺនុយទាញចុះ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យទាំងអស់ក្នុងវគ្គនេះនឹងត្រូវលុប។"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"សូមស្វាគមន៍ការត្រឡប់មកវិញ, ភ្ញៀវ!"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> មិនអាចប្រើមុខងារសន្ទនាបានទេ"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"មតិកែលម្អ"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ច្រានចោល"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"កុំបង្ហាញម្ដងទៀត"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"មិនអាចកែប្រែការជូនដំណឹងទាំងនេះបានទេ។"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"មិនអាចកែប្រែការជូនដំណឹងអំពីការហៅទូរសព្ទបានទេ។"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"មិនអាចកំណត់រចនាសម្ព័ន្ធក្រុមការជូនដំណឹងនេះនៅទីនេះបានទេ"</string>
diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml
index 71b12ca..0e47250 100644
--- a/packages/SystemUI/res/values-km/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"បិទ"</item>
<item msgid="5908720590832378783">"បើក"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 5bcd986..2136599 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ಇನ್ಪುಟ್"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ಬ್ರೈಟ್ನೆಸ್ ಅನ್ನು ಅಡ್ಜಸ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ,\n ಏಕೆಂದರೆ ಅದನ್ನು ಟಾಪ್ ಆ್ಯಪ್ ನಿಯಂತ್ರಿಸುತ್ತಿದೆ"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ಬ್ರೈಟ್ನೆಸ್ ಅನ್ನು ಅಡ್ಜಸ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ, ಏಕೆಂದರೆ ಅದನ್ನು ಟಾಪ್ ಆ್ಯಪ್ ನಿಯಂತ್ರಿಸುತ್ತಿದೆ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ಸ್ವಯಂ-ತಿರುಗುವಿಕೆ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ಪರದೆಯನ್ನು ಸ್ವಯಂ-ತಿರುಗಿಸಿ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ಸ್ಥಳ"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ವಿಜೆಟ್ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಬೇಡಿ"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ಎತ್ತರವನ್ನು ಕಡಿಮೆ ಮಾಡಿ"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ಎತ್ತರವನ್ನು ಹೆಚ್ಚಿಸಿ"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"ಮುಂದಿನದನ್ನು ತೋರಿಸಿ"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"ಹಿಂದಿನದನ್ನು ತೋರಿಸಿ"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"ಸಂವಾದ ಫೀಚರ್ಗಳನ್ನು <xliff:g id="APP_NAME">%1$s</xliff:g> ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ಫೀಡ್ಬ್ಯಾಕ್"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ವಜಾಗೊಳಿಸಿ"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ಮತ್ತೊಮ್ಮೆ ತೋರಿಸಬೇಡಿ"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ಕರೆ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ಈ ಗುಂಪಿನ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇಲ್ಲಿ ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾಗಿರುವುದಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
index 49c688a..b3543f9 100644
--- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ಆಫ್ ಆಗಿದೆ"</item>
<item msgid="5908720590832378783">"ಆನ್ ಆಗಿದೆ"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index fd2c62e..9b26e97 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"입력"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"보청기"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"켜는 중..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"상위 앱에서 밝기를 제어하고 있으므로\n 밝기를 조절할 수 없습니다."</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"상위 앱에서 밝기를 제어하고 있으므로 밝기를 조절할 수 없습니다."</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"자동 회전"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"화면 자동 회전"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"위치"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"위젯 선택 해제"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"높이 줄이기"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"높이 늘리기"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"다음 표시"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"이전 표시"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱은 대화 기능을 지원하지 않습니다."</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"의견"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"닫기"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"다시 표시하지 않음"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"이 알림은 수정할 수 없습니다."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"전화 알림은 수정할 수 없습니다."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"이 알림 그룹은 여기에서 설정할 수 없습니다."</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"폴더블 기기를 펼치는 모습"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"폴더블 기기를 뒤집는 모습"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"전면 화면 켜짐"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"슬라이드하여 내부 화면 사용"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"접은 상태"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"펼친 상태"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
index 002d38e..c512435 100644
--- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"사용 안함"</item>
<item msgid="5908720590832378783">"사용"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 1916cbc..c1d5201 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Киргизүү"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Угуу аппараттары"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Күйгүзүлүүдө…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Жарыктыкты тууралоого болбойт, анткени аны\n жогорку колдонмо көзөмөлдөйт"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Жарыктыкты тууралоого болбойт, анткени аны жогорку колдонмо көзөмөлдөйт"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Авто буруу"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Экранды авто буруу"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Жайгашкан жер"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетти тандоодон чыгаруу"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Бийиктигин азайтуу"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Бийиктигин көбөйтүү"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Кийинкини көрсөтүү"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Мурункуну көрсөтүү"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда оозеки сүйлөшкөнгө болбойт"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Пикир билдирүү"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Жабуу"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Экинчи көрсөтүлбөсүн"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Бул билдирмелерди өзгөртүүгө болбойт."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Чалуу билдирмелерин өзгөртүүгө болбойт."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Бул билдирмелердин тобун бул жерде конфигурациялоого болбойт"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ачылып турган бүктөлмө түзмөк"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Оодарылып жаткан бүктөлмө түзмөк"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Маңдайкы экран күйгүзүлдү"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Ички экранды колдонуу үчүн экранды сүрүп коюңуз"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"бүктөлгөн"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"ачылган"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
index 4834dbc..47e36da 100644
--- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Өчүк"</item>
<item msgid="5908720590832378783">"Күйүк"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index f61186d..702c04f 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ການປ້ອນຂໍ້ມູນ"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"ເຄື່ອງຊ່ວຍຟັງ"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ກຳລັງເປີດ..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ບໍ່ສາມາດປັບຄວາມແຈ້ງເນື່ອງຈາກມັນ\n ຖືກຄວບຄຸມໂດຍແອັບຍອດນິຍົມ"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ບໍ່ສາມາດປັບຄວາມແຈ້ງເນື່ອງຈາກມັນ ຖືກຄວບຄຸມໂດຍແອັບຍອດນິຍົມ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ໝຸນອັດຕະໂນມັດ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ໝຸນໜ້າຈໍອັດຕະໂນມັດ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ສະຖານທີ່"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ຍົກເລີກການເລືອກວິດເຈັດ"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ຫຼຸດຄວາມສູງ"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ເພີ່ມຄວາມສູງ"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"ສະແດງເພງຖັດໄປ"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"ສະແດງເພງກ່ອນໜ້າ"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ຮອງຮັບຄຸນສົມບັດການສົນທະນາ"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ຄຳຕິຊົມ"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ປິດໄວ້"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ບໍ່ຕ້ອງສະແດງອີກ"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ບໍ່ສາມາດແກ້ໄຂການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄດ້."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ບໍ່ສາມາດແກ້ໄຂການແຈ້ງເຕືອນການໂທໄດ້."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ບໍ່ສາມາດຕັ້ງຄ່າກຸ່ມການແຈ້ງເຕືອນນີ້ຢູ່ບ່ອນນີ້ໄດ້"</string>
diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
index bc63895..71e084a 100644
--- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ປິດ"</item>
<item msgid="5908720590832378783">"ເປີດ"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 88f9399..36b2b99 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Įvestis"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Klausos aparatai"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Įjungiama…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Negalima koreguoti ryškumo, nes jį valdo\n viršuje esanti programa"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Negalima koreguoti ryškumo, nes jį valdo viršuje esanti programa"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatinis pasukimas"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatiškai sukti ekraną"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Vietovė"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"atšaukti valdiklio pasirinkimą"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Sumažinti aukštį"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Padidinti aukštį"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Rodyti kitą mediją"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Rodyti ankstesnę mediją"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Užrakinimo ekrano valdikliai"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Kad galėtumėte atidaryti programą naudodami valdiklį, turėsite patvirtinti savo tapatybę. Be to, atminkite, kad bet kas gali peržiūrėti valdiklius net tada, kai planšetinis kompiuteris užrakintas. Kai kurie valdikliai gali būti neskirti jūsų užrakinimo ekranui ir gali būti nesaugu juos čia pridėti."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Supratau"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ nepalaiko pokalbių funkcijų"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Atsiliepimai"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Uždaryti"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Neberodyti"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Šių pranešimų keisti negalima."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Skambučių pranešimų keisti negalima."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Šios grupės pranešimai čia nekonfigūruojami"</string>
diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
index 12f8b6c..893d6ae 100644
--- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Išjungta"</item>
<item msgid="5908720590832378783">"Įjungta"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e0e38a1..dcb405b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -125,7 +125,7 @@
<string name="screenrecord_continue" msgid="4055347133700593164">"Sākt"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Notiek ekrāna satura ierakstīšana."</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Notiek ekrāna satura un audio ierakstīšana."</string>
- <string name="screenrecord_taps_label" msgid="1595690528298857649">"Rādīt pieskārienus pie ekrāna"</string>
+ <string name="screenrecord_taps_label" msgid="1595690528298857649">"Rādīt pieskārienus ekrānam"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Pārtraukt"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Kopīgot"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"Ekrāna ieraksts ir saglabāts"</string>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ievade"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Dzirdes aparāti"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Notiek ieslēgšana…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nevar mainīt spilgtumu, jo to kontrolē\n aktīvā lietotne."</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nevar mainīt spilgtumu, jo to kontrolē aktīvā lietotne."</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automātiska pagriešana"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automātiska ekrāna pagriešana"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Atrašanās vieta"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"noņemt logrīka atlasi"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Samazināt augstumu"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Palielināt augstumu"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Rādīt nākamo"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Rādīt iepriekšējo"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> netiek atbalstītas sarunu funkcijas."</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Atsauksmes"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Nerādīt"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Vairs nerādīt"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Šos paziņojumus nevar modificēt."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Paziņojumus par zvaniem nevar modificēt."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Šeit nevar konfigurēt šo paziņojumu grupu."</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Salokāma ierīce tiek atlocīta"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Salokāma ierīce tiek apgriezta"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Priekšējais ekrāns ir ieslēgts"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Velciet, lai izmantotu iekšējo ekrānu."</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"aizvērta"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"atvērta"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
index 1494836..7329751 100644
--- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Izslēgts"</item>
<item msgid="5908720590832378783">"Ieslēgts"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 0a9ca89..10435b8 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Влез"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Слушни помагала"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Се вклучува…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не може да се приспособи осветленоста бидејќи е\n контролирана од горната апликација"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не може да се приспособи осветленоста бидејќи е контролирана од горната апликација"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоматско ротирање"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматско ротирање на екранот"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Локација"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"поништи го изборот на виџетот"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Намали ја висината"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Зголеми ја висината"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Прикажи следно"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Прикажи претходно"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддржува функции за разговор"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Повратни информации"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Отфрли"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Не прикажувај повторно"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Овие известувања не може да се изменат"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Известувањата за повици не може да се изменат."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Оваа група известувања не може да се конфигурира тука"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Преклопувачки уред се отклопува"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Преклопувачки уред се врти"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Предниот екран е вклучен"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Лизгајте за да го користите внатрешниот екран"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"затворен"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"отворен"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index 17545c3..67baf7c 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Исклучено"</item>
<item msgid="5908720590832378783">"Вклучено"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 8ef9b79..489f1ad 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ഇൻപുട്ട്"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"ശ്രവണ സഹായികൾ"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ഓണാക്കുന്നു…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"തെളിച്ചം അഡ്ജസ്റ്റ് ചെയ്യാനാകില്ല, അത്\n നിയന്ത്രിക്കുന്നത് ഏറ്റവും മുകളിലുള്ള ആപ്പാണ്"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"തെളിച്ചം അഡ്ജസ്റ്റ് ചെയ്യാനാകില്ല, അത് നിയന്ത്രിക്കുന്നത് ഏറ്റവും മുകളിലുള്ള ആപ്പാണ്"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"സ്ക്രീൻ സ്വയമേവ തിരിയൽ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"സ്ക്രീൻ സ്വയമേവ തിരിക്കുക"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ലൊക്കേഷൻ"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"വിജറ്റ് തിരഞ്ഞെടുത്തത് മാറ്റുക"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ഉയരം കുറയ്ക്കുക"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ഉയരം കൂട്ടുക"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"അടുത്തത് കാണിക്കുക"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"മുമ്പത്തേത് കാണിക്കുക"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"സംഭാഷണ ഫീച്ചറുകളെ <xliff:g id="APP_NAME">%1$s</xliff:g> പിന്തുണയ്ക്കുന്നില്ല"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ഫീഡ്ബാക്ക്"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ഡിസ്മിസ് ചെയ്യുക"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"വീണ്ടും കാണിക്കരുത്"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ഈ അറിയിപ്പുകൾ പരിഷ്ക്കരിക്കാനാവില്ല."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"കോൾ അറിയിപ്പുകൾ പരിഷ്കരിക്കാനാകുന്നില്ല."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"അറിയിപ്പുകളുടെ ഈ ഗ്രൂപ്പ് ഇവിടെ കോണ്ഫിഗര് ചെയ്യാൻ കഴിയില്ല"</string>
diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
index 689fe85..8639c10 100644
--- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ഓഫാണ്"</item>
<item msgid="5908720590832378783">"ഓണാണ്"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index feca241..776f1e9 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Оролт"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Сонсголын төхөөрөмж"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Асааж байна…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Гэрэлтүүлгийг\nдавуу эрхтэй аппаас хянаж байгаа тул тохируулах боломжгүй"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Гэрэлтүүлгийгдавуу эрхтэй аппаас хянаж байгаа тул тохируулах боломжгүй"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоматаар эргэх"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Дэлгэцийг автоматаар эргүүлэх"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Байршил"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"виджетийн сонголтыг болиулах"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Намсгах"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Өндөрсгөх"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Дараагийнхыг харуулах"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Өмнөхийг харуулах"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь харилцан ярианы онцлогуудыг дэмждэггүй"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Санал хүсэлт"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Хаах"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Дахиж бүү харуул"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Эдгээр мэдэгдлийг өөрчлөх боломжгүй."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Дуудлагын мэдэгдлийг өөрчлөх боломжгүй."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Энэ бүлэг мэдэгдлийг энд тохируулах боломжгүй байна"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Эвхэгддэг төхөөрөмжийг дэлгэж байна"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Эвхэгддэг төхөөрөмжийг хөнтөрч байна"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Нүүрэн талын дэлгэцийг асаасан"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Дотоод дэлгэцийг ашиглахын тулд гулсуулна уу"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"эвхсэн"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"дэлгэсэн"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
index 94e3939..678033c 100644
--- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Унтраалттай"</item>
<item msgid="5908720590832378783">"Асаалттай"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index a3c45f3..5691410 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"इनपुट"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"श्रवणयंत्रे"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"सुरू करत आहे…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ब्राइटनेस ॲडजस्ट करू शकत नाही, कारण तो\n टॉप ॲपद्वारे नियंत्रित केला जात आहे"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ब्राइटनेस ॲडजस्ट करू शकत नाही, कारण तो टॉप ॲपद्वारे नियंत्रित केला जात आहे"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ऑटो-रोटेट"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ऑटो-रोटेट स्क्रीन"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"स्थान"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"विजेटची निवड रद्द करा"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"उंची कमी करा"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"उंची वाढवा"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"पुढील दाखवा"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"मागील दाखवा"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे संभाषण वैशिष्ट्यांना सपोर्ट करत नाही"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"फीडबॅक"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"डिसमिस करा"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"पुन्हा दाखवू नका"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"या सूचनांमध्ये सुधारणा केली जाऊ शकत नाही."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कॉलशी संबंधित सूचनांमध्ये फेरबदल केला जाऊ शकत नाही."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"या सूचनांचा संच येथे कॉन्फिगर केला जाऊ शकत नाही"</string>
@@ -1523,8 +1530,8 @@
<string name="tutorial_animation_content_description" msgid="2698816574982370184">"ट्यूटोरियल अॅनिमेशन थांबवण्यासाठी किंवा पुन्हा सुरू करण्यासाठी प्ले करा वर क्लिक करा."</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड बॅकलाइट"</string>
<string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d पैकी %1$d पातळी"</string>
- <string name="home_controls_dream_label" msgid="6567105701292324257">"होम कंट्रोल"</string>
- <string name="home_controls_dream_description" msgid="4644150952104035789">"स्क्रीनसेव्हर म्हणून होम कंट्रोल झटपट ॲक्सेस करा"</string>
+ <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>
<string name="back_edu_toast_content" msgid="4530314597378982956">"मागे जाण्यासाठी, टचपॅडवर तीन बोटांनी डावीकडे किंवा उजवीकडे स्वाइप करा"</string>
<string name="home_edu_toast_content" msgid="3381071147871955415">"होमवर जाण्यासाठी, टचपॅडवर तीन बोटांनी वरती स्वाइप करा"</string>
diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
index cbaefb9..ec87659 100644
--- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"बंद आहे"</item>
<item msgid="5908720590832378783">"सुरू आहे"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index bb7dcb8..997e4a0 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Alat bantu pendengaran"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Menghidupkan…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Tidak dapat melaraskan kecerahan kerana peranti\n dikawal oleh apl popular"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Tidak dapat melaraskan kecerahan kerana peranti dikawal oleh apl popular"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autoputar"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Autoputar skrin"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokasi"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"nyahpilih widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Kurangkan ketinggian"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Tambahkan ketinggian"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Tunjukkan seterusnya"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Tunjukkan sebelumnya"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget skrin kunci"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Untuk membuka apl menggunakan widget, anda perlu mengesahkan identiti anda. Selain itu, perlu diingat bahawa sesiapa sahaja boleh melihat widget tersebut, walaupun semasa tablet anda dikunci. Sesetengah widget mungkin tidak sesuai untuk skrin kunci anda dan mungkin tidak selamat untuk ditambahkan di sini."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak menyokong ciri perbualan"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Maklum balas"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Ketepikan"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Jangan tunjukkan lagi"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Pemberitahuan ini tidak boleh diubah suai."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Pemberitahuan panggilan tidak boleh diubah suai."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Kumpulan pemberitahuan ini tidak boleh dikonfigurasikan di sini"</string>
diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
index 3c78bcc..6dc9827 100644
--- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Mati"</item>
<item msgid="5908720590832378783">"Hidup"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 0219f69..e4f7154 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"အဝင်"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"နားကြားကိရိယာ"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ဖွင့်နေသည်…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"၎င်းကို ထိပ်ဆုံးရှိအက်ပ်က\n ထိန်းချုပ်နေသဖြင့် တောက်ပမှုကို ပြင်ဆင်၍မရပါ"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"၎င်းကို ထိပ်ဆုံးရှိအက်ပ်က ထိန်းချုပ်နေသဖြင့် တောက်ပမှုကို ပြင်ဆင်၍မရပါ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"အော်တို-လည်"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"မျက်နှာပြင်အား အလိုအလျောက်လှည့်ခြင်း"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"တည်နေရာ"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ဝိဂျက် ပြန်ဖြုတ်ရန်"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"အမြင့်ကို လျှော့ရန်"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"အမြင့်ကို တိုးရန်"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"နောက်တစ်ခု ပြပါ"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"ယခင်တစ်ခု ပြပါ"</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>
@@ -542,7 +544,7 @@
<string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"အားသွင်းနေစဉ် အကြိုက်ဆုံးဝိဂျက်များ၊ စခရင်နားချိန်ပုံများ ကြည့်နိုင်သည်။"</string>
<string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"စကြစို့"</string>
<string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"အားသွင်းနေစဉ် သင့်အကြိုက်ဆုံး စခရင်နားချိန်ပုံများကို ပြသည်"</string>
- <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
+ <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူပြောင်းရန်"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ဆွဲချမီနူး"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ဧည့်သည်ကို ပြန်လည် ကြိုဆိုပါသည်။"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> က စကားဝိုင်းဝန်ဆောင်မှုများကို မပံ့ပိုးပါ"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"အကြံပြုချက်"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ပယ်ရန်"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ထပ်မပြပါနှင့်"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ဤအကြောင်းကြားချက်များကို ပြုပြင်၍ မရပါ။"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ခေါ်ဆိုမှုအကြောင်းကြားချက်များကို ပြင်၍မရပါ။"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ဤအကြောင်းကြားချက်အုပ်စုကို ဤနေရာတွင် စီစဉ်သတ်မှတ်၍ မရပါ"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ခေါက်နိုင်သောစက်ကို ဖြန့်လိုက်သည်"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ခေါက်နိုင်သောစက်ကို တစ်ဘက်သို့ လှန်လိုက်သည်"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"ရှေ့စခရင် ဖွင့်ထားသည်"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"အတွင်းဘက်ဖန်သားပြင် သုံးရန် ဘေးတိုက်ပွတ်ဆွဲပါ"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"ခေါက်ထားသည်"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"ဖြန့်ထားသည်"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml
index 9675cb5..424b4b9 100644
--- a/packages/SystemUI/res/values-my/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ပိတ်"</item>
<item msgid="5908720590832378783">"ဖွင့်"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 15e568b..6ee6cc2 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Innenhet"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Høreapparater"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Slår på …"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kan ikke justere lysstyrken, fordi den\n kontrolleres av appen på toppen"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kan ikke justere lysstyrken, fordi den kontrolleres av appen på toppen"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotér automatisk"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotér skjermen automatisk"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Sted"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"velg bort modul"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Reduser høyden"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Øk høyden"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Vis neste"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Vis forrige"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> støtter ikke samtalefunksjoner"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Tilbakemelding"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Lukk"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ikke vis igjen"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Disse varslene kan ikke endres."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Anropsvarsler kan ikke endres."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Denne varselgruppen kan ikke konfigureres her"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En foldbar enhet blir brettet ut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En foldbar enhet blir snudd"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Frontskjermen er slått på"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Dra for å bruke den indre skjermen"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"lagt sammen"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"åpen"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
index bd5b692..bbeafd8 100644
--- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Av"</item>
<item msgid="5908720590832378783">"På"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 02285f2..90a1923 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"इनपुट"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"हियरिङ डिभाइसहरू"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"सक्रिय गर्दै…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"टप एपले चमक नियन्त्रण गरिरहेकाले\n चमक मिलाउन मिल्दैन"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"टप एपले चमक नियन्त्रण गरिरहेकाले चमक मिलाउन मिल्दैन"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"अटो रोटेट"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"स्क्रिन स्वतःघुम्ने"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"लोकेसन"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"विजेटको चयन रद्द गर्नुहोस्"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"उचाइ घटाउनुहोस्"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"उचाइ बढाउनुहोस्"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"अर्को देखाउनुहोस्"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"अघिल्लो देखाउनुहोस्"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा वार्तालापसम्बन्धी सुविधा प्रयोग गर्न मिल्दैन"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"प्रतिक्रिया"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"हटाउनुहोस्"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"फेरि नदेखाउनुहोस्"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"यी सूचनाहरू परिमार्जन गर्न मिल्दैन।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कलसम्बन्धी सूचनाहरू परिमार्जन गर्न मिल्दैन।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"यहाँबाट सूचनाहरूको यो समूह कन्फिगर गर्न सकिँदैन"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्डेबल डिभाइस अनफोल्ड गरेको देखाइएको एनिमेसन"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्डेबल डिभाइस यताउता पल्टाएर देखाइएको एनिमेसन"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"अगाडिको स्क्रिन अन गरिएको छ"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"भित्री स्क्रिन प्रयोग गर्न स्लाइड गर्नुहोस्"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"फोल्ड गरिएको"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"अनफोल्ड गरिएको"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
index 2dd209d..de3baa0 100644
--- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"अफ छ"</item>
<item msgid="5908720590832378783">"अन छ"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 99c8838..ee0ef9d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Invoer"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hoortoestellen"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aanzetten…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kan de helderheid niet aanpassen omdat deze wordt\n beheerd door de bovenste app"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Kan de helderheid niet aanpassen omdat deze wordt beheerd door de bovenste app"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatisch draaien"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Scherm automatisch draaien"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Locatie"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"widget deselecteren"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Hoogte verkleinen"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Hoogte vergroten"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Volgende tonen"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Vorige tonen"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets op het vergrendelscherm"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Als je een app wilt openen met een widget, moet je verifiëren dat jij het bent. Houd er ook rekening mee dat iedereen ze kan bekijken, ook als je tablet vergrendeld is. Bepaalde widgets zijn misschien niet bedoeld voor je vergrendelscherm en kunnen hier niet veilig worden toegevoegd."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ondersteunt geen gespreksfuncties"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Sluiten"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Niet meer tonen"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Deze meldingen kunnen niet worden aangepast."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Gespreksmeldingen kunnen niet worden aangepast."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Deze groep meldingen kan hier niet worden ingesteld"</string>
diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
index 221749c..90572b6 100644
--- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Uit"</item>
<item msgid="5908720590832378783">"Aan"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 5847a9a..d5ac685 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -128,8 +128,8 @@
<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>
- <string name="screenrecord_save_text" msgid="3008973099800840163">"ଦେଖିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"ସ୍କ୍ରିନ ରେକର୍ଡିଂ ସେଭ କରାଯାଇଛି"</string>
+ <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>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ଇନପୁଟ୍"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ଅନ୍ ହେଉଛି…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ଟପ ଆପ ଦ୍ୱାରା ଉଜ୍ଜ୍ୱଳତା ନିୟନ୍ତ୍ରିତ\nହେଉଥିବା ଯୋଗୁଁ ଏହାକୁ ଆଡଜଷ୍ଟ କରିପାରିବେ ନାହିଁ"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ଟପ ଆପ ଦ୍ୱାରା ଉଜ୍ଜ୍ୱଳତା ନିୟନ୍ତ୍ରିତହେଉଥିବା ଯୋଗୁଁ ଏହାକୁ ଆଡଜଷ୍ଟ କରିପାରିବେ ନାହିଁ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ଅଟୋ-ରୋଟେଟ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ଅଟୋ-ରୋଟେଟ ସ୍କ୍ରିନ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ଲୋକେସନ"</string>
@@ -360,7 +360,7 @@
<string name="quick_settings_connected" msgid="3873605509184830379">"ସଂଯୁକ୍ତ"</string>
<string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"କନେକ୍ଟ ରହିଛି, ବ୍ୟାଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="quick_settings_connecting" msgid="2381969772953268809">"ସଂଯୋଗ କରୁଛି..."</string>
- <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"ହଟସ୍ପଟ୍"</string>
+ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"ହଟସ୍ପଟ"</string>
<string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"ଚାଲୁ ହେଉଛି…"</string>
<string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"ଡାଟା ସେଭର୍ ଅନ୍ ଅଛି"</string>
<string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{#ଟି ଡିଭାଇସ}other{#ଟି ଡିଭାଇସ}}"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ୱିଜେଟକୁ ଅଚୟନ କରନ୍ତୁ"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ଉଚ୍ଚତାକୁ କମ କରନ୍ତୁ"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ଉଚ୍ଚତାକୁ ବଢ଼ାନ୍ତୁ"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"ପରବର୍ତ୍ତୀ ନେଭିଗେସନ ପଏଣ୍ଟ ଦେଖାନ୍ତୁ"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"ପୂର୍ବବର୍ତ୍ତୀ ଦେଖାନ୍ତୁ"</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>
@@ -757,7 +759,7 @@
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ହେଲେ"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> ବେଳେ"</string>
- <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"ହଟସ୍ପଟ୍"</string>
+ <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"ହଟସ୍ପଟ"</string>
<string name="accessibility_status_bar_satellite_no_connection" msgid="3001571744269917762">"ସାଟେଲାଇଟ, କୌଣସି କନେକ୍ସନ ନାହିଁ"</string>
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ସାଟେଲାଇଟ, ଦୁର୍ବଳ କନେକ୍ସନ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ସାଟେଲାଇଟ, ଭଲ କନେକ୍ସନ"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବାର୍ତ୍ତାଳାପ ଫିଚରଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ ନାହିଁ"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ମତାମତ"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ଖାରଜ କରନ୍ତୁ"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ପୁଣି ଶୋ କରନ୍ତୁ ନାହିଁ"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିବର୍ତ୍ତନ କରିହେବ ନାହିଁ।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"କଲ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରାଯାଇପାରିବ ନାହିଁ।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ଏଠାରେ ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଗ୍ରୁପ୍ କନଫ୍ୟୁଗର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
@@ -955,7 +962,7 @@
<item msgid="5874146774389433072">"ଡାହାଣକୁ-ଆଉଜେଇବା"</item>
</string-array>
<string name="save" msgid="3392754183673848006">"ସେଭ କରନ୍ତୁ"</string>
- <string name="reset" msgid="8715144064608810383">"ରିସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="reset" msgid="8715144064608810383">"ରିସେଟ କରନ୍ତୁ"</string>
<string name="clipboard" msgid="8517342737534284617">"କ୍ଲିପ୍ବୋର୍ଡ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"କଷ୍ଟମ୍ ନାଭିଗେଶନ୍ ବଟନ୍"</string>
<string name="left_keycode" msgid="8211040899126637342">"ବାମ କୀ\'କୋଡ୍"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଅନଫୋଲ୍ଡ କରାଯାଉଛି"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଫ୍ଲିପ କରାଯାଉଛି"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"ସାମ୍ନା ସ୍କ୍ରିନ ଚାଲୁ ଅଛି"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"ଭିତର ସ୍କ୍ରିନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ସ୍ଲାଇଡ କରନ୍ତୁ"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"ଫୋଲ୍ଡେଡ"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"ଅନଫୋଲ୍ଡେଡ"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml
index 8d23073..c9c3198 100644
--- a/packages/SystemUI/res/values-or/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ବନ୍ଦ ଅଛି"</item>
<item msgid="5908720590832378783">"ଚାଲୁ ଅଛି"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 17757b8..2499518 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ਇਨਪੁੱਟ"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ਚਮਕ ਨੂੰ ਵਿਵਸਥਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਕਿਉਂਕਿ ਇਹ ਪਹਿਲਾਂ ਚੱਲ ਰਹੀ ਐਪ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕਰਨ ਕਰਕੇ \n ਹੋ ਰਿਹਾ ਹੈ"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ਚਮਕ ਨੂੰ ਵਿਵਸਥਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਕਿਉਂਕਿ ਇਹ ਪਹਿਲਾਂ ਚੱਲ ਰਹੀ ਐਪ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕਰਨ ਕਰਕੇ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ਸਵੈ-ਘੁਮਾਓ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ਸਕ੍ਰੀਨ ਨੂੰ ਆਪਣੇ ਆਪ ਘੁੰਮਾਓ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ਟਿਕਾਣਾ"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ਵਿਜੇਟ ਨੂੰ ਅਣਚੁਣਿਆ ਕਰੋ"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ਉਚਾਈ ਘਟਾਓ"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ਉਚਾਈ ਵਧਾਓ"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"ਅਗਲਾ ਦਿਖਾਓ"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"ਪਿਛਲਾ ਦਿਖਾਓ"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਗੱਲਬਾਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ਵਿਚਾਰ"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ਖਾਰਜ ਕਰੋ"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ਕਾਲ ਸੰਬੰਧੀ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ਇਹ ਸੂਚਨਾਵਾਂ ਦਾ ਗਰੁੱਪ ਇੱਥੇ ਸੰਰੂਪਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
index 0f53e5d..eeb9a5b 100644
--- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ਬੰਦ"</item>
<item msgid="5908720590832378783">"ਚਾਲੂ"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c0a2831..71b5ace 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Wejście"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Aparaty słuchowe"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Włączam…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nie można dostosować jasności, ponieważ jest ona\nkontrolowana przez aplikację na pierwszym planie"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nie można dostosować jasności, ponieważ jest onakontrolowana przez aplikację na pierwszym planie"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autoobracanie"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Autoobracanie ekranu"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokalizacja"</string>
@@ -391,7 +391,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"Komunikacja NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Komunikacja NFC jest wyłączona"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Komunikacja NFC jest włączona"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Nagraj ekran"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Nagrywanie ekranu"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Rozpocznij"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zatrzymaj"</string>
<string name="qs_record_issue_label" msgid="8166290137285529059">"Zarejestruj problem"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"odznacz widżet"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Zmniejsz wysokość"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Zwiększ wysokość"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Pokaż następny"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Pokaż poprzedni"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje funkcji rozmów"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Opinia"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Zamknij"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Nie pokazuj ponownie"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Tych powiadomień nie można zmodyfikować."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Powiadomień o połączeniach nie można modyfikować."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Tej grupy powiadomień nie można tu skonfigurować"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Składane urządzenie jest rozkładane"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Składane urządzenie jest obracane"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Ekran przedni jest włączony"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Przesuń palcem, aby używać wewnętrznego ekranu"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"po zamknięciu"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"po otwarciu"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index c9eb500..bc59a90 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Wyłączony"</item>
<item msgid="5908720590832378783">"Włączony"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c1a8ec4..2a8aabe 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -328,13 +328,13 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Aparelhos auditivos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Ativando…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Não é possível ajustar o brilho, porque ele está sendo\n controlado pelo app principal"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Não é possível ajustar o brilho, porque ele está sendo controlado pelo app principal"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Giro automático da tela"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localização"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Protetor de tela"</string>
- <string name="quick_settings_camera_label" msgid="5612076679385269339">"Acesso à câmera"</string>
- <string name="quick_settings_mic_label" msgid="8392773746295266375">"Acesso ao microfone"</string>
+ <string name="quick_settings_camera_label" msgid="5612076679385269339">"Câmera"</string>
+ <string name="quick_settings_mic_label" msgid="8392773746295266375">"Microfone"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Disponível"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Bloqueada"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo de mídia"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desmarcar widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Diminuir altura"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Aumentar altura"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostrar próximo"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostrar anterior"</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ê precisa confirmar sua identidade. E não se esqueça que qualquer pessoa pode ver os widgets, mesmo com o tablet bloqueado. Além disso, alguns apps não foram criados para a tela de bloqueio, é melhor manter a segurança."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Enviar feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Dispensar"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Não mostrar novamente"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar essas notificações."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamada."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar esse grupo de notificações aqui"</string>
@@ -1524,7 +1531,7 @@
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
<string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
<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="home_controls_dream_description" msgid="4644150952104035789">"Controle de automação no protetor de tela"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Desfazer"</string>
<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>
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 9ddc41c..3e75cdd 100644
--- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Desativado"</item>
<item msgid="5908720590832378783">"Ativado"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 36384bc..bb68610 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -128,7 +128,7 @@
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar toques no ecrã"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Partilhar"</string>
- <string name="screenrecord_save_title" msgid="1886652605520893850">"Gravação de ecrã guardada."</string>
+ <string name="screenrecord_save_title" msgid="1886652605520893850">"Gravação de ecrã guardada"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Toque para ver"</string>
<string name="screenrecord_save_error" msgid="5862648532560118815">"Erro ao guardar a gravação de ecrã"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Ocorreu um erro ao iniciar a gravação do ecrã."</string>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Aparelhos auditivos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"A ativar..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Não é possível ajustar o brilho porque está a ser\n controlado pela app principal"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Não é possível ajustar o brilho porque está a ser controlado pela app principal"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotação auto."</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rodar o ecrã automaticamente"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localização"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desmarcar widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Diminuir altura"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Aumentar altura"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostrar próximo"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostrar anterior"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets do ecrã de bloqueio"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir uma app através de um widget, vai ter de validar a sua identidade. Além disso, tenha em atenção que qualquer pessoa pode ver os widgets, mesmo quando o tablet estiver bloqueado. Alguns widgets podem não se destinar ao ecrã de bloqueio e pode ser inseguro adicioná-los aqui."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> não suporta funcionalidades de conversa."</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Ignorar"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Não mostrar novamente"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar estas notificações."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamadas."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar este grupo de notificações aqui."</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 5baa61c..7e7e673 100644
--- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Desativado"</item>
<item msgid="5908720590832378783">"Ativado"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c1a8ec4..2a8aabe 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -328,13 +328,13 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Aparelhos auditivos"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Ativando…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Não é possível ajustar o brilho, porque ele está sendo\n controlado pelo app principal"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Não é possível ajustar o brilho, porque ele está sendo controlado pelo app principal"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Giro automático da tela"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localização"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Protetor de tela"</string>
- <string name="quick_settings_camera_label" msgid="5612076679385269339">"Acesso à câmera"</string>
- <string name="quick_settings_mic_label" msgid="8392773746295266375">"Acesso ao microfone"</string>
+ <string name="quick_settings_camera_label" msgid="5612076679385269339">"Câmera"</string>
+ <string name="quick_settings_mic_label" msgid="8392773746295266375">"Microfone"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Disponível"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Bloqueada"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo de mídia"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"desmarcar widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Diminuir altura"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Aumentar altura"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Mostrar próximo"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Mostrar anterior"</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ê precisa confirmar sua identidade. E não se esqueça que qualquer pessoa pode ver os widgets, mesmo com o tablet bloqueado. Além disso, alguns apps não foram criados para a tela de bloqueio, é melhor manter a segurança."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Enviar feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Dispensar"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Não mostrar novamente"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar essas notificações."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamada."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar esse grupo de notificações aqui"</string>
@@ -1524,7 +1531,7 @@
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
<string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
<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="home_controls_dream_description" msgid="4644150952104035789">"Controle de automação no protetor de tela"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Desfazer"</string>
<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>
diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
index 9ddc41c..3e75cdd 100644
--- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Desativado"</item>
<item msgid="5908720590832378783">"Ativado"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index beb3c116..6221d49 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Intrare"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Aparate auditive"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Se activează..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nu se poate ajusta luminozitatea deoarece este\n controlată de aplicația de top"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Nu se poate ajusta luminozitatea deoarece este controlată de aplicația de top"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotire automată"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotirea automată a ecranului"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Locație"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"deselectează widgetul"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Redu înălțimea"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Crește înălțimea"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Afișează elementul următor"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Afișează elementul anterior"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu acceptă funcții pentru conversații"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Închide"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Nu mai afișa"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Aceste notificări nu pot fi modificate."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Notificările pentru apeluri nu pot fi modificate."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Acest grup de notificări nu poate fi configurat aici"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispozitiv pliabil care este desfăcut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispozitiv pliabil care este întors"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Ecranul frontal este activat"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Glisează pentru a folosi ecranul interior"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"închis"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"deschis"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index 528b112..6dcb0d3 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Dezactivat"</item>
<item msgid="5908720590832378783">"Activat"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e3f852c..4c14616 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -129,7 +129,7 @@
<string name="screenrecord_stop_label" msgid="72699670052087989">"Остановить"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Поделиться"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"Видео с экрана сохранено"</string>
- <string name="screenrecord_save_text" msgid="3008973099800840163">"Нажмите, чтобы посмотреть."</string>
+ <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>
@@ -162,7 +162,7 @@
<string name="issuerecord_ongoing_screen_only" msgid="6248206059935015722">"Записываем проблему на видео"</string>
<string name="issuerecord_share_label" msgid="3992657993619876199">"Поделиться"</string>
<string name="issuerecord_save_title" msgid="4161043023696751591">"Запись сохранена."</string>
- <string name="issuerecord_save_text" msgid="1205985304551521495">"Нажмите, чтобы посмотреть."</string>
+ <string name="issuerecord_save_text" msgid="1205985304551521495">"Нажмите, чтобы посмотреть"</string>
<string name="issuerecord_save_error" msgid="6913040083446722726">"Не удалось сохранить запись."</string>
<string name="issuerecord_start_error" msgid="3402782952722871190">"Не удалось начать запись."</string>
<string name="immersive_cling_title" msgid="8372056499315585941">"Полноэкранный режим"</string>
@@ -328,14 +328,14 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Устройство ввода"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Слуховые аппараты"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Включение…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Невозможно изменить яркость,\nтак как она регулируется общими настройками."</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Невозможно изменить яркость,так как она регулируется общими настройками."</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоповорот"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоповорот экрана"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Геолокация"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Заставка"</string>
<string name="quick_settings_camera_label" msgid="5612076679385269339">"Доступ к камере"</string>
<string name="quick_settings_mic_label" msgid="8392773746295266375">"Доступ к микрофону"</string>
- <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Есть"</string>
+ <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Разрешен"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Заблокировано"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Режим медиа"</string>
<string name="quick_settings_user_title" msgid="8673045967216204537">"Пользователь"</string>
@@ -381,7 +381,7 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Тёмная тема"</string>
- <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Режим энергосбер."</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Энергосбережение"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вкл. на закате"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До рассвета"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"отменить выбор виджета"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Уменьшить высоту"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Увеличить высоту"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Показать следующий"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Показать предыдущий"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает функции разговоров."</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Оставить отзыв"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Закрыть"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Больше не показывать"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Эти уведомления нельзя изменить."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Уведомления о звонках нельзя изменить."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Эту группу уведомлений нельзя настроить здесь."</string>
diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
index 43d3e2a..e7ff74d 100644
--- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Отключено"</item>
<item msgid="5908720590832378783">"Включено"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 9ff6747..fb8ce18 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ආදානය"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"ශ්රවණාධාරක"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ක්රියාත්මක කරමින්…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ඉහළ යෙදුම මඟින් එය පාලනය වන නිසා\nදීප්තිය ගැළපුම් කළ නොහැක"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ඉහළ යෙදුම මඟින් එය පාලනය වන නිසාදීප්තිය ගැළපුම් කළ නොහැක"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ස්වයංක්රීය කරකැවීම"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ස්වයංක්රීයව-භ්රමණය වන තිරය"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ස්ථානය"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"විජට් නොතෝරන්න"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"උස අඩු කරන්න"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"උස වැඩි කරන්න"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"මීළග පෙන්වන්න"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"පෙර එක පෙන්වන්න"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> සංවාද විශේෂාංගවලට සහාය නොදක්වයි"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ප්රතිපෝෂණය"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"අස් කරන්න"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"නැවත නොපෙන්වන්න"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"මෙම දැනුම්දීම් වෙනස් කළ නොහැක."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ඇමතුම් දැනුම්දීම් වෙනස් කළ නොහැකිය."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"මෙම දැනුම්දීම් සමූහය මෙහි වින්යාස කළ නොහැක"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"දිග හැරෙමින් පවතින නැමිය හැකි උපාංගය"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"වටා පෙරළෙමින් තිබෙන නැමිය හැකි උපාංගය"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"ඉදිරිපස තිරය ක්රියාත්මකයි"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"අභ්යන්තර තිරය භාවිතා කිරීමට ස්ලයිඩ් කරන්න"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"නැවූ"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"නොනැවූ"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml
index 91280e1..710e9aa 100644
--- a/packages/SystemUI/res/values-si/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ක්රියාවිරහිතයි"</item>
<item msgid="5908720590832378783">"ක්රියාත්මකයි"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index a42eb1e..2dba462 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vstup"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Načúvadlá"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Zapína sa…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Jas sa nedá upraviť, pretože ho \n ovláda horná aplikácia"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Jas sa nedá upraviť, pretože ho ovláda horná aplikácia"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatické otáčanie"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatické otáčanie obrazovky"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Poloha"</string>
@@ -354,7 +354,7 @@
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzia farieb"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Úprava farieb"</string>
<string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Veľkosť písma"</string>
- <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Spravovať použ."</string>
+ <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Spravovať používateľov"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zavrieť"</string>
<string name="quick_settings_connected" msgid="3873605509184830379">"Pripojené"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"zrušiť výber miniaplikácie"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Znížiť výšku"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Zväčšiť výšku"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Zobraziť ďalší"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Zobraziť predchádzajúci"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nepodporuje funkcie konverzácie"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Spätná väzba"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Zavrieť"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Nabudúce nezobrazovať"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Tieto upozornenia sa nedajú upraviť."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornenia na hovory sa nedajú upraviť."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Túto skupinu upozornení nejde na tomto mieste konfigurovať"</string>
@@ -1349,7 +1356,7 @@
<string name="clipboard_image_preview" msgid="2156475174343538128">"Ukážka obrázka"</string>
<string name="clipboard_edit" msgid="4500155216174011640">"upraviť"</string>
<string name="add" msgid="81036585205287996">"Pridať"</string>
- <string name="manage_users" msgid="1823875311934643849">"Spravovať použ."</string>
+ <string name="manage_users" msgid="1823875311934643849">"Spravovať používateľov"</string>
<string name="drag_split_not_supported" msgid="7173481676120546121">"Toto upozornenie nepodporuje presun na rozdelenú obrazovku"</string>
<string name="dream_overlay_location_active" msgid="6484763493158166618">"Aktívne miesto"</string>
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nie je k dispozícii"</string>
@@ -1524,7 +1531,7 @@
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvietenie klávesnice"</string>
<string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. úroveň z %2$d"</string>
<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="home_controls_dream_description" msgid="4644150952104035789">"Rýchle ovládanie domácnosti z šetriča obrazovky"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Vrátiť späť"</string>
<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>
diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
index 0b0b894..8323506 100644
--- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Vypnuté"</item>
<item msgid="5908720590832378783">"Zapnuté"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c0e751b..dd86710 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vhodna naprava"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Slušni aparati"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Vklapljanje …"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Svetlosti ni mogoče prilagoditi, ker jo\n nadzoruje aplikacija na vrhu"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Svetlosti ni mogoče prilagoditi, ker jo nadzoruje aplikacija na vrhu"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Samodejno sukanje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Samodejno sukanje zaslona"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"preklic izbire pripomočka"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Zmanjšanje višine"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Povečanje višine"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Prikaz naslednjega"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Prikaz prejšnjega"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podpira pogovornih funkcij."</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Povratne informacije"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Opusti"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Tega ne prikaži več"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Za ta obvestila ni mogoče spremeniti nastavitev."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obvestil o klicih ni mogoče spreminjati."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Te skupine obvestil ni mogoče konfigurirati tukaj"</string>
diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
index f9ccbb1..d644038 100644
--- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Izklopljeno"</item>
<item msgid="5908720590832378783">"Vklopljeno"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 06cefd9c..2532c03 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Hyrja"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Aparatet e dëgjimit"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Po aktivizohet…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ndriçimi nuk mund të rregullohet pasi\n po kontrollohet nga aplikacioni i sipërm"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ndriçimi nuk mund të rregullohet pasi po kontrollohet nga aplikacioni i sipërm"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rrotullim automatik"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rrotullimi automatik i ekranit"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Vendndodhja"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anulo zgjedhjen e miniaplikacionit"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Zvogëlo lartësinë"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Rrit lartësinë"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Shfaq tjetrin"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Shfaq të mëparshmin"</string>
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Miniaplikacionet në ekranin e kyçjes"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mbështet veçoritë e bisedës"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Koment"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Hiq"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Mos e shfaq më"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Këto njoftime nuk mund të modifikohen."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Njoftimet e telefonatave nuk mund të modifikohen."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ky grup njoftimesh nuk mund të konfigurohet këtu"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Pajisja e palosshme duke u hapur"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Pajisja e palosshme duke u rrotulluar"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Ekrani i përparmë është aktivizuar"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Rrëshqit për të përdorur ekranin e brendshëm"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"palosur"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"shpalosur"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index 1ab4f01..1b1a62f 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Joaktive"</item>
<item msgid="5908720590832378783">"Aktive"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 3977058..3ccad52 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Унос"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Слушни апарати"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Укључује се..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не можете да прилагодите осветљеност јер је\n контролише апликација у врху"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не можете да прилагодите осветљеност јер је контролише апликација у врху"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Аутоматска ротација"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Аутоматско ротирање екрана"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Локација"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"поништи избор виџета"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Смањи висину"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Повећај висину"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Прикажите следеће"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Прикажите претходно"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не подржава функције конверзације"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Повратне информације"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Одбаци"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Не приказуј поново"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ова обавештења не могу да се мењају."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Обавештења о позивима не могу да се мењају."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ова група обавештења не може да се конфигурише овде"</string>
@@ -1370,7 +1377,7 @@
<string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Промените излаз"</string>
<string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Непознато"</string>
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"с:мин"</string>
- <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"ч:мин"</string>
+ <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Желите да дозволите да <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> приступа свим евиденцијама уређаја?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Дозволи једнократан приступ"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Не дозволи"</string>
diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
index ec5f10f..e1bd7b1 100644
--- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Искључено"</item>
<item msgid="5908720590832378783">"Укључено"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7051a2a..cab91b1 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ingång"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hörapparater"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiverar …"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Det går inte att justera ljusstyrkan eftersom den\n styrs av den översta appen"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Det går inte att justera ljusstyrkan eftersom den styrs av den översta appen"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotera automatiskt"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotera skärmen automatiskt"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Plats"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"avmarkera widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Minska höjden"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Öka höjden"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Visa nästa"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Visa föregående"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inte stöd för konversationsfunktioner"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Stäng"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Visa inte igen"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Det går inte att ändra de här aviseringarna."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Det går inte att ändra samtalsaviseringarna."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Den här aviseringsgruppen kan inte konfigureras här"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En vikbar enhet viks upp"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En vikbar enhet vänds"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Den främre skärmen har aktiverats"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Dra för att använda den inre skärmen"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"hopvikt"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"uppvikt"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
index e9da805..37d757e 100644
--- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Av"</item>
<item msgid="5908720590832378783">"På"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 2ead01a..6cb3abf 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -328,14 +328,14 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vifaa vya kuingiza sauti"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Visaidizi vya kusikia"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Inawasha..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Imeshindwa kurekebisha mwangaza kwa sababu\n inadhibitiwa na programu inayotumika"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Imeshindwa kurekebisha mwangaza kwa sababu inadhibitiwa na programu inayotumika"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Zungusha kiotomatiki"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Skrini ijizungushe kiotomatiki"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Mahali"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Taswira ya skrini"</string>
<string name="quick_settings_camera_label" msgid="5612076679385269339">"Ufikiaji wa kamera"</string>
<string name="quick_settings_mic_label" msgid="8392773746295266375">"Ufikiaji wa maikrofoni"</string>
- <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Unapatikana"</string>
+ <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Inapatikana"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Umezuiwa"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Kifaa cha faili"</string>
<string name="quick_settings_user_title" msgid="8673045967216204537">"Mtumiaji"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"acha kuchagua wijeti"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Punguza urefu"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Ongeza urefu"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Onyesha inayofuata"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Onyesha iliyotangulia"</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>
@@ -573,7 +575,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Unaporuhusu ufikiaji wa programu, chochote kinachoonyeshwa au kuchezwa katika programu hiyo kitaonekana kwa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ruhusu ufikiaji wa skrini"</string>
<string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> imezima chaguo hili"</string>
- <string name="media_projection_entry_share_app_selector_title" msgid="1419515119767501822">"Kuchagua programu utakayoruhusu ifikiwe"</string>
+ <string name="media_projection_entry_share_app_selector_title" msgid="1419515119767501822">"Chagua programu utakayoruhusu ifikiwe"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Ungependa kutuma maudhui yaliyo katika skrini yako?"</string>
<string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Tuma maudhui ya programu moja"</string>
<string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Tuma maudhui katika skrini nzima"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> haitumii vipengele vya mazungumzo"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Maoni"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Ondoa"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Usionyeshe tena"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Arifa hizi haziwezi kubadilishwa."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Arifa za simu haziwezi kubadilishwa."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Kikundi hiki cha arifa hakiwezi kuwekewa mipangilio hapa"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Kifaa kinachokunjwa kikikunjuliwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Kifaa kinachokunjwa kikigeuzwa"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Umewasha skrini ya mbele"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Telezesha kidole ili utumie skrini ya ndani"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"kimekunjwa"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"kimefunguliwa"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
index 702af45..fae42c3 100644
--- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
@@ -64,12 +64,12 @@
<string-array name="tile_states_rotation">
<item msgid="4578491772376121579">"Hakipatikani"</item>
<item msgid="5776427577477729185">"Kimezimwa"</item>
- <item msgid="7105052717007227415">"Kimewashwa"</item>
+ <item msgid="7105052717007227415">"Imewashwa"</item>
</string-array>
<string-array name="tile_states_bt">
<item msgid="5330252067413512277">"Hakipatikani"</item>
<item msgid="5315121904534729843">"Kimezimwa"</item>
- <item msgid="503679232285959074">"Kimewashwa"</item>
+ <item msgid="503679232285959074">"Imewashwa"</item>
</string-array>
<string-array name="tile_states_airplane">
<item msgid="1985366811411407764">"Hakipatikani"</item>
@@ -93,7 +93,7 @@
</string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Hakipatikani"</item>
- <item msgid="9103697205127645916">"Kimezimwa"</item>
+ <item msgid="9103697205127645916">"Umezimwa"</item>
<item msgid="8067744885820618230">"Kimewashwa"</item>
</string-array>
<string-array name="tile_states_saver">
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Limezimwa"</item>
<item msgid="5908720590832378783">"Limewashwa"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index b37350c..32fa794 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"உள்ளீடு"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"செவித்துணைக் கருவி"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ஆன் செய்கிறது…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"சிறந்த ஆப்ஸால் ஒளிர்வு கட்டுப்படுத்தப்படுவதால்\n இதைச் சரிசெய்ய முடியவில்லை"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"சிறந்த ஆப்ஸால் ஒளிர்வு கட்டுப்படுத்தப்படுவதால் இதைச் சரிசெய்ய முடியவில்லை"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"தானாகச் சுழற்று"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"திரையைத் தானாகச் சுழற்று"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"இருப்பிடம்"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"விட்ஜெட்டைத் தேர்வுநீக்கும்"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"உயரத்தைக் குறைக்கும்"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"உயரத்தை அதிகரிக்கும்"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"அடுத்ததைக் காட்டும்"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"முந்தையதைக் காட்டும்"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"உரையாடல் அம்சங்களை <xliff:g id="APP_NAME">%1$s</xliff:g> ஆதரிக்காது"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"கருத்து"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"மூடுக"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"மீண்டும் காட்டாதே"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"இந்த அறிவிப்புகளை மாற்ற இயலாது."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"அழைப்பு அறிவிப்புகளை மாற்ற முடியாது."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"இந்த அறிவுப்புக் குழுக்களை இங்கே உள்ளமைக்க இயலாது"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"மடக்கத்தக்க சாதனம் திறக்கப்படுகிறது"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"மடக்கத்தக்க சாதனம் ஃபிளிப் செய்யப்பட்டு திருப்பப்படுகிறது"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"முன்பக்கத் திரை இயக்கப்பட்டுள்ளது"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"உட்புறத் திரையைப் பயன்படுத்த ஸ்லைடு செய்யுங்கள்"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"மடக்கப்பட்டது"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"விரிக்கப்பட்டது"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
index 17cc570..b09b17f 100644
--- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"முடக்கப்பட்டுள்ளது"</item>
<item msgid="5908720590832378783">"இயக்கப்பட்டுள்ளது"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index f64c737..f3084a9 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ఇన్పుట్"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"వినికిడి పరికరాలు"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ఆన్ చేస్తోంది…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ఇది టాప్ యాప్ ద్వారా\n కంట్రోల్ చేయబడుతున్నందున బ్రైట్నెస్ను సర్దుబాటు చేయడం సాధ్యం కాదు"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ఇది టాప్ యాప్ ద్వారా కంట్రోల్ చేయబడుతున్నందున బ్రైట్నెస్ను సర్దుబాటు చేయడం సాధ్యం కాదు"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ఆటో-రొటేట్"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"స్క్రీన్ ఆటో-రొటేట్"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"లొకేషన్"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"విడ్జెట్ ఎంపిక రద్దు చేయండి"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ఎత్తును తగ్గించండి"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"ఎత్తును పెంచండి"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"తర్వాతది చూడండి"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"మునుపటి దాన్ని చూడండి"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> సంభాషణ ఫీచర్లను సపోర్ట్ చేయదు"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ఫీడ్బ్యాక్"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"విస్మరించండి"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"మళ్లీ చూపవద్దు"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ఈ నోటిఫికేషన్లను ఎడిట్ చేయడం వీలుపడదు."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"కాల్ నోటిఫికేషన్లను ఎడిట్ చేయడం సాధ్యం కాదు."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ఈ నోటిఫికేషన్ల గ్రూప్ను ఇక్కడ కాన్ఫిగర్ చేయలేము"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"మడవగల పరికరం విప్పబడుతోంది"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"మడవగల పరికరం చుట్టూ తిప్పబడుతోంది"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"ముందు వైపు స్క్రీన్ ఆన్ అయింది"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"లోపలి స్క్రీన్ను ఉపయోగించడానికి స్లయిడ్ చేయండి"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"మడిచే సదుపాయం గల పరికరం"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"మడిచే సదుపాయం లేని పరికరం"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml
index 8a0ab484..7562aae 100644
--- a/packages/SystemUI/res/values-te/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ఆఫ్లో ఉంది"</item>
<item msgid="5908720590832378783">"ఆన్లో ఉంది"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 316aab0..3fac78f 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"อินพุต"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"เครื่องช่วยฟัง"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"กำลังเปิด..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ปรับความสว่างไม่ได้เนื่องจาก\nควบคุมโดยแอปที่อยู่ด้านบน"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"ปรับความสว่างไม่ได้เนื่องจากควบคุมโดยแอปที่อยู่ด้านบน"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"หมุนอัตโนมัติ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"หมุนหน้าจออัตโนมัติ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ตำแหน่ง"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ยกเลิกการเลือกวิดเจ็ต"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"ลดความสูง"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"เพิ่มความสูง"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"แสดงมีเดียเพลเยอร์ถัดไป"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"แสดงมีเดียเพลเยอร์ก่อนหน้า"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่รองรับฟีเจอร์การสนทนา"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"ความคิดเห็น"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"ปิด"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ไม่ต้องแสดงอีก"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"แก้ไขการแจ้งเตือนเหล่านี้ไม่ได้"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"แก้ไขการแจ้งเตือนสายเรียกเข้าไม่ได้"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"การแจ้งเตือนกลุ่มนี้กำหนดค่าที่นี่ไม่ได้"</string>
diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml
index 4db59c0..6d36036 100644
--- a/packages/SystemUI/res/values-th/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"ปิด"</item>
<item msgid="5908720590832378783">"เปิด"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 04dc6c7..8e87e84 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Mga hearing aid"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Ino-on…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Hindi ma-adjust ang liwanag dahil\n kinokontrol ito ng nangingibabaw na app"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Hindi ma-adjust ang liwanag dahil kinokontrol ito ng nangingibabaw na app"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"I-auto rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Awtomatikong i-rotate ang screen"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokasyon"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"i-unselect ang widget"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Bawasan ang taas"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Dagdagan ang taas"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Ipakita ang susunod"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Ipakita ang mga nakaraan"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"Hindi sinusuportahan ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang mga feature ng pag-uusap"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Feedback"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"I-dismiss"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Huwag nang ipakita ulit"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Hindi puwedeng baguhin ang mga notification na ito."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Hindi mabago ang mga notification ng tawag."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Hindi mako-configure dito ang pangkat na ito ng mga notification"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ina-unfold na foldable na device"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Fini-flip na foldable na device"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Na-on ang screen sa harap"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"I-slide para gamitin ang inner screen"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"naka-fold"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"hindi naka-fold"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
index 4832d1d..112c0bf 100644
--- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Naka-off"</item>
<item msgid="5908720590832378783">"Naka-on"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f4a2c92..474c53f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Giriş"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"İşitme cihazları"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Açılıyor…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Parlaklık ayarlanamıyor, çünkü bu özellik\n en üstteki uygulama tarafından kontrol ediliyor"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Parlaklık ayarlanamıyor, çünkü bu özellik en üstteki uygulama tarafından kontrol ediliyor"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Otomatik döndür"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranı otomatik döndür"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Konum"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"widget\'ın seçimini kaldırın"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Yüksekliği azalt"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Yüksekliği artır"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Sonrakini göster"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Öncekini göster"</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>
@@ -542,7 +544,7 @@
<string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Cihazınız şarj olurken en sevdiğiniz widget\'lara ve ekran koruyuculara erişin."</string>
<string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Başlayalım"</string>
<string name="glanceable_hub_to_dream_button_tooltip" msgid="9018287673822335829">"Cihazınız şarj olurken en sevdiğiniz ekran koruyucuları gösterin"</string>
- <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştirme"</string>
+ <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştir"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"açılır menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Misafir kullanıcı, tekrar hoşgeldiniz"</string>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>, sohbet özelliklerini desteklemiyor"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Geri bildirim"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Kapat"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Tekrar gösterme"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirimler değiştirilemez."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Arama bildirimleri değiştirilemez."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Bu bildirim grubu burada yapılandırılamaz"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Katlanabilir cihaz açılıyor"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Katlanabilir cihaz döndürülüyor"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Ön ekran açıldı"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"İç taraftaki ekranı kullanmak için kaydırın"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"katlanmış"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"katlanmamış"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
index 1c0c110..f3c51c0 100644
--- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Kapalı"</item>
<item msgid="5908720590832378783">"Açık"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 7dab3db..27c2e53 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Джерело сигналу"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Слухові апарати"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Увімкнення…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не вдається змінити яскравість, оскільки\n нею керує основний додаток"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Не вдається змінити яскравість, оскільки нею керує основний додаток"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автообертання"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматично обертати екран"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Геодані"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"скасувати вибір віджета"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Зменшити висоту"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Збільшити висоту"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Показати наступний"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Показати попередній"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не підтримує функції розмов"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Надіслати відгук"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Закрити"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Більше не показувати"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ці сповіщення не можна змінити."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Сповіщення про виклик не можна змінити."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Цю групу сповіщень не можна налаштувати тут"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Розкладний пристрій у розкладеному стані"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Розкладний пристрій обертається"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Передній екран увімкнено"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Проведіть пальцем, щоб використовувати внутрішній екран"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"складений"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"розкладений"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
index 656ccd4..4fac740 100644
--- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Вимкнено"</item>
<item msgid="5908720590832378783">"Увімкнено"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 6460721..28572b9 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ان پٹ"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"سماعتی آلات"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"آن ہو رہا ہے…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"چمک کو ایڈجسٹ نہیں کیا جا سکتا کیونکہ اسے سرفہرست ایپ کے ذریعے \n کنٹرول کیا جا رہا ہے"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"چمک کو ایڈجسٹ نہیں کیا جا سکتا کیونکہ اسے سرفہرست ایپ کے ذریعے کنٹرول کیا جا رہا ہے"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"خود کار طور پر گھمائیں"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"اسکرین کو خود کار طور پر گھمائیں"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"مقام"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"ویجیٹ غیر منتخب کریں"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"اونچائی کم کریں"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"اونچائی بڑھائیں"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"اگلا دکھائیں"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"سابقہ دکھائیں"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ گفتگو کی خصوصیات کو سپورٹ نہیں کرتی ہے"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"تاثرات"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"برخاست کریں"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"دوبارہ نہ دکھائیں"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ان اطلاعات کی ترمیم نہیں کی جا سکتی۔"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"کال کی اطلاعات میں ترمیم نہیں کی جا سکتی۔"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"اطلاعات کے اس گروپ کو یہاں کنفیگر نہیں کیا جا سکتا"</string>
diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
index 4aa490d..06e213b 100644
--- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"آف"</item>
<item msgid="5908720590832378783">"آن"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 6bcd9d6..54c1412d 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -60,12 +60,12 @@
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Tilni almashtirish"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Joriy tilni qoldirish"</string>
<string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi ulashuv"</string>
- <string name="wifi_debugging_title" msgid="7300007687492186076">"Wi-Fi orqali debagging uchun ruxsat berilsinmi?"</string>
+ <string name="wifi_debugging_title" msgid="7300007687492186076">"Wi-Fi orqali debaging uchun ruxsat berilsinmi?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Tarmoq nomi (SSID):\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Manzil (BSSID):\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Bu tarmoqda doim ruxsat etilsin"</string>
<string name="wifi_debugging_allow" msgid="4573224609684957886">"Ruxsat"</string>
- <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Wi-Fi orqali debagging taqiqlandi"</string>
- <string name="wifi_debugging_secondary_user_message" msgid="9085779370142222881">"Ayni paytda ushbu qurilmaga oʻz hisobi bilan kirgan foydalanuvchi Wi-Fi orqali debagging funksiyasini yoqa olmaydi. Bu funksiyadan foydalanish uchun administrator profiliga oʻting."</string>
+ <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Wi-Fi orqali debaging taqiqlandi"</string>
+ <string name="wifi_debugging_secondary_user_message" msgid="9085779370142222881">"Ayni paytda ushbu qurilmaga oʻz hisobi bilan kirgan foydalanuvchi Wi-Fi orqali debaging funksiyasini yoqa olmaydi. Bu funksiyadan foydalanish uchun administrator profiliga oʻting."</string>
<string name="usb_contaminant_title" msgid="894052515034594113">"USB port faolsizlashtirildi"</string>
<string name="usb_contaminant_message" msgid="7730476585174719805">"Qurilmangizni suyuqlik va turli parchalardan himoya qilish uchun USB port faolsizlashtiriladi va hech qanday aksessuarni aniqlay olmaydi.\n\nUSB portdan xavfsiz foydalanish mumkin boʻlganda, sizga xabar beriladi."</string>
<string name="usb_port_enabled" msgid="531823867664717018">"Quvvatlash moslamalari va aksessuarlarni aniqlash uchun USB port yoqildi"</string>
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Kirish"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Eshitish moslamalari"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Yoqilmoqda…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Yorqinlik umumiy sozlamalar orqali boshqariladi.\nUni moslash imkonsiz"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Yorqinlik umumiy sozlamalar orqali boshqariladi.Uni moslash imkonsiz"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Avto-burilish"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranning avtomatik burilishi"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Joylashuv"</string>
@@ -354,7 +354,7 @@
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ranglarni akslantirish"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ranglarni tuzatish"</string>
<string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Shrift hajmi"</string>
- <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Foyd-ni boshqarish"</string>
+ <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Foydalanuvchilarni boshqarish"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Tayyor"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Yopish"</string>
<string name="quick_settings_connected" msgid="3873605509184830379">"Ulangan"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"vidjetni bekor qilish"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Balandligini kichraytirish"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Balandligini oshirish"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Keyingisi"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Avvalgisi"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasida suhbat funksiyalari ishlamaydi"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Fikr-mulohaza"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Yopish"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Boshqa chiqmasin"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirishnomalarni tahrirlash imkonsiz."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Chaqiruv bildirishnomalarini tahrirlash imkonsiz."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ushbu bildirishnomalar guruhi bu yerda sozlanmaydi"</string>
@@ -1349,7 +1356,7 @@
<string name="clipboard_image_preview" msgid="2156475174343538128">"Rasmga razm solish"</string>
<string name="clipboard_edit" msgid="4500155216174011640">"tahrir"</string>
<string name="add" msgid="81036585205287996">"Kiritish"</string>
- <string name="manage_users" msgid="1823875311934643849">"Foyd-ni boshqarish"</string>
+ <string name="manage_users" msgid="1823875311934643849">"Foydalanuvchilarni boshqarish"</string>
<string name="drag_split_not_supported" msgid="7173481676120546121">"Bu bildirishnoma ikkiga ajratilgan ekranda ishlamaydi."</string>
<string name="dream_overlay_location_active" msgid="6484763493158166618">"Joylashuv faol"</string>
<string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ishlamayapti"</string>
@@ -1394,10 +1401,9 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Buklanadigan qurilma ochilmoqda"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Buklanadigan qurilma aylantirilmoqda"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Old ekran yoqildi"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Ichki ekranni ishlatish uchun surish"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"buklangan"</string>
- <string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"buklanmagan"</string>
+ <string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"yoyib ochilgan"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
<string name="stylus_battery_low_percentage" msgid="2564243323894629626">"Stilus batareyasi: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Stilusni quvvat manbaiga ulang"</string>
diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
index 1c32e9fb..f636bc6 100644
--- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Yoqilmagan"</item>
<item msgid="5908720590832378783">"Yoniq"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a9f24ed..4414e09 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Thiết bị đầu vào"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Thiết bị trợ thính"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Đang bật…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Không điều chỉnh được độ sáng vì độ sáng đang được\n ứng dụng trên cùng điều khiển"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Không điều chỉnh được độ sáng vì độ sáng đang được ứng dụng trên cùng điều khiển"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Tự động xoay"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Tự động xoay màn hình"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Vị trí"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"bỏ chọn tiện ích"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Giảm chiều cao"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Tăng chiều cao"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Hiện trình phát nội dung nghe nhìn tiếp theo"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Hiện trình phát nội dung nghe nhìn trước"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> không hỗ trợ các tính năng trò chuyện"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Phản hồi"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Đóng"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Không hiện lại"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Không thể sửa đổi các thông báo này."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Không thể sửa đổi các thông báo cuộc gọi."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Không thể định cấu hình nhóm thông báo này tại đây"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Thiết bị có thể gập lại đang được mở ra"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Thiết bị có thể gập lại đang được lật ngược"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Đã bật màn hình trước"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Trượt để dùng màn hình bên trong"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"gập"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"mở"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
index 466eb3d6..d8e6887 100644
--- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Đang tắt"</item>
<item msgid="5908720590832378783">"Đang bật"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 0f28d92..f45ca2d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"输入"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"助听器"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"正在开启…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"亮度无法调整,因为它正在被\n顶层应用控制"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"亮度无法调整,因为它正在被顶层应用控制"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"自动屏幕旋转"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"自动旋转屏幕"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"位置信息"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消选中微件"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"减小高度"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"增加高度"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"显示下一个"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"显示上一个"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>不支持对话功能"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"反馈"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"关闭"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"不再显示"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"无法修改这些通知。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"无法修改来电通知。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"您无法在此处配置这组通知"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展开可折叠设备"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻转可折叠设备"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"前屏已开启"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"滑动即可使用内屏"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"折叠状态"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"展开状态"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s/%2$s"</string>
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 65415f6..6f36065 100644
--- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"关闭"</item>
<item msgid="5908720590832378783">"开启"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 6a29d86..ebf07ee 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"輸入"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"助聽器"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"正在開啟…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"無法調整亮度,因為\n目前是由上層應用程式控制亮度"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"無法調整亮度,因為目前是由上層應用程式控制亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"自動旋轉"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"自動旋轉螢幕"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"位置"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消揀小工具"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"調低高度"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"調高高度"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"顯示下一個"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"顯示上一個"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"意見反映"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"關閉"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"不要再顯示"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"無法修改這些通知。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"無法修改通話通知。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"無法在此設定這組通知"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"正面螢幕已開啟"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"滑動即可使用內部螢幕"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"已摺疊"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"已打開"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
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 0882be7..25548e2 100644
--- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"關閉"</item>
<item msgid="5908720590832378783">"開啟"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a931304..2e2a930 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -328,7 +328,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"輸入"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"助聽器"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"開啟中…"</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"無法調整亮度,因為\n目前是由上層應用程式控制亮度"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"無法調整亮度,因為目前是由上層應用程式控制亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"自動旋轉"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"自動旋轉螢幕"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"定位"</string>
@@ -534,6 +534,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"取消選取小工具"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"調低"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"調高"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"顯示下一個"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"顯示上一個"</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>
@@ -806,7 +808,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"意見回饋"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"關閉"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"不要再顯示"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"無法修改這些通知。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"無法修改來電通知。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"無法在這裡設定這個通知群組"</string>
@@ -1394,8 +1401,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開的折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"正面螢幕已開啟"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"滑動即可使用內螢幕"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"已摺疊"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"已展開"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
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 f94b044..3a192ba 100644
--- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"關閉"</item>
<item msgid="5908720590832378783">"開啟"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 08e6852..818b6e3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -330,7 +330,7 @@
<string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Okokufaka"</string>
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Imishini yendlebe"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Iyavula..."</string>
- <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ayikwazi ukulungisa ukukhanya ngoba ilawulwa\n yi-app ephezulu"</string>
+ <string name="quick_settings_brightness_unable_adjust_msg" msgid="786478497970492300">"Ayikwazi ukulungisa ukukhanya ngoba ilawulwa yi-app ephezulu"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Ukuphenduka okuzenzakalelayo"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Phendula iskrini ngokuzenzakalela"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Indawo"</string>
@@ -536,6 +536,8 @@
<string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"yeka ukukhetha iwijethi"</string>
<string name="accessibility_action_label_shrink_widget" msgid="8259511040536438771">"Nciphisa ubude"</string>
<string name="accessibility_action_label_expand_widget" msgid="9190524260912211759">"Khuphula ubude"</string>
+ <string name="accessibility_action_label_umo_show_next" msgid="8033581654789193281">"Bonisa okulandelayo"</string>
+ <string name="accessibility_action_label_umo_show_previous" msgid="5935831384525173810">"Bonisa okwangaphambili"</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>
@@ -808,7 +810,12 @@
<string name="no_shortcut" msgid="8257177117568230126">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayisekeli izici zengxoxo"</string>
<string name="notification_guts_bundle_feedback" msgid="7581587973879656500">"Impendulo"</string>
<string name="notification_inline_dismiss" msgid="88423586921134258">"Chitha"</string>
- <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ungabonisi futhi"</string>
+ <!-- no translation found for notification_inline_disable_promotion (3551682588314376921) -->
+ <skip />
+ <!-- no translation found for live_notifications_title (1586553354601345379) -->
+ <skip />
+ <!-- no translation found for live_notifications_desc (7470787001768372152) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Lezi zaziso azikwazi ukushintshwa."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Izaziso zekholi azikwazi ukushintshwa."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Leli qembu lezaziso alikwazi ukulungiselelwa lapha"</string>
@@ -1396,8 +1403,7 @@
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Idivayisi egoqekayo iyembulwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Idivayisi egoqekayo iphendulwa nxazonke"</string>
<string name="rear_display_unfolded_front_screen_on" msgid="5946436677205643170">"Isikrini sangaphambili sivuliwe"</string>
- <!-- no translation found for rear_display_unfolded_front_screen_on_slide_to_cancel (1455192420423012859) -->
- <skip />
+ <string name="rear_display_unfolded_front_screen_on_slide_to_cancel" msgid="1455192420423012859">"Slayida ukuze usebenzise isikrini esingaphakathi"</string>
<string name="quick_settings_rotation_posture_folded" msgid="2430280856312528289">"kugoqiwe"</string>
<string name="quick_settings_rotation_posture_unfolded" msgid="6372316273574167114">"kuvuliwe"</string>
<string name="rotation_tile_with_posture_secondary_label_template" msgid="7648496484163318886">"%1$s / %2$s"</string>
diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
index be5c6d8..f9f27bd 100644
--- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
@@ -196,4 +196,7 @@
<item msgid="6419996398343291862">"Valiwe"</item>
<item msgid="5908720590832378783">"Vuliwe"</item>
</string-array>
+ <!-- no translation found for tile_states_desktopeffects:0 (6253480000354287321) -->
+ <!-- no translation found for tile_states_desktopeffects:1 (6641673879029894995) -->
+ <!-- no translation found for tile_states_desktopeffects:2 (5806682401126108403) -->
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8665fd6..f4c6904 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -198,6 +198,7 @@
<!-- media -->
<color name="media_seamless_border">?android:attr/colorAccent</color>
<color name="media_paging_indicator">@color/material_dynamic_neutral_variant80</color>
+ <color name="media_on_background">#FFFFFF</color>
<!-- media output dialog-->
<color name="media_dialog_background" android:lstar="98">@color/material_dynamic_neutral90</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7d0c393..640e1fa 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -491,6 +491,9 @@
<!-- some constraints use a negative margin. must be aligned with overlay_border_width, above;
overlay_border_width_neg = overlay_border_width * -1 -->
<dimen name="overlay_border_width_neg">-4dp</dimen>
+ <dimen name="overlay_shade_panel_shape_radius">
+ @dimen/aux_spacing_overlay_panel_shape_radius
+ </dimen>
<dimen name="clipboard_preview_size">@dimen/overlay_x_scale</dimen>
<dimen name="clipboard_overlay_min_font">10sp</dimen>
@@ -2183,9 +2186,7 @@
orientation when the vertical space is limited
-->
<dimen name="volume_dialog_slider_vertical_margin">124dp</dimen>
-
- <fraction name="volume_dialog_half_opened_bias">0.2</fraction>
-
+ <dimen name="volume_dialog_half_opened_offset">-128dp</dimen>
<dimen name="volume_dialog_slider_max_deviation">56dp</dimen>
<dimen name="volume_dialog_background_square_corner_radius">12dp</dimen>
@@ -2217,4 +2218,8 @@
<dimen name="rear_display_progress_width">231dp</dimen>
<!-- Rear display mode end -->
+ <!-- Spacing attributes to overwrite -->
+ <dimen name="aux_spacing_overlay_panel_shape_radius">46dp</dimen>
+ <!-- Spacing attributes to overwrite end -->
+
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c0eea15..e97919e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -574,11 +574,12 @@
<!-- Content description of the bluetooth device settings gear icon. [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_device_settings_gear">Click to configure device detail</string>
+ <!-- Content description of the bluetooth device settings gear icon. [CHAR LIMIT=NONE] [BACKUP_MESSAGE_ID=3314916468105272540] -->
+ <string name="accessibility_bluetooth_device_settings_gear_with_name"><xliff:g id="device_name">%s</xliff:g>. Configure device detail</string>
<!-- Content description of the bluetooth device settings see all. [CHAR LIMIT=NONE] -->
- <string name="accessibility_bluetooth_device_settings_see_all">Click to see all devices</string>
+ <string name="accessibility_bluetooth_device_settings_see_all">See all devices</string>
<!-- Content description of the bluetooth device settings pair new device. [CHAR LIMIT=NONE] -->
- <string name="accessibility_bluetooth_device_settings_pair_new_device">Click to pair new device</string>
-
+ <string name="accessibility_bluetooth_device_settings_pair_new_device">Pair new device</string>
<!-- Content description of the battery when battery state is unknown for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_unknown">Battery percentage unknown.</string>
@@ -801,7 +802,7 @@
<!-- QuickSettings: Bluetooth secondary label shown when bluetooth is being enabled [CHAR LIMIT=NONE] -->
<string name="quick_settings_bluetooth_secondary_label_transient">Turning on…</string>
<!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
- <string name="quick_settings_brightness_unable_adjust_msg">Can\'t adjust brightness because it\'s being\n controlled by the top app</string>
+ <string name="quick_settings_brightness_unable_adjust_msg">Can\'t adjust brightness because it\'s being controlled by the top app</string>
<!-- QuickSettings: Rotation Unlocked [CHAR LIMIT=NONE] -->
<string name="quick_settings_rotation_unlocked_label">Auto-rotate</string>
<!-- Accessibility label for Auto-ratate QuickSettings tile [CHAR LIMIT=NONE] -->
@@ -2559,6 +2560,9 @@
<!-- SysUI Tuner: Other section -->
<string name="other">Other</string>
+ <!-- Accessibility description of action to toggle QS tile size on click. It will read as "Double-tap to toggle the tile's size" in screen readers [CHAR LIMIT=NONE] -->
+ <string name="accessibility_qs_edit_toggle_tile_size_action">toggle the tile\'s size</string>
+
<!-- Accessibility description of action to remove QS tile on click. It will read as "Double-tap to remove tile" in screen readers [CHAR LIMIT=NONE] -->
<string name="accessibility_qs_edit_remove_tile_action">remove tile</string>
@@ -3166,8 +3170,8 @@
<string name="controls_media_settings_button">Settings</string>
<!-- Description for media control's playing media item, including information for the media's title, the artist, and source app [CHAR LIMIT=NONE]-->
<string name="controls_media_playing_item_description"><xliff:g id="song_name" example="Daily mix">%1$s</xliff:g> by <xliff:g id="artist_name" example="Various artists">%2$s</xliff:g> is playing from <xliff:g id="app_label" example="Spotify">%3$s</xliff:g></string>
- <!-- Content description for media cotnrols progress bar [CHAR_LIMIT=NONE] -->
- <string name="controls_media_seekbar_description"><xliff:g id="elapsed_time" example="1:30">%1$s</xliff:g> of <xliff:g id="total_time" example="3:00">%2$s</xliff:g></string>
+ <!-- Content description for media controls progress bar [CHAR_LIMIT=NONE] -->
+ <string name="controls_media_seekbar_description"><xliff:g id="elapsed_time" example="1 hour 2 minutes 30 seconds">%1$s</xliff:g> of <xliff:g id="total_time" example="4 hours 5 seconds">%2$s</xliff:g></string>
<!-- Placeholder title to inform user that an app has posted media controls [CHAR_LIMIT=NONE] -->
<string name="controls_media_empty_title"><xliff:g id="app_name" example="Foo Music App">%1$s</xliff:g> is running</string>
@@ -4009,6 +4013,8 @@
<string name="touchpad_tutorial_switch_apps_gesture_button">Switch apps</string>
<!-- Label for button finishing touchpad tutorial [CHAR LIMIT=NONE] -->
<string name="touchpad_tutorial_done_button">Done</string>
+ <!-- Label for button proceeding touchpad tutorial [CHAR LIMIT=NONE] -->
+ <string name="touchpad_tutorial_next_button">Next</string>
<!-- Screen title after gesture was not done correctly [CHAR LIMIT=NONE] -->
<string name="gesture_error_title">Try again!</string>
<!-- BACK GESTURE -->
@@ -4094,8 +4100,10 @@
<!-- 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>
+ <!-- Main text of the one line view of a public notification -->
+ <string name="public_notification_single_line_text">Unlock to view</string>
+ <!-- Main text of the one line view of a redacted OTP notification -->
+ <string name="redacted_otp_notification_single_line_text">Unlock to view code</string>
<!-- Content description for contextual education dialog [CHAR LIMIT=NONE] -->
<string name="contextual_education_dialog_title">Contextual education</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 8f808d3..8a6b3af 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -186,7 +186,7 @@
</style>
<style name="TextAppearance.QS.Status.Build">
- <item name="android:textColor">?attr/onSurfaceVariant</item>
+ <item name="android:textColor">?attr/onShadeInactiveVariant</item>
</style>
<style name="TextAppearance.DeviceManagementDialog.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"/>
@@ -828,23 +828,23 @@
<item name="android:elevation">10dp</item>
</style>
- <!-- Media controls always have light background -->
+ <!-- Media controls always have dark background -->
<style name="MediaPlayer" parent="@*android:style/Theme.DeviceDefault.Light">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:backgroundTint">@color/material_dynamic_secondary95</item>
+ <item name="android:textColor">@color/media_on_background</item>
+ <item name="android:backgroundTint">@android:color/system_on_surface_light</item>
</style>
<style name="MediaPlayer.ProgressBar" parent="@android:style/Widget.ProgressBar.Horizontal">
<item name="android:thumb">@drawable/media_seekbar_thumb</item>
- <item name="android:thumbTint">?android:attr/textColorPrimary</item>
+ <item name="android:thumbTint">@color/media_on_background</item>
<item name="android:progressDrawable">@drawable/media_squiggly_progress</item>
- <item name="android:progressTint">?android:attr/textColorPrimary</item>
- <item name="android:progressBackgroundTint">?android:attr/textColorTertiary</item>
+ <item name="android:progressTint">@color/media_on_background</item>
+ <item name="android:progressBackgroundTint">@android:color/system_primary_dark</item>
<item name="android:splitTrack">false</item>
</style>
<style name="MediaPlayer.Subtitle" parent="MediaPlayer">
- <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textColor">@color/media_on_background</item>
</style>
<style name="MediaPlayer.ScrubbingTime">
@@ -853,21 +853,10 @@
<item name="android:gravity">center</item>
</style>
- <style name="MediaPlayer.Action" parent="@android:style/Widget.Material.Button.Borderless.Small">
- <item name="android:background">@drawable/qs_media_light_source</item>
- <item name="android:tint">?android:attr/textColorPrimary</item>
- <item name="android:stateListAnimator">@anim/media_button_state_list_animator</item>
- <item name="android:paddingTop">8dp</item>
- <item name="android:paddingStart">12dp</item>
- <item name="android:paddingEnd">12dp</item>
- <item name="android:paddingBottom">16dp</item>
- <item name="android:scaleType">centerInside</item>
- </style>
-
<style name="MediaPlayer.SessionAction"
parent="@android:style/Widget.Material.Button.Borderless.Small">
<item name="android:background">@drawable/qs_media_light_source</item>
- <item name="android:tint">?android:attr/textColorPrimary</item>
+ <item name="android:tint">@color/media_on_background</item>
<item name="android:paddingTop">12dp</item>
<item name="android:paddingStart">12dp</item>
<item name="android:paddingEnd">12dp</item>
@@ -886,8 +875,8 @@
<style name="MediaPlayer.OutlineButton">
<item name="android:background">@drawable/qs_media_outline_button</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:backgroundTint">@color/media_player_outline_button_bg</item>
+ <item name="android:textColor">@color/media_on_background</item>
+ <item name="android:backgroundTint">@android:color/system_primary_dark</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:layout_gravity">center</item>
<item name="android:singleLine">true</item>
@@ -895,8 +884,8 @@
<style name="MediaPlayer.SolidButton">
<item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
- <item name="android:tint">?android:attr/colorPrimary</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:tint">@android:color/system_on_primary_dark</item>
+ <item name="android:textColor">@android:color/system_on_primary_dark</item>
</style>
<style name="MediaPlayer.Recommendation"/>
diff --git a/packages/SystemUI/res/xml/volume_dialog_constraint_set.xml b/packages/SystemUI/res/xml/volume_dialog_constraint_set.xml
deleted file mode 100644
index dcc5d4f..0000000
--- a/packages/SystemUI/res/xml/volume_dialog_constraint_set.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ConstraintSet xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/volume_dialog_constraint_set">
-
- <Constraint
- android:id="@id/volume_dialog_main_slider_container"
- android:layout_width="@dimen/volume_dialog_slider_width"
- android:layout_height="0dp"
- android:layout_marginTop="@dimen/volume_dialog_slider_vertical_margin"
- android:layout_marginEnd="@dimen/volume_dialog_window_margin"
- android:layout_marginBottom="@dimen/volume_dialog_slider_vertical_margin"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHeight_max="@dimen/volume_dialog_slider_height"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintVertical_bias="0.5" />
-</ConstraintSet>
\ No newline at end of file
diff --git a/packages/SystemUI/res/xml/volume_dialog_half_folded_constraint_set.xml b/packages/SystemUI/res/xml/volume_dialog_half_folded_constraint_set.xml
deleted file mode 100644
index 3a5e41d..0000000
--- a/packages/SystemUI/res/xml/volume_dialog_half_folded_constraint_set.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ConstraintSet xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/volume_dialog_half_folded_constraint_set">
-
- <Constraint
- android:id="@id/volume_dialog_main_slider_container"
- android:layout_width="@dimen/volume_dialog_slider_width"
- android:layout_height="0dp"
- android:layout_marginTop="@dimen/volume_dialog_slider_vertical_margin"
- android:layout_marginEnd="@dimen/volume_dialog_window_margin"
- android:layout_marginBottom="@dimen/volume_dialog_slider_vertical_margin"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHeight_max="@dimen/volume_dialog_slider_height"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintVertical_bias="@fraction/volume_dialog_half_opened_bias" />
-</ConstraintSet>
\ No newline at end of file
diff --git a/packages/SystemUI/res/xml/volume_dialog_scene.xml b/packages/SystemUI/res/xml/volume_dialog_scene.xml
deleted file mode 100644
index b813474..0000000
--- a/packages/SystemUI/res/xml/volume_dialog_scene.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
- -->
-
-<MotionScene xmlns:motion="http://schemas.android.com/apk/res-auto">
-
- <Transition
- motion:autoTransition="none"
- motion:constraintSetEnd="@id/volume_dialog_half_folded_constraint_set"
- motion:constraintSetStart="@id/volume_dialog_constraint_set"
- motion:duration="150" />
-
- <Include motion:constraintSet="@xml/volume_dialog_constraint_set" />
- <Include motion:constraintSet="@xml/volume_dialog_half_folded_constraint_set" />
-</MotionScene>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 0f1da50..ae3a76e 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -71,6 +71,7 @@
"//frameworks/libs/systemui:com_android_systemui_shared_flags_lib",
"//frameworks/libs/systemui:msdl",
"//frameworks/libs/systemui:view_capture",
+ "am_flags_lib",
],
resource_dirs: [
"res",
diff --git a/packages/SystemUI/shared/res/values/bools.xml b/packages/SystemUI/shared/res/values/bools.xml
index f22dac4..98e5cea 100644
--- a/packages/SystemUI/shared/res/values/bools.xml
+++ b/packages/SystemUI/shared/res/values/bools.xml
@@ -22,4 +22,7 @@
<resources>
<!-- Whether to add padding at the bottom of the complication clock -->
<bool name="dream_overlay_complication_clock_bottom_padding">false</bool>
-</resources>
\ No newline at end of file
+
+ <!-- Whether to mark tasks that are present in the UI as perceptible tasks. -->
+ <bool name="config_usePerceptibleTasks">false</bool>
+</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index 9ebb15f..c822439 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -19,6 +19,7 @@
import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import android.annotation.TargetApi;
import android.app.StatusBarManager.NavbarFlags;
@@ -35,6 +36,8 @@
import android.view.Surface;
import android.view.WindowManager;
+import com.android.systemui.shared.recents.model.Task;
+
/* Common code */
public class Utilities {
@@ -165,4 +168,10 @@
float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;
return (size / densityRatio);
}
+
+ /** Whether a task is in freeform mode. */
+ public static boolean isFreeformTask(Task task) {
+ return task != null && task.getKey() != null
+ && task.getKey().windowingMode == WINDOWING_MODE_FREEFORM;
+ }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index ed9ba7a..487d1ce 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -46,6 +46,8 @@
import android.window.TaskSnapshot;
import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.server.am.Flags;
+import com.android.systemui.shared.R;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -227,6 +229,17 @@
}
/**
+ * Sets whether or not the specified task is perceptible.
+ */
+ public boolean setTaskIsPerceptible(int taskId, boolean isPerceptible) {
+ try {
+ return getService().setTaskIsPerceptible(taskId, isPerceptible);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Removes a task by id.
*/
public void removeTask(final int taskId) {
@@ -311,10 +324,23 @@
}
/**
+ * Returns true if tasks with a presence in the UI should be marked as perceptible tasks.
+ */
+ public static boolean usePerceptibleTasks(Context context) {
+ return Flags.perceptibleTasks()
+ && context.getResources().getBoolean(R.bool.config_usePerceptibleTasks);
+ }
+
+ /**
* Returns true if the running task represents the home task
*/
public static boolean isHomeTask(RunningTaskInfo info) {
return info.configuration.windowConfiguration.getActivityType()
== WindowConfiguration.ACTIVITY_TYPE_HOME;
}
+
+ public boolean isRunningInTestHarness() {
+ return ActivityManager.isRunningInTestHarness()
+ || ActivityManager.isRunningInUserTestHarness();
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
index 5e36539..a7bb11e 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
@@ -156,7 +156,7 @@
mMainExecutor.execute(() -> mView.updateEmergencyCallButton(
/* isInCall= */ isInCall,
/* hasTelephonyRadio= */ getContext().getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_TELEPHONY),
+ .hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING),
/* simLocked= */ mKeyguardUpdateMonitor.isSimPinVoiceSecure(),
/* isSecure= */ isSecure));
});
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 42896a4..b2cb357 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -167,7 +167,7 @@
public void setHeight(float h) {
if (DEBUG_SCALE) Log.v(TAG, "SetHeight: setting to " + h);
- mView.setActualHeight((int) h);
+ mView.setFinalActualHeight((int) h);
mCurrentHeight = h;
}
public float getHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
index 7c141c1..5247acc 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
@@ -58,11 +58,22 @@
private final BiMap<Integer, AmbientVolumeSlider> mSideToSliderMap = HashBiMap.create();
private int mVolumeLevel = AMBIENT_VOLUME_LEVEL_DEFAULT;
+ private HearingDevicesUiEventLogger mUiEventLogger;
+ private int mLaunchSourceId;
+
private final AmbientVolumeSlider.OnChangeListener mSliderOnChangeListener =
(slider, value) -> {
- if (mListener != null) {
- final int side = mSideToSliderMap.inverse().get(slider);
- mListener.onSliderValueChange(side, value);
+ final Integer side = mSideToSliderMap.inverse().get(slider);
+ if (side != null) {
+ if (mUiEventLogger != null) {
+ HearingDevicesUiEvent uiEvent = side == SIDE_UNIFIED
+ ? HearingDevicesUiEvent.HEARING_DEVICES_AMBIENT_CHANGE_UNIFIED
+ : HearingDevicesUiEvent.HEARING_DEVICES_AMBIENT_CHANGE_SEPARATED;
+ mUiEventLogger.log(uiEvent, mLaunchSourceId);
+ }
+ if (mListener != null) {
+ mListener.onSliderValueChange(side, value);
+ }
}
};
@@ -94,6 +105,12 @@
return;
}
setMuted(!mMuted);
+ if (mUiEventLogger != null) {
+ HearingDevicesUiEvent uiEvent = mMuted
+ ? HearingDevicesUiEvent.HEARING_DEVICES_AMBIENT_MUTE
+ : HearingDevicesUiEvent.HEARING_DEVICES_AMBIENT_UNMUTE;
+ mUiEventLogger.log(uiEvent, mLaunchSourceId);
+ }
if (mListener != null) {
mListener.onAmbientVolumeIconClick();
}
@@ -103,6 +120,12 @@
mExpandIcon = requireViewById(R.id.ambient_expand_icon);
mExpandIcon.setOnClickListener(v -> {
setExpanded(!mExpanded);
+ if (mUiEventLogger != null) {
+ HearingDevicesUiEvent uiEvent = mExpanded
+ ? HearingDevicesUiEvent.HEARING_DEVICES_AMBIENT_EXPAND_CONTROLS
+ : HearingDevicesUiEvent.HEARING_DEVICES_AMBIENT_COLLAPSE_CONTROLS;
+ mUiEventLogger.log(uiEvent, mLaunchSourceId);
+ }
if (mListener != null) {
mListener.onExpandIconClick();
}
@@ -243,6 +266,11 @@
updateVolumeLevel();
}
+ void setUiEventLogger(HearingDevicesUiEventLogger uiEventLogger, int launchSourceId) {
+ mUiEventLogger = uiEventLogger;
+ mLaunchSourceId = launchSourceId;
+ }
+
private void updateVolumeLevel() {
int leftLevel, rightLevel;
if (mExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
index 22ecb0a..786d27a 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
@@ -382,6 +382,7 @@
private void setupAmbientControls(CachedBluetoothDevice activeHearingDevice) {
final AmbientVolumeLayout ambientLayout = mDialog.requireViewById(R.id.ambient_layout);
+ ambientLayout.setUiEventLogger(mUiEventLogger, mLaunchSourceId);
mAmbientController = new AmbientVolumeUiController(
mDialog.getContext(), mLocalBluetoothManager, ambientLayout);
mAmbientController.setShowUiWhenLocalDataExist(false);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt
index 9e77b02..fe1d504 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt
@@ -29,7 +29,17 @@
@UiEvent(doc = "Click on the device gear to enter device detail page")
HEARING_DEVICES_GEAR_CLICK(1853),
@UiEvent(doc = "Select a preset from preset spinner") HEARING_DEVICES_PRESET_SELECT(1854),
- @UiEvent(doc = "Click on related tool") HEARING_DEVICES_RELATED_TOOL_CLICK(1856);
+ @UiEvent(doc = "Click on related tool") HEARING_DEVICES_RELATED_TOOL_CLICK(1856),
+ @UiEvent(doc = "Change the ambient volume with unified control")
+ HEARING_DEVICES_AMBIENT_CHANGE_UNIFIED(2149),
+ @UiEvent(doc = "Change the ambient volume with separated control")
+ HEARING_DEVICES_AMBIENT_CHANGE_SEPARATED(2150),
+ @UiEvent(doc = "Mute the ambient volume") HEARING_DEVICES_AMBIENT_MUTE(2151),
+ @UiEvent(doc = "Unmute the ambient volume") HEARING_DEVICES_AMBIENT_UNMUTE(2152),
+ @UiEvent(doc = "Expand the ambient volume controls")
+ HEARING_DEVICES_AMBIENT_EXPAND_CONTROLS(2153),
+ @UiEvent(doc = "Collapse the ambient volume controls")
+ HEARING_DEVICES_AMBIENT_COLLAPSE_CONTROLS(2154);
override fun getId(): Int = this.id
}
diff --git a/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS b/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS
index 429b4b0..329aa07 100644
--- a/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS
@@ -3,6 +3,5 @@
dupin@google.com
linyuh@google.com
pauldpong@google.com
-praveenj@google.com
vicliang@google.com
yuklimko@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index b653711..4c8a8f1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -33,6 +33,7 @@
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
+import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.PromptInfo;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -100,7 +101,7 @@
*/
@Deprecated
public class AuthContainerView extends LinearLayout
- implements AuthDialog, WakefulnessLifecycle.Observer, CredentialView.Host {
+ implements WakefulnessLifecycle.Observer, CredentialView.Host {
private static final String TAG = "AuthContainerView";
@@ -158,12 +159,11 @@
private final Set<Integer> mFailedModalities = new HashSet<Integer>();
private final OnBackInvokedCallback mBackCallback = this::onBackInvoked;
- private final @Background DelayableExecutor mBackgroundExecutor;
private final MSDLPlayer mMSDLPlayer;
// Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
- @Nullable @AuthDialogCallback.DismissedReason private Integer mPendingCallbackReason;
+ @Nullable @BiometricPrompt.DismissedReason private Integer mPendingCallbackReason;
// HAT received from LockSettingsService when credential is verified.
@Nullable private byte[] mCredentialAttestation;
@@ -188,18 +188,18 @@
final class BiometricCallback implements Spaghetti.Callback {
@Override
public void onAuthenticated() {
- animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
+ animateAway(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED);
}
@Override
public void onUserCanceled() {
sendEarlyUserCanceled();
- animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ animateAway(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
}
@Override
public void onButtonNegative() {
- animateAway(AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE);
+ animateAway(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
}
@Override
@@ -210,12 +210,12 @@
@Override
public void onContentViewMoreOptionsButtonPressed() {
- animateAway(AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS);
+ animateAway(BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS);
}
@Override
public void onError() {
- animateAway(AuthDialogCallback.DISMISSED_ERROR);
+ animateAway(BiometricPrompt.DISMISSED_REASON_ERROR);
}
@Override
@@ -234,20 +234,20 @@
@Override
public void onAuthenticatedAndConfirmed() {
- animateAway(AuthDialogCallback.DISMISSED_BUTTON_POSITIVE);
+ animateAway(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED);
}
}
@Override
public void onCredentialMatched(@NonNull byte[] attestation) {
mCredentialAttestation = attestation;
- animateAway(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED);
+ animateAway(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED);
}
@Override
public void onCredentialAborted() {
sendEarlyUserCanceled();
- animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ animateAway(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
}
@Override
@@ -277,7 +277,7 @@
com.android.settingslib.R.string.failed_attempts_now_wiping_dialog_dismiss,
null /* OnClickListener */)
.setOnDismissListener(
- dialog -> animateAway(AuthDialogCallback.DISMISSED_ERROR))
+ dialog -> animateAway(BiometricPrompt.DISMISSED_REASON_ERROR))
.create();
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
alertDialog.show();
@@ -349,7 +349,6 @@
mPanelView = mLayout.findViewById(R.id.panel);
mPanelController = new AuthPanelController(mContext, mPanelView);
- mBackgroundExecutor = bgExecutor;
mInteractionJankMonitor = jankMonitor;
mCredentialViewModelProvider = credentialViewModelProvider;
@@ -394,7 +393,7 @@
@VisibleForTesting
public void onBackInvoked() {
sendEarlyUserCanceled();
- animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ animateAway(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
}
void sendEarlyUserCanceled() {
@@ -402,7 +401,6 @@
BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL, getRequestId());
}
- @Override
public boolean isAllowDeviceCredentials() {
return Utils.isDeviceCredentialAllowed(mConfig.mPromptInfo);
}
@@ -450,7 +448,6 @@
mPanelController.setContainerDimensions(getMeasuredWidth(), getMeasuredHeight());
}
- @Override
public void onOrientationChanged() {
}
@@ -538,10 +535,9 @@
@Override
public void onStartedGoingToSleep() {
- animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ animateAway(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
}
- @Override
public void show(WindowManager wm) {
wm.addView(this, getLayoutParams(mWindowToken, mConfig.mPromptInfo.getTitle()));
}
@@ -559,7 +555,6 @@
}
}
- @Override
public void dismissWithoutCallback(boolean animate) {
if (animate) {
animateAway(false /* sendReason */, 0 /* reason */);
@@ -569,12 +564,10 @@
}
}
- @Override
public void dismissFromSystemServer() {
animateAway(false /* sendReason */, 0 /* reason */);
}
- @Override
public void onAuthenticationSucceeded(@Modality int modality) {
if (mBiometricView != null) {
mBiometricView.onAuthenticationSucceeded(modality);
@@ -583,7 +576,6 @@
}
}
- @Override
public void onAuthenticationFailed(@Modality int modality, String failureReason) {
if (mBiometricView != null) {
mFailedModalities.add(modality);
@@ -593,7 +585,6 @@
}
}
- @Override
public void onHelp(@Modality int modality, String help) {
if (mBiometricView != null) {
mBiometricView.onHelp(modality, help);
@@ -602,7 +593,6 @@
}
}
- @Override
public void onError(@Modality int modality, String error) {
if (mBiometricView != null) {
mBiometricView.onError(modality, error);
@@ -611,7 +601,6 @@
}
}
- @Override
public void onPointerDown() {
if (mBiometricView != null) {
if (mFailedModalities.contains(TYPE_FACE)) {
@@ -624,22 +613,18 @@
}
}
- @Override
public String getOpPackageName() {
return mConfig.mOpPackageName;
}
- @Override
public String getClassNameIfItIsConfirmDeviceCredentialActivity() {
return mConfig.mPromptInfo.getClassNameIfItIsConfirmDeviceCredentialActivity();
}
- @Override
public long getRequestId() {
return mConfig.mRequestId;
}
- @Override
public void animateToCredentialUI(boolean isError) {
if (mBiometricView != null) {
mBiometricView.startTransitionToCredentialUI(isError);
@@ -648,11 +633,11 @@
}
}
- void animateAway(@AuthDialogCallback.DismissedReason int reason) {
+ void animateAway(@BiometricPrompt.DismissedReason int reason) {
animateAway(true /* sendReason */, reason);
}
- private void animateAway(boolean sendReason, @AuthDialogCallback.DismissedReason int reason) {
+ private void animateAway(boolean sendReason, @BiometricPrompt.DismissedReason int reason) {
if (mContainerState == STATE_ANIMATING_IN) {
Log.w(TAG, "startDismiss(): waiting for onDialogAnimatedIn");
mContainerState = STATE_PENDING_DISMISS;
@@ -732,7 +717,7 @@
private void onDialogAnimatedIn() {
if (mContainerState == STATE_PENDING_DISMISS) {
Log.d(TAG, "onDialogAnimatedIn(): mPendingDismissDialog=true, dismissing now");
- animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ animateAway(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
return;
}
if (mContainerState == STATE_ANIMATING_OUT || mContainerState == STATE_GONE) {
@@ -748,7 +733,6 @@
}
}
- @Override
public PromptViewModel getViewModel() {
return mPromptViewModel;
}
@@ -776,7 +760,6 @@
return lp;
}
- @Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println(" isAttachedToWindow=" + isAttachedToWindow());
pw.println(" containerState=" + mContainerState);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index eee5f9e..68a2820 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -163,7 +163,7 @@
// TODO: These should just be saved from onSaveState
private SomeArgs mCurrentDialogArgs;
@VisibleForTesting
- AuthDialog mCurrentDialog;
+ AuthContainerView mCurrentDialog;
@NonNull private final WindowManager mWindowManager;
@NonNull private final DisplayManager mDisplayManager;
@@ -222,7 +222,7 @@
closeDialog(BiometricPrompt.DISMISSED_REASON_USER_CANCEL, reasonString);
}
- private void closeDialog(@DismissedReason int reason, String reasonString) {
+ private void closeDialog(@BiometricPrompt.DismissedReason int reason, String reasonString) {
if (isShowing()) {
Log.i(TAG, "Close BP, reason :" + reasonString);
mCurrentDialog.dismissWithoutCallback(true /* animate */);
@@ -511,60 +511,14 @@
}
@Override
- public void onDismissed(@DismissedReason int reason,
- @Nullable byte[] credentialAttestation, long requestId) {
-
+ public void onDismissed(@BiometricPrompt.DismissedReason int reason,
+ @Nullable byte[] credentialAttestation, long requestId) {
if (mCurrentDialog != null && requestId != mCurrentDialog.getRequestId()) {
Log.w(TAG, "requestId doesn't match, skip onDismissed");
return;
}
- switch (reason) {
- case AuthDialogCallback.DISMISSED_USER_CANCELED:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
- credentialAttestation);
- break;
-
- case AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_NEGATIVE,
- credentialAttestation);
- break;
-
- case AuthDialogCallback.DISMISSED_BUTTON_POSITIVE:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED,
- credentialAttestation);
- break;
-
- case AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED:
- sendResultAndCleanUp(
- BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED,
- credentialAttestation);
- break;
-
- case AuthDialogCallback.DISMISSED_ERROR:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_ERROR,
- credentialAttestation);
- break;
-
- case AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED,
- credentialAttestation);
- break;
-
- case AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED:
- sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED,
- credentialAttestation);
- break;
-
- case AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS:
- sendResultAndCleanUp(
- BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS,
- credentialAttestation);
- break;
- default:
- Log.e(TAG, "Unhandled reason: " + reason);
- break;
- }
+ sendResultAndCleanUp(reason, credentialAttestation);
}
@Override
@@ -699,7 +653,7 @@
mUdfpsController.onAodInterrupt(screenX, screenY, major, minor);
}
- private void sendResultAndCleanUp(@DismissedReason int reason,
+ private void sendResultAndCleanUp(@BiometricPrompt.DismissedReason int reason,
@Nullable byte[] credentialAttestation) {
if (mReceiver == null) {
Log.e(TAG, "sendResultAndCleanUp: Receiver is null");
@@ -1244,7 +1198,7 @@
final long requestId = args.argl2;
// Create a new dialog but do not replace the current one yet.
- final AuthDialog newDialog = buildDialog(
+ final AuthContainerView newDialog = buildDialog(
mBackgroundExecutor,
promptInfo,
requireConfirmation,
@@ -1327,7 +1281,7 @@
return mContext.createDisplayContext(display).getSystemService(WindowManager.class);
}
- private void onDialogDismissed(@DismissedReason int reason) {
+ private void onDialogDismissed(@BiometricPrompt.DismissedReason int reason) {
if (DEBUG) Log.d(TAG, "onDialogDismissed: " + reason);
if (mCurrentDialog == null) {
Log.w(TAG, "Dialog already dismissed");
@@ -1361,7 +1315,7 @@
}
}
- protected AuthDialog buildDialog(@Background DelayableExecutor bgExecutor,
+ protected AuthContainerView buildDialog(@Background DelayableExecutor bgExecutor,
PromptInfo promptInfo, boolean requireConfirmation, int userId, int[] sensorIds,
String opPackageName, boolean skipIntro, long operationId, long requestId,
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@@ -1389,7 +1343,7 @@
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
- final AuthDialog dialog = mCurrentDialog;
+ final AuthContainerView dialog = mCurrentDialog;
pw.println(" mCachedDisplayInfo=" + mCachedDisplayInfo);
pw.println(" mScaleFactor=" + mScaleFactor);
pw.println(" fingerprintSensorLocationInNaturalOrientation="
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
deleted file mode 100644
index 8611916..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.systemui.biometrics;
-
-import android.hardware.biometrics.BiometricAuthenticator.Modality;
-import android.view.WindowManager;
-
-import com.android.systemui.Dumpable;
-import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel;
-
-/**
- * Interface for the biometric dialog UI.
- *
- * TODO(b/287311775): remove along with legacy controller once flag is removed
- */
-@Deprecated
-public interface AuthDialog extends Dumpable {
-
- /**
- * Parameters used when laying out {@link AuthBiometricView}, its subclasses, and
- * {@link AuthPanelController}.
- */
- class LayoutParams {
- public final int mMediumHeight;
- public final int mMediumWidth;
-
- public LayoutParams(int mediumWidth, int mediumHeight) {
- mMediumWidth = mediumWidth;
- mMediumHeight = mediumHeight;
- }
- }
-
- /**
- * Show the dialog.
- * @param wm
- */
- void show(WindowManager wm);
-
- /**
- * Dismiss the dialog without sending a callback.
- */
- void dismissWithoutCallback(boolean animate);
-
- /**
- * Dismiss the dialog. Animate away.
- */
- void dismissFromSystemServer();
-
- /**
- * Biometric authenticated. May be pending user confirmation, or completed.
- */
- void onAuthenticationSucceeded(@Modality int modality);
-
- /**
- * Authentication failed (reject, timeout). Dialog stays showing.
- * @param modality sensor modality that triggered the error
- * @param failureReason message
- */
- void onAuthenticationFailed(@Modality int modality, String failureReason);
-
- /**
- * Authentication rejected, or help message received.
- * @param modality sensor modality that triggered the help message
- * @param help message
- */
- void onHelp(@Modality int modality, String help);
-
- /**
- * Authentication failed. Dialog going away.
- * @param modality sensor modality that triggered the error
- * @param error message
- */
- void onError(@Modality int modality, String error);
-
- /** UDFPS pointer down event. */
- void onPointerDown();
-
- /**
- * Get the client's package name
- */
- String getOpPackageName();
-
- /**
- * Get the class name of ConfirmDeviceCredentialActivity. Returns null if the direct caller is
- * not ConfirmDeviceCredentialActivity.
- */
- String getClassNameIfItIsConfirmDeviceCredentialActivity();
-
- /** The requestId of the underlying operation within the framework. */
- long getRequestId();
-
- /**
- * Animate to credential UI. Typically called after biometric is locked out.
- */
- void animateToCredentialUI(boolean isError);
-
- /**
- * @return true if device credential is allowed.
- */
- boolean isAllowDeviceCredentials();
-
- /**
- * Called when the device's orientation changed and the dialog may need to do another
- * layout. This is most relevant to UDFPS since configuration changes are not sent by
- * the framework in equivalent cases (landscape to reverse landscape) but the dialog
- * must remain fixed on the physical sensor location.
- */
- void onOrientationChanged();
-
- PromptViewModel getViewModel();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
index 024c6ea..31c63d3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
@@ -16,40 +16,20 @@
package com.android.systemui.biometrics;
-import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricPrompt;
/**
* Callback interface for dialog views. These should be implemented by the controller (e.g.
* FingerprintDialogImpl) and passed into their views (e.g. FingerprintDialogView).
*/
public interface AuthDialogCallback {
-
- int DISMISSED_USER_CANCELED = 1;
- int DISMISSED_BUTTON_NEGATIVE = 2;
- int DISMISSED_BUTTON_POSITIVE = 3;
- int DISMISSED_BIOMETRIC_AUTHENTICATED = 4;
- int DISMISSED_ERROR = 5;
- int DISMISSED_BY_SYSTEM_SERVER = 6;
- int DISMISSED_CREDENTIAL_AUTHENTICATED = 7;
- int DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS = 8;
-
- @IntDef({DISMISSED_USER_CANCELED,
- DISMISSED_BUTTON_NEGATIVE,
- DISMISSED_BUTTON_POSITIVE,
- DISMISSED_BIOMETRIC_AUTHENTICATED,
- DISMISSED_ERROR,
- DISMISSED_BY_SYSTEM_SERVER,
- DISMISSED_CREDENTIAL_AUTHENTICATED,
- DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS})
- @interface DismissedReason {}
-
/**
* Invoked when the dialog is dismissed
- * @param reason
+ * @param reason - the {@link BiometricPrompt.DismissedReason} for dismissing
* @param credentialAttestation the HAT received from LockSettingsService upon verification
*/
- void onDismissed(@DismissedReason int reason,
+ void onDismissed(@BiometricPrompt.DismissedReason int reason,
@Nullable byte[] credentialAttestation, long requestId);
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
index 4ac5a12..f7efaba 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
@@ -32,6 +32,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.res.R;
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import javax.inject.Inject;
@@ -44,6 +45,7 @@
private static final String TAG = "BiometricNotificationDialogFactory";
private final Resources mResources;
private final SystemUIDialog.Factory mSystemUIDialogFactory;
+ private final ShadeDialogContextInteractor mDialogContextInteractor;
@Nullable private final FingerprintManager mFingerprintManager;
@Nullable private final FaceManager mFaceManager;
@@ -51,10 +53,12 @@
BiometricNotificationDialogFactory(
@Main Resources resources,
SystemUIDialog.Factory systemUIDialogFactory,
+ ShadeDialogContextInteractor shadeDialogContextInteractor,
@Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager) {
mResources = resources;
mSystemUIDialogFactory = systemUIDialogFactory;
+ mDialogContextInteractor = shadeDialogContextInteractor;
mFingerprintManager = fingerprintManager;
mFaceManager = faceManager;
}
@@ -62,7 +66,8 @@
Dialog createReenrollDialog(
int userId, ActivityStarter activityStarter, BiometricSourceType biometricSourceType,
boolean isReenrollForced) {
- SystemUIDialog sysuiDialog = mSystemUIDialogFactory.create();
+ SystemUIDialog sysuiDialog =
+ mSystemUIDialogFactory.create(mDialogContextInteractor.getContext());
if (biometricSourceType == BiometricSourceType.FACE) {
sysuiDialog.setTitle(mResources.getString(R.string.face_re_enroll_dialog_title));
sysuiDialog.setMessage(mResources.getString(R.string.face_re_enroll_dialog_content));
@@ -90,7 +95,8 @@
}
private Dialog createReenrollFailureDialog(BiometricSourceType biometricType) {
- final SystemUIDialog sysuiDialog = mSystemUIDialogFactory.create();
+ final SystemUIDialog sysuiDialog =
+ mSystemUIDialogFactory.create(mDialogContextInteractor.getContext());
if (biometricType == BiometricSourceType.FACE) {
sysuiDialog.setMessage(mResources.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index fd11fa5..88694ae 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -94,6 +94,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.shade.ShadeDisplayAware;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.VibratorHelper;
@@ -656,9 +657,9 @@
}
@Inject
- public UdfpsController(@NonNull Context context,
+ public UdfpsController(@NonNull @Main Context context,
@NonNull Execution execution,
- @NonNull LayoutInflater inflater,
+ @NonNull @ShadeDisplayAware LayoutInflater inflater,
@Nullable FingerprintManager fingerprintManager,
@NonNull ViewCaptureAwareWindowManager viewCaptureAwareWindowManager,
@NonNull StatusBarStateController statusBarStateController,
@@ -676,7 +677,7 @@
@NonNull KeyguardStateController keyguardStateController,
@NonNull DisplayManager displayManager,
@Main Handler mainHandler,
- @NonNull ConfigurationController configurationController,
+ @NonNull @Main ConfigurationController configurationController,
@NonNull SystemClock systemClock,
@NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@NonNull SystemUIDialogManager dialogManager,
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentManager.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentManager.kt
index eebcf0b..576acd2 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentManager.kt
@@ -383,6 +383,11 @@
actionIcon.setImageResource(item.actionIconRes)
actionIcon.drawable?.setTint(tintColor)
+ actionIconView.contentDescription =
+ resources.getString(
+ R.string.accessibility_bluetooth_device_settings_gear_with_name,
+ item.deviceName,
+ )
divider.setBackgroundColor(tintColor)
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 cce1ae1..6473b1c 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
@@ -237,7 +237,15 @@
with(mediaHost) {
expansion = MediaHostState.EXPANDED
expandedMatchesParentHeight = true
- showsOnlyActiveMedia = false
+ if (v2FlagEnabled()) {
+ // Only show active media to match lock screen, not resumable media, which can
+ // persist
+ // for up to 2 days.
+ showsOnlyActiveMedia = true
+ } else {
+ // Maintain old behavior on tablet until V2 flag rolls out.
+ showsOnlyActiveMedia = false
+ }
falsingProtectionNeeded = false
disablePagination = true
init(MediaHierarchyManager.LOCATION_COMMUNAL_HUB)
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 3c68e3a..a25faa3 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -56,6 +56,7 @@
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
import com.android.systemui.recents.RecentsModule;
+import com.android.systemui.rotationlock.DeviceStateAutoRotateModule;
import com.android.systemui.rotationlock.RotationLockModule;
import com.android.systemui.rotationlock.RotationLockNewModule;
import com.android.systemui.scene.SceneContainerFrameworkModule;
@@ -132,6 +133,7 @@
CollapsedStatusBarFragmentStartableModule.class,
ConnectingDisplayViewModel.StartableModule.class,
DefaultBlueprintModule.class,
+ DeviceStateAutoRotateModule.class,
EmergencyGestureModule.class,
GestureModule.class,
HeadsUpModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index fe5a82c..f8cf6b0 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -105,6 +105,7 @@
import com.android.systemui.recents.Recents;
import com.android.systemui.recordissue.RecordIssueModule;
import com.android.systemui.retail.RetailModeModule;
+import com.android.systemui.rotationlock.DeviceStateAutoRotateModule.BoundsDeviceStateAutoRotateModule;
import com.android.systemui.scene.shared.model.SceneContainerConfig;
import com.android.systemui.scene.shared.model.SceneDataSource;
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator;
@@ -145,6 +146,7 @@
import com.android.systemui.statusbar.phone.ConfigurationControllerModule;
import com.android.systemui.statusbar.phone.LetterboxModule;
import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule;
+import com.android.systemui.statusbar.policy.DeviceStateRotationLockSettingController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.PolicyModule;
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
@@ -391,6 +393,11 @@
@BindsOptionalOf
abstract LockscreenContent optionalLockscreenContent();
+ @BindsOptionalOf
+ @BoundsDeviceStateAutoRotateModule
+ abstract Optional<DeviceStateRotationLockSettingController>
+ optionalDeviceStateRotationLockSettingController();
+
@SysUISingleton
@Binds
abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
@@ -466,6 +473,16 @@
return new SceneDataSourceDelegator(applicationScope, config);
}
+ @Provides
+ @SysUISingleton
+ static Optional<DeviceStateRotationLockSettingController>
+ provideDeviceStateRotationLockSettingController(
+ @BoundsDeviceStateAutoRotateModule
+ Optional<Optional<DeviceStateRotationLockSettingController>> optionalOfOptional
+ ) {
+ return optionalOfOptional.orElseGet(Optional::empty);
+ }
+
@Binds
abstract SceneDataSource bindSceneDataSource(SceneDataSourceDelegator delegator);
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt
index bd3e771..7d2492a 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt
@@ -20,7 +20,9 @@
interface TouchpadTutorialScreensProvider {
- @Composable fun BackGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit)
+ @Composable
+ fun BackGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit, isAutoProceed: Boolean)
- @Composable fun HomeGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit)
+ @Composable
+ fun HomeGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit, isAutoProceed: Boolean)
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt
index 8cbcba2..ee875c4 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt
@@ -137,6 +137,7 @@
onDoneButtonClicked = onDoneButtonClicked,
modifier = Modifier.padding(horizontal = 60.dp).graphicsLayer { alpha = buttonAlpha },
enabled = actionState is Finished,
+ isNext = config.hasNextButton,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt
index 202dba3..d92e48e 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt
@@ -32,6 +32,7 @@
onDoneButtonClicked: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
+ isNext: Boolean = false,
) {
Row(
horizontalArrangement = Arrangement.End,
@@ -39,7 +40,10 @@
modifier = modifier.fillMaxWidth(),
) {
Button(onClick = onDoneButtonClicked, enabled = enabled) {
- Text(stringResource(R.string.touchpad_tutorial_done_button))
+ val text =
+ if (isNext) R.string.touchpad_tutorial_next_button
+ else R.string.touchpad_tutorial_done_button
+ Text(stringResource(text))
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt
index eda23a5..65adc14 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt
@@ -28,6 +28,7 @@
val colors: Colors,
val strings: Strings,
val animations: Animations,
+ val hasNextButton: Boolean = false,
) {
data class Colors(
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
index 639e9b1..086705f 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
@@ -93,17 +93,29 @@
}
}
}
+ val entryPointExtra = intent.getStringExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY)
+ val isAutoProceed =
+ if (entryPointExtra == null) true
+ else entryPointExtra.equals(INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER)
+ val scopeExtra = intent.getStringExtra(INTENT_TUTORIAL_SCOPE_KEY)
+ val isScopeAll = INTENT_TUTORIAL_SCOPE_ALL.equals(scopeExtra)
setContent {
- PlatformTheme { KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) }
+ PlatformTheme {
+ KeyboardTouchpadTutorialContainer(
+ vm,
+ touchpadTutorialScreensProvider,
+ isAutoProceed,
+ isScopeAll,
+ )
+ }
}
if (savedInstanceState == null) {
logger.logOpenTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL)
- val entryPointExtra = intent.getStringExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY)
val tutorialTypeExtra = intent.getStringExtra(INTENT_TUTORIAL_SCOPE_KEY)
metricsLogger.logPeripheralTutorialLaunched(entryPointExtra, tutorialTypeExtra)
// We only update launched info when the tutorial is triggered by the scheduler
- if (entryPointExtra.equals(INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER))
+ if (INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER.equals(entryPointExtra))
updateLaunchInfo(tutorialTypeExtra)
}
}
@@ -124,17 +136,27 @@
fun KeyboardTouchpadTutorialContainer(
vm: KeyboardTouchpadTutorialViewModel,
touchpadScreens: Optional<TouchpadTutorialScreensProvider>,
+ isAutoProceed: Boolean = false,
+ isScopeAll: Boolean = false,
) {
val activeScreen by vm.screen.collectAsStateWithLifecycle(STARTED)
when (activeScreen) {
BACK_GESTURE ->
touchpadScreens
.get()
- .BackGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack)
+ .BackGesture(
+ onDoneButtonClicked = vm::onDoneButtonClicked,
+ onBack = vm::onBack,
+ isAutoProceed = isAutoProceed,
+ )
HOME_GESTURE ->
touchpadScreens
.get()
- .HomeGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack)
+ .HomeGesture(
+ onDoneButtonClicked = vm::onDoneButtonClicked,
+ onBack = vm::onBack,
+ isAutoProceed = isScopeAll,
+ )
ACTION_KEY ->
ActionKeyTutorialScreen(
onDoneButtonClicked = vm::onDoneButtonClicked,
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
index 0908e3b..a779c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
@@ -31,7 +31,6 @@
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION
-import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER
@@ -67,7 +66,6 @@
KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER to System,
KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL to System,
KEY_GESTURE_TYPE_LOCK_SCREEN to System,
- KEY_GESTURE_TYPE_OPEN_NOTES to System,
KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS to System,
KEY_GESTURE_TYPE_LAUNCH_ASSISTANT to System,
KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT to System,
@@ -113,7 +111,6 @@
R.string.shortcut_helper_category_system_controls,
KEY_GESTURE_TYPE_LOCK_SCREEN to R.string.shortcut_helper_category_system_controls,
KEY_GESTURE_TYPE_ALL_APPS to R.string.shortcut_helper_category_system_controls,
- KEY_GESTURE_TYPE_OPEN_NOTES to R.string.shortcut_helper_category_system_apps,
KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS to
R.string.shortcut_helper_category_system_apps,
KEY_GESTURE_TYPE_LAUNCH_ASSISTANT to R.string.shortcut_helper_category_system_apps,
@@ -173,7 +170,6 @@
R.string.group_system_access_notification_shade,
KEY_GESTURE_TYPE_LOCK_SCREEN to R.string.group_system_lock_screen,
KEY_GESTURE_TYPE_ALL_APPS to R.string.group_system_access_all_apps_search,
- KEY_GESTURE_TYPE_OPEN_NOTES to R.string.group_system_quick_memo,
KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS to R.string.group_system_access_system_settings,
KEY_GESTURE_TYPE_LAUNCH_ASSISTANT to R.string.group_system_access_google_assistant,
KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT to
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
index 8bed853..a7375f7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
@@ -178,11 +178,6 @@
private fun systemAppsShortcuts() =
listOf(
- // Pull up Notes app for quick memo:
- // - Meta + Ctrl + N
- shortcutInfo(resources.getString(R.string.group_system_quick_memo)) {
- command(META_META_ON or META_CTRL_ON, KEYCODE_N)
- },
// Access system settings:
// - Meta + I
shortcutInfo(resources.getString(R.string.group_system_access_system_settings)) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 97ad2d7..6b1248b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -247,14 +247,13 @@
@Provides
@SysUISingleton
static BlurConfig provideBlurConfig(@Main Resources resources) {
- int minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius);
int maxBlurRadius =
Flags.notificationShadeBlur() || Flags.bouncerUiRevamp()
|| Flags.glanceableHubBlurredBackground()
? resources.getDimensionPixelSize(R.dimen.max_shade_window_blur_radius)
: resources.getDimensionPixelSize(R.dimen.max_window_blur_radius);
- return new BlurConfig(minBlurRadius, maxBlurRadius);
+ return new BlurConfig(0.0f, maxBlurRadius);
}
/** */
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 4ad04be..ef06a85 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
@@ -20,6 +20,10 @@
import android.util.Log
import com.android.app.animation.Interpolators
import com.android.app.tracing.coroutines.launchTraced as launch
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
+import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -54,6 +58,9 @@
keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
val deviceEntryRepository: DeviceEntryRepository,
private val wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor,
+ private val communalSettingsInteractor: CommunalSettingsInteractor,
+ private val communalSceneInteractor: CommunalSceneInteractor,
+ private val communalInteractor: CommunalInteractor,
) :
TransitionInteractor(
fromState = KeyguardState.AOD,
@@ -103,6 +110,7 @@
val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value
val biometricUnlockMode = keyguardInteractor.biometricUnlockState.value.mode
val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value
+ val shouldShowCommunal = communalInteractor.shouldShowCommunal.value
if (!maybeHandleInsecurePowerGesture()) {
val shouldTransitionToLockscreen =
@@ -129,6 +137,9 @@
(!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen()) ||
(KeyguardWmStateRefactor.isEnabled && canWakeDirectlyToGone)
+ val shouldTransitionToCommunal =
+ communalSettingsInteractor.isV2FlagEnabled() && shouldShowCommunal
+
if (shouldTransitionToGone) {
// TODO(b/360368320): Adapt for scene framework
if (SceneContainerFlag.isEnabled) return@collect
@@ -137,6 +148,11 @@
modeOnCanceled = TransitionModeOnCanceled.REVERSE,
ownerReason = "canWakeDirectlyToGone = true",
)
+ } else if (shouldTransitionToCommunal) {
+ communalSceneInteractor.changeScene(
+ CommunalScenes.Communal,
+ "listen for aod to communal",
+ )
} else if (shouldTransitionToLockscreen) {
val modeOnCanceled =
if (startedStep.from == KeyguardState.LOCKSCREEN) {
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 6f5f662..0700ec6 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
@@ -159,6 +159,7 @@
val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value
val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value
val isKeyguardGoingAway = keyguardInteractor.isKeyguardGoingAway.value
+ val canStartDreaming = dreamManager.canStartDreaming(false)
if (!deviceEntryInteractor.isLockscreenEnabled()) {
if (!SceneContainerFlag.isEnabled) {
@@ -191,6 +192,13 @@
if (!SceneContainerFlag.isEnabled) {
transitionToGlanceableHub()
}
+ } else if (canStartDreaming) {
+ // If we're waking up to dream, transition directly to dreaming without
+ // showing the lockscreen.
+ startTransitionTo(
+ KeyguardState.DREAMING,
+ ownerReason = "moving from doze to dream",
+ )
} else {
startTransitionTo(KeyguardState.LOCKSCREEN)
}
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 2eeba0f..3ad862b 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
@@ -77,7 +77,7 @@
if (!communalSettingsInteractor.isCommunalFlagEnabled()) {
return
}
- listenForHubToDozing()
+ listenForHubToAodOrDozing()
listenForHubToPrimaryBouncer()
listenForHubToAlternateBouncer()
listenForHubToOccluded()
@@ -123,15 +123,15 @@
}
}
- private fun listenForHubToDozing() {
+ private fun listenForHubToAodOrDozing() {
scope.launch {
powerInteractor.isAsleep
.filterRelevantKeyguardStateAnd { isAsleep -> isAsleep }
.collect {
- communalSceneInteractor.snapToScene(
+ communalSceneInteractor.changeScene(
newScene = CommunalScenes.Blank,
- loggingReason = "hub to dozing",
- keyguardState = KeyguardState.DOZING,
+ loggingReason = "hub to sleep",
+ keyguardState = keyguardInteractor.asleepKeyguardState.value,
)
}
}
@@ -254,5 +254,6 @@
val TO_LOCKSCREEN_DURATION = 1.seconds
val TO_BOUNCER_DURATION = 400.milliseconds
val TO_OCCLUDED_DURATION = 450.milliseconds
+ val TO_AOD_DURATION = 500.milliseconds
}
}
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 da87e38..c7791cd 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
@@ -26,6 +26,8 @@
import android.view.InputDevice
import android.view.MotionEvent
import android.view.View
+import android.view.View.GONE
+import android.view.View.INVISIBLE
import android.view.View.OnLayoutChangeListener
import android.view.View.VISIBLE
import android.view.ViewGroup
@@ -304,8 +306,9 @@
if (isVisible.value) {
blueprintViewModel.refreshBlueprint()
}
- childViews[aodPromotedNotificationId]
- ?.setAodNotifIconContainerIsVisible(isVisible)
+ childViews[aodPromotedNotificationId]?.setAodPromotedNotifIsVisible(
+ isVisible
+ )
}
}
@@ -313,7 +316,7 @@
shadeInteractor.isAnyFullyExpanded.collect { isFullyAnyExpanded ->
view.visibility =
if (isFullyAnyExpanded) {
- View.INVISIBLE
+ INVISIBLE
} else {
View.VISIBLE
}
@@ -524,10 +527,10 @@
visibility =
if (isVisible.value) {
alpha = 1f
- View.VISIBLE
+ VISIBLE
} else {
alpha = 0f
- View.INVISIBLE
+ INVISIBLE
}
}
@@ -541,6 +544,36 @@
}
}
+ private fun View.setAodPromotedNotifIsVisible(isVisible: AnimatedValue<Boolean>) {
+ animate().cancel()
+ val animatorListener =
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ isVisible.stopAnimating()
+ }
+ }
+
+ if (isVisible.isAnimating) {
+ if (isVisible.value) {
+ alpha = 0f
+ visibility = VISIBLE
+ CrossFadeHelper.fadeIn(this, animatorListener)
+ } else {
+ CrossFadeHelper.fadeOut(this, animatorListener)
+ }
+ } else {
+ if (isVisible.value) {
+ alpha = 1f
+ visibility = VISIBLE
+ } else {
+ // Hide with GONE, not INVISIBLE, so there won't be a redundant bottom
+ // margin between the smart space and the shelf.
+ alpha = 0f
+ visibility = GONE
+ }
+ }
+ }
+
private fun MotionEvent.isTouchscreenSource(): Boolean {
return device?.supportsSource(InputDevice.SOURCE_TOUCHSCREEN) == true
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
index dba2578..c4a7e1e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
@@ -21,6 +21,7 @@
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.AodToGlanceableHubTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToOccludedTransitionViewModel
@@ -33,6 +34,7 @@
import com.android.systemui.keyguard.ui.viewmodel.DreamingToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GoneToAodTransitionViewModel
@@ -118,6 +120,12 @@
@Binds
@IntoSet
+ abstract fun aodToGlanceableHub(
+ impl: AodToGlanceableHubTransitionViewModel
+ ): DeviceEntryIconTransition
+
+ @Binds
+ @IntoSet
abstract fun dozingToGone(impl: DozingToGoneTransitionViewModel): DeviceEntryIconTransition
@Binds
@@ -258,6 +266,12 @@
@Binds
@IntoSet
+ abstract fun glanceableHubToAod(
+ impl: GlanceableHubToAodTransitionViewModel
+ ): DeviceEntryIconTransition
+
+ @Binds
+ @IntoSet
abstract fun occludedToGlanceableHub(
impl: OccludedToGlanceableHubTransitionViewModel
): DeviceEntryIconTransition
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGlanceableHubTransitionViewModel.kt
new file mode 100644
index 0000000..45f8f10
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGlanceableHubTransitionViewModel.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import android.util.MathUtils
+import com.android.systemui.Flags.lightRevealMigration
+import com.android.systemui.communal.ui.compose.TransitionDuration
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
+import com.android.systemui.keyguard.shared.model.Edge
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
+import com.android.systemui.scene.shared.model.Scenes
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+
+@SysUISingleton
+class AodToGlanceableHubTransitionViewModel
+@Inject
+constructor(
+ animationFlow: KeyguardTransitionAnimationFlow,
+ blurFactory: GlanceableHubBlurComponent.Factory,
+) : DeviceEntryIconTransition, GlanceableHubTransition {
+ private val transitionAnimation =
+ animationFlow
+ .setup(
+ duration = TransitionDuration.TO_GLANCEABLE_HUB_DURATION_MS.milliseconds,
+ edge = Edge.create(AOD, Scenes.Communal),
+ )
+ .setupWithoutSceneContainer(edge = Edge.create(AOD, GLANCEABLE_HUB))
+
+ override val deviceEntryParentViewAlpha: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(1f)
+
+ /** Fade out the lockscreen during a transition to GLANCEABLE_HUB. */
+ fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> {
+ var currentAlpha = 0f
+ return transitionAnimation.sharedFlow(
+ duration = 250.milliseconds,
+ startTime =
+ if (lightRevealMigration()) {
+ 100.milliseconds // Wait for the light reveal to "hit" the LS elements.
+ } else {
+ 0.milliseconds
+ },
+ onStart = {
+ currentAlpha =
+ if (lightRevealMigration()) {
+ viewState.alpha()
+ } else {
+ 0f
+ }
+ },
+ onStep = { MathUtils.lerp(currentAlpha, 0f, it) },
+ )
+ }
+
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().enterBlurRadius
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
index 75bba48..0ccb24a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
@@ -60,6 +60,7 @@
primaryBouncerToDozingTransitionViewModel: PrimaryBouncerToDozingTransitionViewModel,
primaryBouncerToLockscreenTransitionViewModel: PrimaryBouncerToLockscreenTransitionViewModel,
lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel,
+ glanceableHubToAodTransitionViewModel: GlanceableHubToAodTransitionViewModel,
) {
val color: Flow<Int> =
deviceEntryIconViewModel.useBackgroundProtection.flatMapLatest { useBackground ->
@@ -106,6 +107,7 @@
primaryBouncerToLockscreenTransitionViewModel
.deviceEntryBackgroundViewAlpha,
lockscreenToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
+ glanceableHubToAodTransitionViewModel.deviceEntryBackgroundViewAlpha,
)
.merge()
.onStart {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt
index e6a85c6..9018c58 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToDreamingTransitionViewModel.kt
@@ -39,4 +39,6 @@
)
val lockscreenAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(0f)
+ // Notifications should not be shown while transitioning to dream.
+ val notificationAlpha = transitionAnimation.immediatelyTransitionTo(0f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToAodTransitionViewModel.kt
new file mode 100644
index 0000000..6a45845
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToAodTransitionViewModel.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.FromGlanceableHubTransitionInteractor
+import com.android.systemui.keyguard.shared.model.Edge
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.scene.shared.model.Scenes
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flatMapLatest
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class GlanceableHubToAodTransitionViewModel
+@Inject
+constructor(
+ deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ animationFlow: KeyguardTransitionAnimationFlow,
+) : DeviceEntryIconTransition {
+
+ private val transitionAnimation =
+ animationFlow
+ .setup(
+ duration = FromGlanceableHubTransitionInteractor.TO_AOD_DURATION,
+ edge = Edge.create(from = Scenes.Communal, to = AOD),
+ )
+ .setupWithoutSceneContainer(edge = Edge.create(KeyguardState.GLANCEABLE_HUB, AOD))
+
+ val deviceEntryBackgroundViewAlpha: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(0f)
+
+ /** Lockscreen views alpha */
+ val lockscreenAlpha: Flow<Float> =
+ transitionAnimation.sharedFlow(
+ startTime = 233.milliseconds,
+ duration = 250.milliseconds,
+ onStep = { it },
+ )
+
+ override val deviceEntryParentViewAlpha: Flow<Float> =
+ deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { udfpsEnrolledAndEnabled
+ ->
+ if (udfpsEnrolledAndEnabled) {
+ transitionAnimation.immediatelyTransitionTo(1f)
+ } else {
+ emptyFlow()
+ }
+ }
+}
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 8e21745..def87a8 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
@@ -100,6 +100,7 @@
private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
private val aodToOccludedTransitionViewModel: AodToOccludedTransitionViewModel,
private val aodToPrimaryBouncerTransitionViewModel: AodToPrimaryBouncerTransitionViewModel,
+ private val aodToGlanceableHubTransitionViewModel: AodToGlanceableHubTransitionViewModel,
private val dozingToDreamingTransitionViewModel: DozingToDreamingTransitionViewModel,
private val dozingToGoneTransitionViewModel: DozingToGoneTransitionViewModel,
private val dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
@@ -111,6 +112,7 @@
private val dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
private val glanceableHubToLockscreenTransitionViewModel:
GlanceableHubToLockscreenTransitionViewModel,
+ private val glanceableHubToAodTransitionViewModel: GlanceableHubToAodTransitionViewModel,
private val goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
private val goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel,
private val goneToDreamingTransitionViewModel: GoneToDreamingTransitionViewModel,
@@ -258,6 +260,7 @@
aodToLockscreenTransitionViewModel.lockscreenAlpha(viewState),
aodToOccludedTransitionViewModel.lockscreenAlpha(viewState),
aodToPrimaryBouncerTransitionViewModel.lockscreenAlpha,
+ aodToGlanceableHubTransitionViewModel.lockscreenAlpha(viewState),
dozingToDreamingTransitionViewModel.lockscreenAlpha,
dozingToGoneTransitionViewModel.lockscreenAlpha(viewState),
dozingToLockscreenTransitionViewModel.lockscreenAlpha,
@@ -267,6 +270,7 @@
dreamingToGoneTransitionViewModel.lockscreenAlpha,
dreamingToLockscreenTransitionViewModel.lockscreenAlpha,
glanceableHubToLockscreenTransitionViewModel.keyguardAlpha,
+ glanceableHubToAodTransitionViewModel.lockscreenAlpha,
goneToAodTransitionViewModel.enterFromTopAnimationAlpha,
goneToDozingTransitionViewModel.lockscreenAlpha,
goneToDreamingTransitionViewModel.lockscreenAlpha,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransition.kt
index 21407f3..9badf85 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransition.kt
@@ -27,6 +27,7 @@
import com.android.internal.R
import com.android.internal.annotations.VisibleForTesting
import com.android.settingslib.Utils
+import com.android.systemui.Flags
import com.android.systemui.media.controls.ui.view.MediaViewHolder
import com.android.systemui.monet.ColorScheme
import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect
@@ -51,7 +52,7 @@
open class AnimatingColorTransition(
private val defaultColor: Int,
private val extractColor: (ColorScheme) -> Int,
- private val applyColor: (Int) -> Unit
+ private val applyColor: (Int) -> Unit,
) : AnimatorUpdateListener, ColorTransition {
private val argbEvaluator = ArgbEvaluator()
@@ -105,24 +106,60 @@
private val mediaViewHolder: MediaViewHolder,
private val multiRippleController: MultiRippleController,
private val turbulenceNoiseController: TurbulenceNoiseController,
- animatingColorTransitionFactory: AnimatingColorTransitionFactory
+ animatingColorTransitionFactory: AnimatingColorTransitionFactory,
) {
constructor(
context: Context,
mediaViewHolder: MediaViewHolder,
multiRippleController: MultiRippleController,
- turbulenceNoiseController: TurbulenceNoiseController
+ turbulenceNoiseController: TurbulenceNoiseController,
) : this(
context,
mediaViewHolder,
multiRippleController,
turbulenceNoiseController,
- ::AnimatingColorTransition
+ ::AnimatingColorTransition,
)
+
var loadingEffect: LoadingEffect? = null
- val bgColor = context.getColor(com.google.android.material.R.color.material_dynamic_neutral20)
- val surfaceColor =
+ // Defaults may be briefly visible before loading a new player's colors
+ private val backgroundDefault = context.getColor(R.color.system_on_surface_light)
+ private val primaryDefault = context.getColor(R.color.system_primary_dark)
+ private val onPrimaryDefault = context.getColor(R.color.system_on_primary_dark)
+
+ private val backgroundColor: AnimatingColorTransition by lazy {
+ animatingColorTransitionFactory(backgroundDefault, ::backgroundFromScheme) { color ->
+ mediaViewHolder.albumView.backgroundTintList = ColorStateList.valueOf(color)
+ }
+ }
+
+ private val primaryColor: AnimatingColorTransition by lazy {
+ animatingColorTransitionFactory(primaryDefault, ::primaryFromScheme) { primaryColor ->
+ val primaryColorList = ColorStateList.valueOf(primaryColor)
+ mediaViewHolder.actionPlayPause.backgroundTintList = primaryColorList
+ mediaViewHolder.seamlessButton.backgroundTintList = primaryColorList
+ (mediaViewHolder.seamlessButton.background as? RippleDrawable)?.let {
+ it.setColor(primaryColorList)
+ it.effectColor = primaryColorList
+ }
+ mediaViewHolder.seekBar.progressBackgroundTintList = primaryColorList
+ }
+ }
+
+ private val onPrimaryColor: AnimatingColorTransition by lazy {
+ animatingColorTransitionFactory(onPrimaryDefault, ::onPrimaryFromScheme) { onPrimaryColor ->
+ val onPrimaryColorList = ColorStateList.valueOf(onPrimaryColor)
+ mediaViewHolder.actionPlayPause.imageTintList = onPrimaryColorList
+ mediaViewHolder.seamlessText.setTextColor(onPrimaryColor)
+ mediaViewHolder.seamlessIcon.imageTintList = onPrimaryColorList
+ }
+ }
+
+ // TODO(media_controls_a11y_colors): remove the below color definitions
+ private val bgColor =
+ context.getColor(com.google.android.material.R.color.material_dynamic_neutral20)
+ private val surfaceColor: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(bgColor, ::surfaceFromScheme) { surfaceColor ->
val colorList = ColorStateList.valueOf(surfaceColor)
mediaViewHolder.seamlessIcon.imageTintList = colorList
@@ -130,10 +167,12 @@
mediaViewHolder.albumView.backgroundTintList = colorList
mediaViewHolder.gutsViewHolder.setSurfaceColor(surfaceColor)
}
- val accentPrimary =
+ }
+
+ private val accentPrimary: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimary),
- ::accentPrimaryFromScheme
+ ::accentPrimaryFromScheme,
) { accentPrimary ->
val accentColorList = ColorStateList.valueOf(accentPrimary)
mediaViewHolder.actionPlayPause.backgroundTintList = accentColorList
@@ -142,11 +181,12 @@
turbulenceNoiseController.updateNoiseColor(accentPrimary)
loadingEffect?.updateColor(accentPrimary)
}
+ }
- val accentSecondary =
+ private val accentSecondary: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimary),
- ::accentSecondaryFromScheme
+ ::accentSecondaryFromScheme,
) { accentSecondary ->
val colorList = ColorStateList.valueOf(accentSecondary)
(mediaViewHolder.seamlessButton.background as? RippleDrawable)?.let {
@@ -154,8 +194,9 @@
it.effectColor = colorList
}
}
+ }
- val colorSeamless =
+ private val colorSeamless: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimary),
{ colorScheme: ColorScheme ->
@@ -170,13 +211,14 @@
{ seamlessColor: Int ->
val accentColorList = ColorStateList.valueOf(seamlessColor)
mediaViewHolder.seamlessButton.backgroundTintList = accentColorList
- }
+ },
)
+ }
- val textPrimary =
+ private val textPrimary: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimary),
- ::textPrimaryFromScheme
+ ::textPrimaryFromScheme,
) { textPrimary ->
mediaViewHolder.titleText.setTextColor(textPrimary)
val textColorList = ColorStateList.valueOf(textPrimary)
@@ -189,44 +231,81 @@
}
mediaViewHolder.gutsViewHolder.setTextPrimaryColor(textPrimary)
}
+ }
- val textPrimaryInverse =
+ private val textPrimaryInverse: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimaryInverse),
- ::textPrimaryInverseFromScheme
+ ::textPrimaryInverseFromScheme,
) { textPrimaryInverse ->
mediaViewHolder.actionPlayPause.imageTintList =
ColorStateList.valueOf(textPrimaryInverse)
}
+ }
- val textSecondary =
+ private val textSecondary: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorSecondary),
- ::textSecondaryFromScheme
+ ::textSecondaryFromScheme,
) { textSecondary ->
mediaViewHolder.artistText.setTextColor(textSecondary)
}
+ }
- val textTertiary =
+ private val textTertiary: AnimatingColorTransition by lazy {
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorTertiary),
- ::textTertiaryFromScheme
+ ::textTertiaryFromScheme,
) { textTertiary ->
mediaViewHolder.seekBar.progressBackgroundTintList =
ColorStateList.valueOf(textTertiary)
}
+ }
- val colorTransitions =
- arrayOf(
- surfaceColor,
- colorSeamless,
- accentPrimary,
- accentSecondary,
- textPrimary,
- textPrimaryInverse,
- textSecondary,
- textTertiary,
- )
+ fun getDeviceIconColor(): Int {
+ if (Flags.mediaControlsA11yColors()) {
+ return onPrimaryColor.targetColor
+ }
+ return surfaceColor.targetColor
+ }
+
+ fun getAppIconColor(): Int {
+ if (Flags.mediaControlsA11yColors()) {
+ return primaryColor.targetColor
+ }
+ return accentPrimary.targetColor
+ }
+
+ fun getSurfaceEffectColor(): Int {
+ if (Flags.mediaControlsA11yColors()) {
+ return primaryColor.targetColor
+ }
+ return accentPrimary.targetColor
+ }
+
+ fun getGutsTextColor(): Int {
+ if (Flags.mediaControlsA11yColors()) {
+ return context.getColor(com.android.systemui.res.R.color.media_on_background)
+ }
+ return textPrimary.targetColor
+ }
+
+ private fun getColorTransitions(): Array<AnimatingColorTransition> {
+ return if (Flags.mediaControlsA11yColors()) {
+ arrayOf(backgroundColor, primaryColor, onPrimaryColor)
+ } else {
+ arrayOf(
+ surfaceColor,
+ colorSeamless,
+ accentPrimary,
+ accentSecondary,
+ textPrimary,
+ textPrimaryInverse,
+ textSecondary,
+ textTertiary,
+ )
+ }
+ }
private fun loadDefaultColor(id: Int): Int {
return Utils.getColorAttr(context, id).defaultColor
@@ -234,15 +313,26 @@
fun updateColorScheme(colorScheme: ColorScheme?): Boolean {
var anyChanged = false
- colorTransitions.forEach {
+ getColorTransitions().forEach {
val isChanged = it.updateColorScheme(colorScheme)
// Ignore changes to colorSeamless, since that is expected when toggling dark mode
+ // TODO(media_controls_a11y_colors): remove, not necessary
if (it == colorSeamless) return@forEach
anyChanged = isChanged || anyChanged
}
- colorScheme?.let { mediaViewHolder.gutsViewHolder.colorScheme = colorScheme }
+ if (Flags.mediaControlsA11yColors()) {
+ getSurfaceEffectColor().let {
+ multiRippleController.updateColor(it)
+ turbulenceNoiseController.updateNoiseColor(it)
+ loadingEffect?.updateColor(it)
+ }
+ mediaViewHolder.gutsViewHolder.setTextColor(getGutsTextColor())
+ colorScheme?.let { mediaViewHolder.gutsViewHolder.setColors(it) }
+ } else {
+ colorScheme?.let { mediaViewHolder.gutsViewHolder.colorScheme = colorScheme }
+ }
return anyChanged
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/MediaColorSchemes.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/MediaColorSchemes.kt
index 3c57c83..67113a4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/MediaColorSchemes.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/animation/MediaColorSchemes.kt
@@ -19,28 +19,43 @@
import com.android.systemui.monet.ColorScheme
/** Returns the surface color for media controls based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun surfaceFromScheme(scheme: ColorScheme) = scheme.accent2.s800 // A2-800
/** Returns the primary accent color for media controls based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun accentPrimaryFromScheme(scheme: ColorScheme) = scheme.accent1.s100 // A1-100
/** Returns the secondary accent color for media controls based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun accentSecondaryFromScheme(scheme: ColorScheme) = scheme.accent1.s200 // A1-200
/** Returns the primary text color for media controls based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun textPrimaryFromScheme(scheme: ColorScheme) = scheme.neutral1.s50 // N1-50
/** Returns the inverse of the primary text color for media controls based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun textPrimaryInverseFromScheme(scheme: ColorScheme) = scheme.neutral1.s900 // N1-900
/** Returns the secondary text color for media controls based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun textSecondaryFromScheme(scheme: ColorScheme) = scheme.neutral2.s200 // N2-200
/** Returns the tertiary text color for media controls based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun textTertiaryFromScheme(scheme: ColorScheme) = scheme.neutral2.s400 // N2-400
/** Returns the color for the start of the background gradient based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun backgroundStartFromScheme(scheme: ColorScheme) = scheme.accent2.s700 // A2-700
/** Returns the color for the end of the background gradient based on the scheme. */
+@Deprecated("Remove with media_controls_a11y_colors")
internal fun backgroundEndFromScheme(scheme: ColorScheme) = scheme.accent1.s700 // A1-700
+
+internal fun backgroundFromScheme(scheme: ColorScheme) = scheme.materialScheme.getOnSurface()
+
+internal fun primaryFromScheme(scheme: ColorScheme) = scheme.materialScheme.getPrimaryFixed()
+
+internal fun onPrimaryFromScheme(scheme: ColorScheme) = scheme.materialScheme.getOnPrimaryFixed()
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
index 910d3a8..3f53820 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
@@ -36,6 +36,7 @@
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.settingslib.widget.AdaptiveIcon
+import com.android.systemui.Flags
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Background
@@ -49,7 +50,9 @@
import com.android.systemui.media.controls.ui.viewmodel.MediaActionViewModel
import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel
import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.MEDIA_PLAYER_SCRIM_END_ALPHA
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.MEDIA_PLAYER_SCRIM_END_ALPHA_LEGACY
import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.MEDIA_PLAYER_SCRIM_START_ALPHA
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.MEDIA_PLAYER_SCRIM_START_ALPHA_LEGACY
import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.SEMANTIC_ACTIONS_ALL
import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.SEMANTIC_ACTIONS_COMPACT
import com.android.systemui.media.controls.ui.viewmodel.MediaOutputSwitcherViewModel
@@ -198,7 +201,9 @@
is Icon.Loaded -> {
val icon = viewModel.deviceIcon.drawable
if (icon is AdaptiveIcon) {
- icon.setBackgroundColor(viewController.colorSchemeTransition.bgColor)
+ icon.setBackgroundColor(
+ viewController.colorSchemeTransition.getDeviceIconColor()
+ )
}
viewHolder.seamlessIcon.setImageDrawable(icon)
}
@@ -431,11 +436,16 @@
TAG,
)
val isArtworkBound = wallpaperColors != null
+ val darkTheme = !Flags.mediaControlsA11yColors()
val scheme =
- wallpaperColors?.let { ColorScheme(it, true, Style.CONTENT) }
+ wallpaperColors?.let { ColorScheme(it, darkTheme, Style.CONTENT) }
?: let {
if (viewModel.launcherIcon is Icon.Loaded) {
- MediaArtworkHelper.getColorScheme(viewModel.launcherIcon.drawable, TAG)
+ MediaArtworkHelper.getColorScheme(
+ viewModel.launcherIcon.drawable,
+ TAG,
+ darkTheme,
+ )
} else {
null
}
@@ -496,7 +506,7 @@
}
} else {
viewHolder.appIcon.setColorFilter(
- viewController.colorSchemeTransition.accentPrimary.targetColor
+ viewController.colorSchemeTransition.getAppIconColor()
)
viewHolder.appIcon.setImageIcon(viewModel.appIcon)
}
@@ -528,12 +538,24 @@
height: Int,
): LayerDrawable {
val albumArt = MediaArtworkHelper.getScaledBackground(context, artworkIcon, width, height)
+ val startAlpha =
+ if (Flags.mediaControlsA11yColors()) {
+ MEDIA_PLAYER_SCRIM_START_ALPHA
+ } else {
+ MEDIA_PLAYER_SCRIM_START_ALPHA_LEGACY
+ }
+ val endAlpha =
+ if (Flags.mediaControlsA11yColors()) {
+ MEDIA_PLAYER_SCRIM_END_ALPHA
+ } else {
+ MEDIA_PLAYER_SCRIM_END_ALPHA_LEGACY
+ }
return MediaArtworkHelper.setUpGradientColorOnDrawable(
albumArt,
context.getDrawable(R.drawable.qs_media_scrim)?.mutate() as GradientDrawable,
mutableColorScheme,
- MEDIA_PLAYER_SCRIM_START_ALPHA,
- MEDIA_PLAYER_SCRIM_END_ALPHA,
+ startAlpha,
+ endAlpha,
)
}
@@ -572,7 +594,7 @@
maxSize,
maxSize,
button.context.resources.displayMetrics.density,
- colorSchemeTransition.accentPrimary.currentColor,
+ colorSchemeTransition.getSurfaceEffectColor(),
opacity = 100,
sparkleStrength = 0f,
baseRingFadeParams = null,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/SeekBarObserver.kt
index 34f7c4d..c9716be 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/SeekBarObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/SeekBarObserver.kt
@@ -18,6 +18,9 @@
import android.animation.Animator
import android.animation.ObjectAnimator
+import android.icu.text.MeasureFormat
+import android.icu.util.Measure
+import android.icu.util.MeasureUnit
import android.text.format.DateUtils
import androidx.annotation.UiThread
import androidx.lifecycle.Observer
@@ -28,8 +31,11 @@
import com.android.systemui.media.controls.ui.view.MediaViewHolder
import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel
import com.android.systemui.res.R
+import java.util.Locale
private const val TAG = "SeekBarObserver"
+private const val MIN_IN_SEC = 60
+private const val HOUR_IN_SEC = MIN_IN_SEC * 60
/**
* Observer for changes from SeekBarViewModel.
@@ -127,10 +133,9 @@
}
holder.seekBar.setMax(data.duration)
- val totalTimeString =
- DateUtils.formatElapsedTime(data.duration / DateUtils.SECOND_IN_MILLIS)
+ val totalTimeDescription = formatTimeContentDescription(data.duration)
if (data.scrubbing) {
- holder.scrubbingTotalTimeView.text = totalTimeString
+ holder.scrubbingTotalTimeView.text = formatTimeLabel(data.duration)
}
data.elapsedTime?.let {
@@ -148,20 +153,62 @@
}
}
- val elapsedTimeString = DateUtils.formatElapsedTime(it / DateUtils.SECOND_IN_MILLIS)
+ val elapsedTimeDescription = formatTimeContentDescription(it)
if (data.scrubbing) {
- holder.scrubbingElapsedTimeView.text = elapsedTimeString
+ holder.scrubbingElapsedTimeView.text = formatTimeLabel(it)
}
holder.seekBar.contentDescription =
holder.seekBar.context.getString(
R.string.controls_media_seekbar_description,
- elapsedTimeString,
- totalTimeString
+ elapsedTimeDescription,
+ totalTimeDescription,
)
}
}
+ /** Returns a time string suitable for display, e.g. "12:34" */
+ private fun formatTimeLabel(milliseconds: Int): CharSequence {
+ return DateUtils.formatElapsedTime(milliseconds / DateUtils.SECOND_IN_MILLIS)
+ }
+
+ /**
+ * Returns a time string suitable for content description, e.g. "12 minutes 34 seconds"
+ *
+ * Follows same logic as Chronometer#formatDuration
+ */
+ private fun formatTimeContentDescription(milliseconds: Int): CharSequence {
+ var seconds = milliseconds / DateUtils.SECOND_IN_MILLIS
+
+ val hours =
+ if (seconds >= HOUR_IN_SEC) {
+ seconds / HOUR_IN_SEC
+ } else {
+ 0
+ }
+ seconds -= hours * HOUR_IN_SEC
+
+ val minutes =
+ if (seconds >= MIN_IN_SEC) {
+ seconds / MIN_IN_SEC
+ } else {
+ 0
+ }
+ seconds -= minutes * MIN_IN_SEC
+
+ val measures = arrayListOf<Measure>()
+ if (hours > 0) {
+ measures.add(Measure(hours, MeasureUnit.HOUR))
+ }
+ if (minutes > 0) {
+ measures.add(Measure(minutes, MeasureUnit.MINUTE))
+ }
+ measures.add(Measure(seconds, MeasureUnit.SECOND))
+
+ return MeasureFormat.getInstance(Locale.getDefault(), MeasureFormat.FormatWidth.WIDE)
+ .formatMeasures(*measures.toTypedArray())
+ }
+
@VisibleForTesting
open fun buildResetAnimator(targetTime: Int): Animator {
val animator =
@@ -169,7 +216,7 @@
holder.seekBar,
"progress",
holder.seekBar.progress,
- targetTime + RESET_ANIMATION_DURATION_MS
+ targetTime + RESET_ANIMATION_DURATION_MS,
)
animator.setAutoCancel(true)
animator.duration = RESET_ANIMATION_DURATION_MS.toLong()
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
index 606f71a..d26a723 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
@@ -55,7 +55,7 @@
private val bypassController: KeyguardBypassController,
private val statusBarStateController: SysuiStatusBarStateController,
@ShadeDisplayAware private val context: Context,
- configurationController: ConfigurationController,
+ @ShadeDisplayAware configurationController: ConfigurationController,
private val splitShadeStateController: SplitShadeStateController,
private val logger: KeyguardMediaControllerLogger,
dumpManager: DumpManager,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index 93c4baf..55d8b8c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -132,7 +132,7 @@
@Inject
constructor(
@Application applicationScope: CoroutineScope,
- private val context: Context,
+ @Main private val context: Context,
private val mediaControlPanelFactory: Provider<MediaControlPanel>,
private val visualStabilityProvider: VisualStabilityProvider,
private val mediaHostStatesManager: MediaHostStatesManager,
@@ -143,7 +143,7 @@
@Background private val bgExecutor: Executor,
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val mediaManager: MediaDataManager,
- configurationController: ConfigurationController,
+ @Main configurationController: ConfigurationController,
private val falsingManager: FalsingManager,
dumpManager: DumpManager,
private val logger: MediaUiEventLogger,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index 2bf6a10..694a4c7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -23,6 +23,10 @@
import static com.android.systemui.Flags.mediaLockscreenLaunchAnimation;
import static com.android.systemui.media.controls.domain.pipeline.MediaActionsKt.getNotificationActions;
import static com.android.systemui.media.controls.shared.model.SmartspaceMediaDataKt.NUM_REQUIRED_RECOMMENDATIONS;
+import static com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.MEDIA_PLAYER_SCRIM_END_ALPHA;
+import static com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.MEDIA_PLAYER_SCRIM_END_ALPHA_LEGACY;
+import static com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.MEDIA_PLAYER_SCRIM_START_ALPHA;
+import static com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.MEDIA_PLAYER_SCRIM_START_ALPHA_LEGACY;
import android.animation.Animator;
import android.animation.AnimatorInflater;
@@ -175,9 +179,7 @@
protected static final int SMARTSPACE_CARD_DISMISS_EVENT = 761;
private static final float REC_MEDIA_COVER_SCALE_FACTOR = 1.25f;
- private static final float MEDIA_SCRIM_START_ALPHA = 0.25f;
private static final float MEDIA_REC_SCRIM_START_ALPHA = 0.15f;
- private static final float MEDIA_PLAYER_SCRIM_END_ALPHA = 1.0f;
private static final float MEDIA_REC_SCRIM_END_ALPHA = 1.0f;
private static final Intent SETTINGS_INTENT = new Intent(ACTION_MEDIA_CONTROLS_SETTINGS);
@@ -305,7 +307,7 @@
*/
@Inject
public MediaControlPanel(
- Context context,
+ @Main Context context,
@Background Executor backgroundExecutor,
@Main DelayableExecutor mainExecutor,
ActivityStarter activityStarter,
@@ -730,7 +732,7 @@
Drawable icon = device.getIcon();
if (icon instanceof AdaptiveIcon) {
AdaptiveIcon aIcon = (AdaptiveIcon) icon;
- aIcon.setBackgroundColor(mColorSchemeTransition.getBgColor());
+ aIcon.setBackgroundColor(mColorSchemeTransition.getDeviceIconColor());
iconView.setImageDrawable(aIcon);
} else {
iconView.setImageDrawable(icon);
@@ -921,8 +923,9 @@
boolean isArtworkBound;
Icon artworkIcon = data.getArtwork();
WallpaperColors wallpaperColors = getWallpaperColor(artworkIcon);
+ boolean darkTheme = !Flags.mediaControlsA11yColors();
if (wallpaperColors != null) {
- mutableColorScheme = new ColorScheme(wallpaperColors, true, Style.CONTENT);
+ mutableColorScheme = new ColorScheme(wallpaperColors, darkTheme, Style.CONTENT);
artwork = addGradientToPlayerAlbum(artworkIcon, mutableColorScheme, finalWidth,
finalHeight);
isArtworkBound = true;
@@ -933,8 +936,8 @@
try {
Drawable icon = mContext.getPackageManager()
.getApplicationIcon(data.getPackageName());
- mutableColorScheme = new ColorScheme(WallpaperColors.fromDrawable(icon), true,
- Style.CONTENT);
+ mutableColorScheme = new ColorScheme(WallpaperColors.fromDrawable(icon),
+ darkTheme, Style.CONTENT);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e);
}
@@ -950,7 +953,8 @@
mArtworkBoundId = reqId;
// Transition Colors to current color scheme
- boolean colorSchemeChanged = mColorSchemeTransition.updateColorScheme(colorScheme);
+ boolean colorSchemeChanged;
+ colorSchemeChanged = mColorSchemeTransition.updateColorScheme(colorScheme);
// Bind the album view to the artwork or a transition drawable
ImageView albumView = mMediaViewHolder.getAlbumView();
@@ -973,7 +977,6 @@
transitionDrawable.setLayerGravity(0, Gravity.CENTER);
transitionDrawable.setLayerGravity(1, Gravity.CENTER);
transitionDrawable.setCrossFadeEnabled(true);
-
albumView.setImageDrawable(transitionDrawable);
transitionDrawable.startTransition(isArtworkBound ? 333 : 80);
}
@@ -986,8 +989,7 @@
appIconView.clearColorFilter();
if (data.getAppIcon() != null && !data.getResumption()) {
appIconView.setImageIcon(data.getAppIcon());
- appIconView.setColorFilter(
- mColorSchemeTransition.getAccentPrimary().getTargetColor());
+ appIconView.setColorFilter(mColorSchemeTransition.getAppIconColor());
} else {
// Resume players use launcher icon
appIconView.setColorFilter(getGrayscaleFilter());
@@ -1092,8 +1094,12 @@
Drawable albumArt = getScaledBackground(artworkIcon, width, height);
GradientDrawable gradient = (GradientDrawable) mContext.getDrawable(
R.drawable.qs_media_scrim).mutate();
+ if (Flags.mediaControlsA11yColors()) {
+ return setupGradientColorOnDrawable(albumArt, gradient, mutableColorScheme,
+ MEDIA_PLAYER_SCRIM_START_ALPHA, MEDIA_PLAYER_SCRIM_END_ALPHA);
+ }
return setupGradientColorOnDrawable(albumArt, gradient, mutableColorScheme,
- MEDIA_SCRIM_START_ALPHA, MEDIA_PLAYER_SCRIM_END_ALPHA);
+ MEDIA_PLAYER_SCRIM_START_ALPHA_LEGACY, MEDIA_PLAYER_SCRIM_END_ALPHA_LEGACY);
}
@VisibleForTesting
@@ -1113,12 +1119,21 @@
private LayerDrawable setupGradientColorOnDrawable(Drawable albumArt, GradientDrawable gradient,
ColorScheme mutableColorScheme, float startAlpha, float endAlpha) {
+ int startColor;
+ int endColor;
+ if (Flags.mediaControlsA11yColors()) {
+ startColor = MediaColorSchemesKt.backgroundFromScheme(mutableColorScheme);
+ endColor = startColor;
+ } else {
+ startColor = MediaColorSchemesKt.backgroundStartFromScheme(mutableColorScheme);
+ endColor = MediaColorSchemesKt.backgroundEndFromScheme(mutableColorScheme);
+ }
gradient.setColors(new int[]{
ColorUtilKt.getColorWithAlpha(
- MediaColorSchemesKt.backgroundStartFromScheme(mutableColorScheme),
+ startColor,
startAlpha),
ColorUtilKt.getColorWithAlpha(
- MediaColorSchemesKt.backgroundEndFromScheme(mutableColorScheme),
+ endColor,
endAlpha),
});
return new LayerDrawable(new Drawable[]{albumArt, gradient});
@@ -1308,7 +1323,7 @@
/* maxWidth= */ maxSize,
/* maxHeight= */ maxSize,
/* pixelDensity= */ getContext().getResources().getDisplayMetrics().density,
- mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
+ /* color= */ mColorSchemeTransition.getSurfaceEffectColor(),
/* opacity= */ 100,
/* sparkleStrength= */ 0f,
/* baseRingFadeParams= */ null,
@@ -1330,10 +1345,13 @@
int width = targetView.getWidth();
int height = targetView.getHeight();
Random random = new Random();
+ float luminosity = (Flags.mediaControlsA11yColors())
+ ? 0.6f
+ : TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER;
return new TurbulenceNoiseAnimationConfig(
/* gridCount= */ 2.14f,
- TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
+ /* luminosityMultiplier= */ luminosity,
/* noiseOffsetX= */ random.nextFloat(),
/* noiseOffsetY= */ random.nextFloat(),
/* noiseOffsetZ= */ random.nextFloat(),
@@ -1341,7 +1359,7 @@
/* noiseMoveSpeedY= */ 0f,
TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z,
// Color will be correctly updated in ColorSchemeTransition.
- /* color= */ mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
+ /* color= */ mColorSchemeTransition.getSurfaceEffectColor(),
/* screenColor= */ Color.BLACK,
width,
height,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index 2059394..b64cb3d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -113,7 +113,7 @@
private val dreamOverlayStateController: DreamOverlayStateController,
private val keyguardInteractor: KeyguardInteractor,
communalTransitionViewModel: CommunalTransitionViewModel,
- configurationController: ConfigurationController,
+ @ShadeDisplayAware configurationController: ConfigurationController,
wakefulnessLifecycle: WakefulnessLifecycle,
shadeInteractor: ShadeInteractor,
private val secureSettings: SecureSettings,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
index 2b36872..b687dce 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
@@ -81,8 +81,8 @@
open class MediaViewController
@Inject
constructor(
- private val context: Context,
- private val configurationController: ConfigurationController,
+ @Main private val context: Context,
+ @Main private val configurationController: ConfigurationController,
private val mediaHostStatesManager: MediaHostStatesManager,
private val logger: MediaViewLogger,
private val seekBarViewModel: SeekBarViewModel,
@@ -1137,6 +1137,7 @@
) {
gutsViewHolder.gutsText.setTypeface(menuTF)
gutsViewHolder.dismissText.setTypeface(menuTF)
+ gutsViewHolder.cancelText.setTypeface(menuTF)
titleText.setTypeface(titleTF)
artistText.setTypeface(artistTF)
seamlessText.setTypeface(menuTF)
@@ -1237,9 +1238,15 @@
val width = targetView.width
val height = targetView.height
val random = Random()
+ val luminosity =
+ if (Flags.mediaControlsA11yColors()) {
+ 0.6f
+ } else {
+ TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER
+ }
return TurbulenceNoiseAnimationConfig(
gridCount = 2.14f,
- TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
+ luminosity,
random.nextFloat(),
random.nextFloat(),
random.nextFloat(),
@@ -1247,7 +1254,7 @@
noiseMoveSpeedY = 0f,
TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z,
// Color will be correctly updated in ColorSchemeTransition.
- colorSchemeTransition.accentPrimary.currentColor,
+ colorSchemeTransition.getSurfaceEffectColor(),
screenColor = Color.BLACK,
width.toFloat(),
height.toFloat(),
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
index 14a4e26..5570325 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
@@ -25,7 +25,9 @@
import android.graphics.drawable.Icon
import android.graphics.drawable.LayerDrawable
import android.util.Log
+import com.android.systemui.Flags
import com.android.systemui.media.controls.ui.animation.backgroundEndFromScheme
+import com.android.systemui.media.controls.ui.animation.backgroundFromScheme
import com.android.systemui.media.controls.ui.animation.backgroundStartFromScheme
import com.android.systemui.monet.ColorScheme
import com.android.systemui.monet.Style
@@ -89,22 +91,30 @@
startAlpha: Float,
endAlpha: Float,
): LayerDrawable {
+ val startColor =
+ if (Flags.mediaControlsA11yColors()) {
+ backgroundFromScheme(colorScheme)
+ } else {
+ backgroundStartFromScheme(colorScheme)
+ }
+ val endColor =
+ if (Flags.mediaControlsA11yColors()) {
+ startColor
+ } else {
+ backgroundEndFromScheme(colorScheme)
+ }
gradient.colors =
intArrayOf(
- getColorWithAlpha(backgroundStartFromScheme(colorScheme), startAlpha),
- getColorWithAlpha(backgroundEndFromScheme(colorScheme), endAlpha),
+ getColorWithAlpha(startColor, startAlpha),
+ getColorWithAlpha(endColor, endAlpha),
)
return LayerDrawable(arrayOf(albumArt, gradient))
}
/** Returns [ColorScheme] of media app given its [icon]. */
- fun getColorScheme(
- icon: Drawable,
- tag: String,
- @Style.Type style: Int = Style.TONAL_SPOT,
- ): ColorScheme? {
+ fun getColorScheme(icon: Drawable, tag: String, darkTheme: Boolean): ColorScheme? {
return try {
- ColorScheme(WallpaperColors.fromDrawable(icon), true, style)
+ ColorScheme(WallpaperColors.fromDrawable(icon), darkTheme, Style.CONTENT)
} catch (e: PackageManager.NameNotFoundException) {
Log.w(tag, "Fail to get media app info", e)
null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/GutsViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/GutsViewHolder.kt
index a667c58..fa500ae 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/GutsViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/GutsViewHolder.kt
@@ -22,7 +22,10 @@
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.TextView
+import com.android.systemui.Flags
import com.android.systemui.media.controls.ui.animation.accentPrimaryFromScheme
+import com.android.systemui.media.controls.ui.animation.onPrimaryFromScheme
+import com.android.systemui.media.controls.ui.animation.primaryFromScheme
import com.android.systemui.media.controls.ui.animation.surfaceFromScheme
import com.android.systemui.media.controls.ui.animation.textPrimaryFromScheme
import com.android.systemui.monet.ColorScheme
@@ -35,7 +38,7 @@
* Both [MediaViewHolder] and [RecommendationViewHolder] use the same guts menu layout, so this
* class helps share logic between the two.
*/
-class GutsViewHolder constructor(itemView: View) {
+class GutsViewHolder(itemView: View) {
val gutsText: TextView = itemView.requireViewById(R.id.remove_text)
val cancel: View = itemView.requireViewById(R.id.cancel)
val cancelText: TextView = itemView.requireViewById(R.id.cancel_text)
@@ -44,7 +47,9 @@
val settings: ImageButton = itemView.requireViewById(R.id.settings)
private var isDismissible: Boolean = true
+ // TODO(media_controls_a11y_colors): make private
var colorScheme: ColorScheme? = null
+ private var textColorFixed: Int? = null
/** Marquees the main text of the guts menu. */
fun marquee(start: Boolean, delay: Long, tag: String) {
@@ -67,12 +72,43 @@
/** Sets the right colors on all the guts views based on the given [ColorScheme]. */
fun setColors(scheme: ColorScheme) {
colorScheme = scheme
- setSurfaceColor(surfaceFromScheme(scheme))
- setTextPrimaryColor(textPrimaryFromScheme(scheme))
- setAccentPrimaryColor(accentPrimaryFromScheme(scheme))
+
+ if (Flags.mediaControlsA11yColors()) {
+ textColorFixed?.let { setTextColor(it) }
+ setPrimaryColor(primaryFromScheme(scheme))
+ setOnPrimaryColor(onPrimaryFromScheme(scheme))
+ } else {
+ setSurfaceColor(surfaceFromScheme(scheme))
+ setTextPrimaryColor(textPrimaryFromScheme(scheme))
+ setAccentPrimaryColor(accentPrimaryFromScheme(scheme))
+ }
+ }
+
+ private fun setPrimaryColor(color: Int) {
+ val colorList = ColorStateList.valueOf(color)
+ dismissText.backgroundTintList = colorList
+ cancelText.backgroundTintList = colorList
+ }
+
+ private fun setOnPrimaryColor(color: Int) {
+ dismissText.setTextColor(color)
+ if (!isDismissible) {
+ cancelText.setTextColor(color)
+ }
+ }
+
+ fun setTextColor(color: Int) {
+ textColorFixed = color
+ gutsText.setTextColor(color)
+ settings.imageTintList = ColorStateList.valueOf(color)
+
+ if (isDismissible) {
+ cancelText.setTextColor(color)
+ }
}
/** Sets the surface color on all guts views that use it. */
+ @Deprecated("Remove with media_controls_a11y_colors")
fun setSurfaceColor(surfaceColor: Int) {
dismissText.setTextColor(surfaceColor)
if (!isDismissible) {
@@ -81,6 +117,7 @@
}
/** Sets the primary accent color on all guts views that use it. */
+ @Deprecated("Remove with media_controls_a11y_colors")
fun setAccentPrimaryColor(accentPrimary: Int) {
val accentColorList = ColorStateList.valueOf(accentPrimary)
settings.imageTintList = accentColorList
@@ -89,6 +126,7 @@
}
/** Sets the primary text color on all guts views that use it. */
+ @Deprecated("Remove with media_controls_a11y_colors")
fun setTextPrimaryColor(textPrimary: Int) {
val textColorList = ColorStateList.valueOf(textPrimary)
gutsText.setTextColor(textColorList)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
index 61e4d95..bcda485 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
@@ -418,7 +418,11 @@
)
const val TURBULENCE_NOISE_PLAY_MS_DURATION = 7500L
- const val MEDIA_PLAYER_SCRIM_START_ALPHA = 0.25f
- const val MEDIA_PLAYER_SCRIM_END_ALPHA = 1.0f
+ @Deprecated("Remove with media_controls_a11y_colors flag")
+ const val MEDIA_PLAYER_SCRIM_START_ALPHA_LEGACY = 0.25f
+ @Deprecated("Remove with media_controls_a11y_colors flag")
+ const val MEDIA_PLAYER_SCRIM_END_ALPHA_LEGACY = 1.0f
+ const val MEDIA_PLAYER_SCRIM_START_ALPHA = 0.65f
+ const val MEDIA_PLAYER_SCRIM_END_ALPHA = 0.75f
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacy.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacy.java
index 565b2e4..ea44184 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapterLegacy.java
@@ -185,6 +185,7 @@
mSubTitleText.setTextColor(mController.getColorItemContent());
mVolumeValueText.setTextColor(mController.getColorItemContent());
mIconAreaLayout.setBackground(null);
+ updateIconAreaClickListener(null);
mSeekBar.setProgressTintList(
ColorStateList.valueOf(mController.getColorSeekbarProgress()));
enableFocusPropertyForView(mContainerLayout);
@@ -392,6 +393,11 @@
@Override
public void onMute() {
+ mController.logInteractionMuteDevice(device);
+ }
+
+ @Override
+ public void onUnmute() {
mController.logInteractionUnmuteDevice(device);
}
};
@@ -430,6 +436,9 @@
@Override
public void onMute() {}
+
+ @Override
+ public void onUnmute() {}
};
if (!mController.isVolumeControlEnabledForSession()) {
@@ -622,11 +631,13 @@
private void updateFullItemClickListener(@Nullable View.OnClickListener listener) {
mContainerLayout.setOnClickListener(listener);
- updateIconAreaClickListener(listener);
}
void updateIconAreaClickListener(@Nullable View.OnClickListener listener) {
mIconAreaLayout.setOnClickListener(listener);
+ if (listener == null) {
+ mIconAreaLayout.setClickable(false); // clickable is not removed automatically.
+ }
}
private void initAnimator() {
@@ -677,6 +688,7 @@
mSeekBar.setOnTouchListener((v, event) -> false);
updateIconAreaClickListener((v) -> {
if (volumeControl.getVolume() == 0) {
+ volumeControl.onUnmute();
mSeekBar.setVolume(UNMUTE_DEFAULT_VOLUME);
volumeControl.setVolume(UNMUTE_DEFAULT_VOLUME);
updateUnmutedVolumeIcon(null);
@@ -713,6 +725,7 @@
int getVolume();
void setVolume(int volume);
void onMute();
+ void onUnmute();
}
private abstract class MediaSeekBarChangedListener
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt b/packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
index 24bb16a..3a81102 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
@@ -27,9 +27,7 @@
private set
fun setLoggerForTesting(): UiEventLoggerFake {
- return UiEventLoggerFake().also {
- qsUiEventsLogger = it
- }
+ return UiEventLoggerFake().also { qsUiEventsLogger = it }
}
fun resetLogger() {
@@ -40,32 +38,28 @@
enum class QSEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
@UiEvent(doc = "Tile clicked. It has an instance id and a spec (or packageName)")
QS_ACTION_CLICK(387),
-
- @UiEvent(doc = "Tile secondary button clicked. " +
- "It has an instance id and a spec (or packageName)")
+ @UiEvent(
+ doc =
+ "Tile secondary button clicked. " + "It has an instance id and a spec (or packageName)"
+ )
QS_ACTION_SECONDARY_CLICK(388),
-
@UiEvent(doc = "Tile long clicked. It has an instance id and a spec (or packageName)")
QS_ACTION_LONG_PRESS(389),
-
- @UiEvent(doc = "Quick Settings panel expanded")
- QS_PANEL_EXPANDED(390),
-
- @UiEvent(doc = "Quick Settings panel collapsed")
- QS_PANEL_COLLAPSED(391),
-
- @UiEvent(doc = "Tile visible in Quick Settings panel. The tile may be in a different page. " +
- "It has an instance id and a spec (or packageName)")
+ @UiEvent(doc = "Quick Settings panel expanded") QS_PANEL_EXPANDED(390),
+ @UiEvent(doc = "Quick Settings panel collapsed") QS_PANEL_COLLAPSED(391),
+ @UiEvent(
+ doc =
+ "Tile visible in Quick Settings panel. The tile may be in a different page. " +
+ "It has an instance id and a spec (or packageName)"
+ )
QS_TILE_VISIBLE(392),
-
- @UiEvent(doc = "Quick Quick Settings panel expanded")
- QQS_PANEL_EXPANDED(393),
-
- @UiEvent(doc = "Quick Quick Settings panel collapsed")
- QQS_PANEL_COLLAPSED(394),
-
- @UiEvent(doc = "Tile visible in Quick Quick Settings panel. " +
- "It has an instance id and a spec (or packageName)")
+ @UiEvent(doc = "Quick Quick Settings panel expanded") QQS_PANEL_EXPANDED(393),
+ @UiEvent(doc = "Quick Quick Settings panel collapsed") QQS_PANEL_COLLAPSED(394),
+ @UiEvent(
+ doc =
+ "Tile visible in Quick Quick Settings panel. " +
+ "It has an instance id and a spec (or packageName)"
+ )
QQS_TILE_VISIBLE(395);
override fun getId() = _id
@@ -73,47 +67,32 @@
enum class QSEditEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
- @UiEvent(doc = "Tile removed from current tiles")
- QS_EDIT_REMOVE(210),
-
- @UiEvent(doc = "Tile added to current tiles")
- QS_EDIT_ADD(211),
-
- @UiEvent(doc = "Tile moved")
- QS_EDIT_MOVE(212),
-
- @UiEvent(doc = "QS customizer open")
- QS_EDIT_OPEN(213),
-
- @UiEvent(doc = "QS customizer closed")
- QS_EDIT_CLOSED(214),
-
- @UiEvent(doc = "QS tiles reset")
- QS_EDIT_RESET(215);
+ @UiEvent(doc = "Tile removed from current tiles") QS_EDIT_REMOVE(210),
+ @UiEvent(doc = "Tile added to current tiles") QS_EDIT_ADD(211),
+ @UiEvent(doc = "Tile moved") QS_EDIT_MOVE(212),
+ @UiEvent(doc = "QS customizer open") QS_EDIT_OPEN(213),
+ @UiEvent(doc = "QS customizer closed") QS_EDIT_CLOSED(214),
+ @UiEvent(doc = "QS tiles reset") QS_EDIT_RESET(215),
+ @UiEvent(doc = "QS edit mode resize tile to large") QS_EDIT_RESIZE_LARGE(2122),
+ @UiEvent(doc = "QS edit mode resize tile to small") QS_EDIT_RESIZE_SMALL(2123);
override fun getId() = _id
}
/**
- * Events from the QS DND tile dialog. {@see QSZenModeDialogMetricsLogger}
- * Other names for DND (Do Not Disturb) include "Zen" and "Priority mode".
+ * Events from the QS DND tile dialog. {@see QSZenModeDialogMetricsLogger} Other names for DND (Do
+ * Not Disturb) include "Zen" and "Priority mode".
*/
enum class QSDndEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
- @UiEvent(doc = "User selected an option on the DND dialog")
- QS_DND_CONDITION_SELECT(420),
-
+ @UiEvent(doc = "User selected an option on the DND dialog") QS_DND_CONDITION_SELECT(420),
@UiEvent(doc = "User increased countdown duration of DND from the DND dialog")
QS_DND_TIME_UP(422),
-
@UiEvent(doc = "User decreased countdown duration of DND from the DND dialog")
QS_DND_TIME_DOWN(423),
-
@UiEvent(doc = "User enabled DND from the QS DND dialog to last until manually turned off")
QS_DND_DIALOG_ENABLE_FOREVER(946),
-
@UiEvent(doc = "User enabled DND from the QS DND dialog to last until the next alarm goes off")
QS_DND_DIALOG_ENABLE_UNTIL_ALARM(947),
-
@UiEvent(doc = "User enabled DND from the QS DND dialog to last until countdown is done")
QS_DND_DIALOG_ENABLE_UNTIL_COUNTDOWN(948);
@@ -121,29 +100,17 @@
}
enum class QSUserSwitcherEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
- @UiEvent(doc = "The current user has been switched in the detail panel")
- QS_USER_SWITCH(424),
-
- @UiEvent(doc = "User switcher QS dialog open")
- QS_USER_DETAIL_OPEN(425),
-
- @UiEvent(doc = "User switcher QS dialog closed")
- QS_USER_DETAIL_CLOSE(426),
-
- @UiEvent(doc = "User switcher QS dialog more settings pressed")
- QS_USER_MORE_SETTINGS(427),
-
- @UiEvent(doc = "The user has added a guest in the detail panel")
- QS_USER_GUEST_ADD(754),
-
+ @UiEvent(doc = "The current user has been switched in the detail panel") QS_USER_SWITCH(424),
+ @UiEvent(doc = "User switcher QS dialog open") QS_USER_DETAIL_OPEN(425),
+ @UiEvent(doc = "User switcher QS dialog closed") QS_USER_DETAIL_CLOSE(426),
+ @UiEvent(doc = "User switcher QS dialog more settings pressed") QS_USER_MORE_SETTINGS(427),
+ @UiEvent(doc = "The user has added a guest in the detail panel") QS_USER_GUEST_ADD(754),
@UiEvent(doc = "The user selected 'Start over' after switching to the existing Guest user")
QS_USER_GUEST_WIPE(755),
-
@UiEvent(doc = "The user selected 'Yes, continue' after switching to the existing Guest user")
QS_USER_GUEST_CONTINUE(756),
-
@UiEvent(doc = "The user has pressed 'Remove guest' in the detail panel")
QS_USER_GUEST_REMOVE(757);
override fun getId() = _id
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
index 28540d4..5930a24 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
@@ -53,6 +53,7 @@
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
@@ -287,7 +288,7 @@
private fun CollapsableQuickSettingsSTL() {
val sceneState =
rememberMutableSceneTransitionLayoutState(
- viewModel.expansionState.toIdleSceneKey(),
+ initialScene = remember { viewModel.expansionState.toIdleSceneKey() },
transitions =
transitions {
from(QuickQuickSettings, QuickSettings) {
@@ -305,6 +306,7 @@
sceneState,
viewModel.containerViewModel.editModeViewModel.isEditing,
snapshotFlow { viewModel.expansionState }.map { it.progress },
+ snapshotFlow { viewModel.isQSExpandingOrCollapsing },
)
}
@@ -536,6 +538,10 @@
return qqsVisible.value
}
+ override fun setQSExpandingOrCollapsing(isQSExpandingOrCollapsing: Boolean) {
+ viewModel.isQSExpandingOrCollapsing = isQSExpandingOrCollapsing
+ }
+
private fun setListenerCollections() {
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
@@ -876,6 +882,7 @@
state: MutableSceneTransitionLayoutState,
editMode: Flow<Boolean>,
expansion: Flow<Float>,
+ isQSExpandingOrCollapsing: Flow<Boolean>,
) {
coroutineScope {
val animationScope = this
@@ -887,31 +894,46 @@
currentTransition = null
}
- editMode.combine(expansion, ::Pair).collectLatest { (editMode, progress) ->
+ var lastValidProgress = 0f
+ combine(editMode, expansion, isQSExpandingOrCollapsing, ::Triple).collectLatest {
+ (editMode, progress, isQSExpandingOrCollapsing) ->
if (editMode && state.currentScene != SceneKeys.EditMode) {
state.setTargetScene(SceneKeys.EditMode, animationScope)?.second?.join()
} else if (!editMode && state.currentScene == SceneKeys.EditMode) {
state.setTargetScene(SceneKeys.QuickSettings, animationScope)?.second?.join()
}
- if (!editMode) {
- when (progress) {
- 0f -> snapTo(QuickQuickSettings)
- 1f -> snapTo(QuickSettings)
- else -> {
- val transition = currentTransition
- if (transition != null) {
- transition.progress = progress
- return@collectLatest
- }
- val newTransition =
- ExpansionTransition(progress).also { currentTransition = it }
- state.startTransitionImmediately(
- animationScope = animationScope,
- transition = newTransition,
- )
+ if (!editMode) {
+ if (!isQSExpandingOrCollapsing) {
+ if (progress == 0f) {
+ snapTo(QuickQuickSettings)
+ return@collectLatest
+ }
+
+ if (progress == 1f) {
+ snapTo(QuickSettings)
+ return@collectLatest
}
}
+
+ var progress = progress
+ if (progress >= 0f || progress <= 1f) {
+ lastValidProgress = progress
+ } else {
+ progress = lastValidProgress
+ }
+
+ val transition = currentTransition
+ if (transition != null) {
+ transition.progress = progress
+ return@collectLatest
+ }
+
+ val newTransition = ExpansionTransition(progress).also { currentTransition = it }
+ state.startTransitionImmediately(
+ animationScope = animationScope,
+ transition = newTransition,
+ )
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
index c09d319..b829bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
@@ -35,7 +35,6 @@
import com.android.systemui.classifier.Classifier
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
@@ -43,7 +42,6 @@
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QQS
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QS
import com.android.systemui.media.controls.ui.view.MediaHost
@@ -101,7 +99,7 @@
private val footerActionsController: FooterActionsController,
private val sysuiStatusBarStateController: SysuiStatusBarStateController,
deviceEntryInteractor: DeviceEntryInteractor,
- DisableFlagsInteractor: DisableFlagsInteractor,
+ disableFlagsInteractor: DisableFlagsInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val largeScreenShadeInterpolator: LargeScreenShadeInterpolator,
shadeInteractor: ShadeInteractor,
@@ -119,7 +117,7 @@
@Assisted private val lifecycleScope: LifecycleCoroutineScope,
) : Dumpable, ExclusiveActivatable() {
- val containerViewModel = containerViewModelFactory.create(true)
+ val containerViewModel = containerViewModelFactory.create(supportsBrightnessMirroring = true)
val quickQuickSettingsViewModel = quickQuickSettingsViewModelFactory.create()
private val qqsMediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QQS)
@@ -199,8 +197,8 @@
val isQsEnabled by
hydrator.hydratedStateOf(
traceName = "isQsEnabled",
- initialValue = DisableFlagsInteractor.disableFlags.value.isQuickSettingsEnabled(),
- source = DisableFlagsInteractor.disableFlags.map { it.isQuickSettingsEnabled() },
+ initialValue = disableFlagsInteractor.disableFlags.value.isQuickSettingsEnabled(),
+ source = disableFlagsInteractor.disableFlags.map { it.isQuickSettingsEnabled() },
)
var isInSplitShade by mutableStateOf(false)
@@ -308,6 +306,8 @@
val animateTilesExpansion: Boolean
get() = inFirstPage && !mediaSuddenlyAppearingInLandscape
+ var isQSExpandingOrCollapsing by mutableStateOf(false)
+
private val inFirstPage: Boolean
get() = inFirstPageViewModel.inFirstPage
@@ -490,12 +490,12 @@
qqsMediaHost.apply {
expansion = qqsMediaExpansion
showsOnlyActiveMedia = true
- init(MediaHierarchyManager.LOCATION_QQS)
+ init(LOCATION_QQS)
}
qsMediaHost.apply {
expansion = MediaHostState.EXPANDED
showsOnlyActiveMedia = false
- init(MediaHierarchyManager.LOCATION_QS)
+ init(LOCATION_QS)
}
}
@@ -541,6 +541,7 @@
println("proposedTranslation", proposedTranslation)
println("expansionState", expansionState)
println("forceQS", forceQs)
+ println("isShadeExpandingOrCollapsing", isQSExpandingOrCollapsing)
printSection("Derived values") {
println("headerTranslation", headerTranslation)
println("translationScaleY", translationScaleY)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
index 482cd40..3f279b0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
@@ -16,15 +16,18 @@
package com.android.systemui.qs.panels.domain.interactor
+import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
+import com.android.systemui.qs.QSEditEvent
import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepository
import com.android.systemui.qs.panels.data.repository.LargeTileSpanRepository
import com.android.systemui.qs.panels.shared.model.PanelsLog
import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.pipeline.shared.metricSpec
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
@@ -40,6 +43,7 @@
private val repo: DefaultLargeTilesRepository,
private val currentTilesInteractor: CurrentTilesInteractor,
private val preferencesInteractor: QSPreferencesInteractor,
+ private val uiEventLogger: UiEventLogger,
largeTilesSpanRepo: LargeTileSpanRepository,
@PanelsLog private val logBuffer: LogBuffer,
@Application private val applicationScope: CoroutineScope,
@@ -70,8 +74,18 @@
val isIcon = !largeTilesSpecs.value.contains(spec)
if (toIcon && !isIcon) {
preferencesInteractor.setLargeTilesSpecs(largeTilesSpecs.value - spec)
+ uiEventLogger.log(
+ /* event= */ QSEditEvent.QS_EDIT_RESIZE_SMALL,
+ /* uid= */ 0,
+ /* packageName= */ spec.metricSpec,
+ )
} else if (!toIcon && isIcon) {
preferencesInteractor.setLargeTilesSpecs(largeTilesSpecs.value + spec)
+ uiEventLogger.log(
+ /* event= */ QSEditEvent.QS_EDIT_RESIZE_LARGE,
+ /* uid= */ 0,
+ /* packageName= */ spec.metricSpec,
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
index 302242c..eb6f979 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
@@ -19,8 +19,6 @@
import androidx.compose.runtime.Stable
import com.android.compose.animation.Bounceable
import com.android.systemui.qs.panels.shared.model.SizedTile
-import com.android.systemui.qs.panels.ui.model.GridCell
-import com.android.systemui.qs.panels.ui.model.TileGridCell
import com.android.systemui.qs.panels.ui.viewmodel.BounceableTileViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
@@ -32,18 +30,6 @@
val bounceEnd: Boolean,
)
-fun List<Pair<GridCell, BounceableTileViewModel>>.bounceableInfo(
- index: Int,
- columns: Int,
-): BounceableInfo {
- val cell = this[index].first as TileGridCell
- // Only look for neighbor bounceables if they are on the same row
- val onLastColumn = cell.onLastColumn(cell.column, columns)
- val previousTile = getOrNull(index - 1)?.takeIf { cell.column != 0 }
- val nextTile = getOrNull(index + 1)?.takeIf { !onLastColumn }
- return BounceableInfo(this[index].second, previousTile?.second, nextTile?.second, !onLastColumn)
-}
-
fun List<BounceableTileViewModel>.bounceableInfo(
sizedTile: SizedTile<TileViewModel>,
index: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
index 1a7ef62..a071206 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
@@ -144,12 +144,17 @@
pagerState: PagerState,
editButtonViewModelFactory: EditModeButtonViewModel.Factory,
) {
+ val editButtonViewModel =
+ rememberViewModel(traceName = "PaginatedGridLayout-editButtonViewModel") {
+ editButtonViewModelFactory.create()
+ }
+
// Use requiredHeight so it won't be squished if the view doesn't quite fit. As this is
// expected to be inside a scrollable container, this should not be an issue.
// Also, we construct the layout this way to do the following:
// * PagerDots is centered in the row, taking as much space as it needs.
// * On the start side, we place the BuildNumber, taking as much space as it needs, but
- // constrained by the available space left over after PagerDots
+ // constrained by the available space left over after PagerDots.
// * On the end side, we place the edit mode button, with the same constraints as for
// BuildNumber (but it will usually fit, as it's just a square button).
Row(
@@ -178,7 +183,7 @@
)
Row(Modifier.weight(1f)) {
Spacer(modifier = Modifier.weight(1f))
- EditModeButton(viewModelFactory = editButtonViewModelFactory)
+ EditModeButton(viewModel = editButtonViewModel)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
index ebfe101..ddadb88 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
@@ -22,7 +22,6 @@
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateDpAsState
-import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
@@ -34,7 +33,6 @@
import androidx.compose.foundation.clickable
import androidx.compose.foundation.clipScrollableContainer
import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
@@ -47,28 +45,27 @@
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeightIn
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyGridScope
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.foundation.systemGestureExclusion
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Clear
-import androidx.compose.material.icons.filled.Remove
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalContentColor
-import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
@@ -91,12 +88,9 @@
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.isSpecified
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.layout.layout
import androidx.compose.ui.layout.onGloballyPositioned
@@ -113,24 +107,17 @@
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import androidx.compose.ui.unit.toSize
import androidx.compose.ui.util.fastMap
-import androidx.compose.ui.zIndex
-import com.android.app.tracing.coroutines.launchTraced as launch
-import com.android.compose.animation.bounceable
import com.android.compose.modifiers.height
import com.android.systemui.common.ui.compose.load
import com.android.systemui.qs.panels.shared.model.SizedTile
import com.android.systemui.qs.panels.shared.model.SizedTileImpl
-import com.android.systemui.qs.panels.ui.compose.BounceableInfo
import com.android.systemui.qs.panels.ui.compose.DragAndDropState
import com.android.systemui.qs.panels.ui.compose.DragType
import com.android.systemui.qs.panels.ui.compose.EditTileListState
-import com.android.systemui.qs.panels.ui.compose.bounceableInfo
import com.android.systemui.qs.panels.ui.compose.dragAndDropRemoveZone
import com.android.systemui.qs.panels.ui.compose.dragAndDropTileList
import com.android.systemui.qs.panels.ui.compose.dragAndDropTileSource
@@ -142,13 +129,14 @@
import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.AUTO_SCROLL_SPEED
import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.AvailableTilesGridMinHeight
import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.CurrentTilesGridPadding
-import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.TileBadgeSize
+import com.android.systemui.qs.panels.ui.compose.selection.InteractiveTileContainer
import com.android.systemui.qs.panels.ui.compose.selection.MutableSelectionState
-import com.android.systemui.qs.panels.ui.compose.selection.ResizableTileContainer
import com.android.systemui.qs.panels.ui.compose.selection.ResizingState
import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation
import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation.FinalResizeOperation
import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation.TemporaryResizeOperation
+import com.android.systemui.qs.panels.ui.compose.selection.StaticTileBadge
+import com.android.systemui.qs.panels.ui.compose.selection.TileState
import com.android.systemui.qs.panels.ui.compose.selection.rememberResizingState
import com.android.systemui.qs.panels.ui.compose.selection.rememberSelectionState
import com.android.systemui.qs.panels.ui.compose.selection.selectableTile
@@ -252,13 +240,15 @@
AnimatedContent(
targetState = listState.dragInProgress || selectionState.selected,
label = "QSEditHeader",
+ contentAlignment = Alignment.Center,
+ modifier = Modifier.fillMaxWidth().heightIn(min = 80.dp),
) { showRemoveTarget ->
- EditGridHeader(Modifier.padding(bottom = 26.dp)) {
+ EditGridHeader {
if (showRemoveTarget) {
RemoveTileTarget {
selectionState.selection?.let {
selectionState.unSelect()
- onRemoveTile(it.tileSpec)
+ onRemoveTile(it)
}
}
} else {
@@ -380,7 +370,7 @@
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = tileHorizontalArrangement(),
modifier =
- Modifier.fillMaxHeight()
+ Modifier.wrapContentSize()
.clickable(onClick = onClick)
.border(1.dp, LocalContentColor.current, shape = CircleShape)
.padding(10.dp),
@@ -430,22 +420,15 @@
)
.dragAndDropTileList(gridState, { gridContentOffset }, listState) { spec ->
onSetTiles(currentListState.tileSpecs())
- selectionState.select(spec, manual = false)
+ selectionState.select(spec)
}
.onGloballyPositioned { coordinates ->
gridContentOffset = coordinates.positionInRoot()
}
.testTag(CURRENT_TILES_GRID_TEST_TAG),
) {
- EditTiles(
- cells,
- columns,
- listState,
- selectionState,
- coroutineScope,
- largeTilesSpan,
- onRemoveTile,
- ) { resizingOperation ->
+ EditTiles(cells, listState, selectionState, coroutineScope, largeTilesSpan, onRemoveTile) {
+ resizingOperation ->
when (resizingOperation) {
is TemporaryResizeOperation -> {
currentListState.resizeTile(resizingOperation.spec, resizingOperation.toIcon)
@@ -453,10 +436,6 @@
is FinalResizeOperation -> {
// Commit the new size of the tile
onResize(resizingOperation.spec, resizingOperation.toIcon)
-
- // Mark the selection as automatic in case the tile ends up moving to a
- // different row with its new size.
- selectionState.select(resizingOperation.spec, manual = false)
}
}
}
@@ -536,7 +515,6 @@
* Adds a list of [GridCell] to the lazy grid
*
* @param cells the pairs of [GridCell] to [BounceableTileViewModel]
- * @param columns the number of columns of this tile grid
* @param dragAndDropState the [DragAndDropState] for this grid
* @param selectionState the [MutableSelectionState] for this grid
* @param coroutineScope the [CoroutineScope] to be used for the tiles
@@ -545,7 +523,6 @@
*/
fun LazyGridScope.EditTiles(
cells: List<Pair<GridCell, BounceableTileViewModel>>,
- columns: Int,
dragAndDropState: DragAndDropState,
selectionState: MutableSelectionState,
coroutineScope: CoroutineScope,
@@ -581,7 +558,6 @@
onResize = onResize,
onRemoveTile = onRemoveTile,
coroutineScope = coroutineScope,
- bounceableInfo = cells.bounceableInfo(index, columns),
largeTilesSpan = largeTilesSpan,
modifier = Modifier.animateItem(),
)
@@ -601,83 +577,84 @@
onRemoveTile: (TileSpec) -> Unit,
coroutineScope: CoroutineScope,
largeTilesSpan: Int,
- bounceableInfo: BounceableInfo,
modifier: Modifier = Modifier,
) {
val stateDescription = stringResource(id = R.string.accessibility_qs_edit_position, index + 1)
- var selected by remember { mutableStateOf(false) }
- val showRemovalBadge =
- !selected && cell.tile.availableEditActions.contains(AvailableEditActions.REMOVE)
- val selectionAlpha by
- animateFloatAsState(
- targetValue = if (selected) 1f else 0f,
- label = "QSEditTileSelectionAlpha",
- )
- val selectionColor = MaterialTheme.colorScheme.primary
- val colors = EditModeTileDefaults.editTileColors()
- val currentBounceableInfo by rememberUpdatedState(bounceableInfo)
+ val canShowRemovalBadge = cell.tile.availableEditActions.contains(AvailableEditActions.REMOVE)
+ var tileState by remember { mutableStateOf(TileState.None) }
- LaunchedEffect(selectionState.selection?.tileSpec) {
- selectionState.selection?.let {
- // A delay is introduced on automatic selections such as dragged tiles or reflow caused
- // by resizing. This avoids clipping issues on the border and resizing handle, as well
- // as letting the selection animation play correctly.
- if (!it.manual) {
- delay(250)
+ LaunchedEffect(selectionState.selection, canShowRemovalBadge) {
+ tileState =
+ when {
+ selectionState.selection == cell.tile.tileSpec -> {
+ if (tileState == TileState.None && canShowRemovalBadge) {
+ // The tile decoration is None if a tile is newly composed OR the removal
+ // badge can't be shown.
+ // For newly composed and selected tiles, such as dragged tiles or moved
+ // tiles from resizing, introduce a short delay. This avoids clipping issues
+ // on the border and resizing handle, as well as letting the selection
+ // animation play correctly.
+ delay(250)
+ }
+ TileState.Selected
+ }
+ canShowRemovalBadge -> TileState.Removable
+ else -> TileState.None
}
- }
- selected = selectionState.selection?.tileSpec == cell.tile.tileSpec
}
- val state = rememberResizingState(cell.tile.tileSpec, cell.isIcon)
-
+ val resizingState = rememberResizingState(cell.tile.tileSpec, cell.isIcon)
val progress: () -> Float = {
- if (selected) {
- // If selected, return the manual progress from the drag
- state.progress()
+ if (tileState == TileState.Selected) {
+ resizingState.progress()
} else {
- // Else, return the target progress for the tile format
if (cell.isIcon) 0f else 1f
}
}
- if (!selected) {
+ if (tileState != TileState.Selected) {
// Update the draggable anchor state when the tile's size is not manually toggled
- LaunchedEffect(cell.isIcon) { state.updateCurrentValue(cell.isIcon) }
+ LaunchedEffect(cell.isIcon) { resizingState.updateCurrentValue(cell.isIcon) }
} else {
// If the tile is selected, listen to new target values from the draggable anchor to toggle
// the tile's size
- LaunchedEffect(state.temporaryResizeOperation) { onResize(state.temporaryResizeOperation) }
- LaunchedEffect(state.finalResizeOperation) { onResize(state.finalResizeOperation) }
+ LaunchedEffect(resizingState.temporaryResizeOperation) {
+ onResize(resizingState.temporaryResizeOperation)
+ }
+ LaunchedEffect(resizingState.finalResizeOperation) {
+ onResize(resizingState.finalResizeOperation)
+ }
}
val totalPadding =
with(LocalDensity.current) { (largeTilesSpan - 1) * TileArrangementPadding.roundToPx() }
-
- ResizableTileContainer(
- selected = selected,
- state = state,
- selectionAlpha = { selectionAlpha },
- selectionColor = selectionColor,
+ val colors = EditModeTileDefaults.editTileColors()
+ val toggleSizeLabel = stringResource(R.string.accessibility_qs_edit_toggle_tile_size_action)
+ val clickLabel =
+ when (tileState) {
+ TileState.None -> null
+ TileState.Removable ->
+ stringResource(id = R.string.accessibility_qs_edit_remove_tile_action)
+ TileState.Selected -> toggleSizeLabel
+ }
+ InteractiveTileContainer(
+ tileState = tileState,
+ resizingState = resizingState,
modifier =
- modifier
- .height(TileHeight)
- .fillMaxWidth()
- .onSizeChanged {
- // Grab the size before the bounceable to get the idle width
- val min =
- if (cell.isIcon) it.width else (it.width - totalPadding) / largeTilesSpan
- val max =
- if (cell.isIcon) (it.width * largeTilesSpan) + totalPadding else it.width
- state.updateAnchors(min.toFloat(), max.toFloat())
- }
- .bounceable(
- bounceable = currentBounceableInfo.bounceable,
- previousBounceable = currentBounceableInfo.previousTile,
- nextBounceable = currentBounceableInfo.nextTile,
- orientation = Orientation.Horizontal,
- bounceEnd = currentBounceableInfo.bounceEnd,
- ),
+ modifier.height(TileHeight).fillMaxWidth().onSizeChanged {
+ // Calculate the min/max width from the idle size
+ val min = if (cell.isIcon) it.width else (it.width - totalPadding) / largeTilesSpan
+ val max = if (cell.isIcon) (it.width * largeTilesSpan) + totalPadding else it.width
+ resizingState.updateAnchors(min.toFloat(), max.toFloat())
+ },
+ onClick = {
+ if (tileState == TileState.Removable) {
+ onRemoveTile(cell.tile.tileSpec)
+ } else if (tileState == TileState.Selected) {
+ coroutineScope.launch { resizingState.toggleCurrentValue() }
+ }
+ },
+ onClickLabel = clickLabel,
) {
Box(
modifier
@@ -688,15 +665,13 @@
customActions =
listOf(
// TODO(b/367748260): Add final accessibility actions
- CustomAccessibilityAction("Toggle size") {
+ CustomAccessibilityAction(toggleSizeLabel) {
onResize(FinalResizeOperation(cell.tile.tileSpec, !cell.isIcon))
true
}
)
}
- .selectableTile(cell.tile.tileSpec, selectionState) {
- coroutineScope.launch { currentBounceableInfo.bounceable.animateBounce() }
- }
+ .selectableTile(cell.tile.tileSpec, selectionState)
.dragAndDropTileSource(
SizedTileImpl(cell.tile, cell.width),
dragAndDropState,
@@ -705,16 +680,7 @@
)
.tileBackground(colors.background)
) {
- EditTile(tile = cell.tile, state = state, progress = progress)
- }
-
- if (showRemovalBadge) {
- TileBadge(
- icon = Icons.Default.Remove,
- contentDescription = stringResource(R.string.qs_customize_remove),
- ) {
- onRemoveTile(cell.tile.tileSpec)
- }
+ EditTile(tile = cell.tile, state = resizingState, progress = progress)
}
}
}
@@ -733,7 +699,7 @@
val colors = EditModeTileDefaults.editTileColors()
val onClick = {
onAddTile(cell.tile.tileSpec)
- selectionState.select(cell.tile.tileSpec, manual = false)
+ selectionState.select(cell.tile.tileSpec)
}
// Displays the tile as an icon tile with the label underneath
@@ -742,10 +708,9 @@
verticalArrangement = spacedBy(CommonTileDefaults.TilePadding, Alignment.Top),
modifier = modifier,
) {
- Box {
+ Box(Modifier.fillMaxWidth().height(TileHeight)) {
Box(
- Modifier.fillMaxWidth()
- .height(TileHeight)
+ Modifier.fillMaxSize()
.clickable(onClick = onClick, onClickLabel = onClickActionName)
.semantics(mergeDescendants = true) { this.stateDescription = stateDescription }
.dragAndDropTileSource(
@@ -756,7 +721,6 @@
selectionState.unSelect()
}
.tileBackground(colors.background)
- .tilePadding()
) {
// Icon
SmallTileContent(
@@ -767,7 +731,7 @@
)
}
- TileBadge(
+ StaticTileBadge(
icon = Icons.Default.Add,
contentDescription = onClickActionName,
onClick = onClick,
@@ -787,39 +751,6 @@
}
@Composable
-private fun TileBadge(icon: ImageVector, contentDescription: String?, onClick: () -> Unit) {
- // Use a higher zIndex than the tile to draw over it, and manually create the touch target as
- // we're drawing over neighbor tiles as well.
- val minTouchTargetSize = LocalMinimumInteractiveComponentSize.current
-
- Box(
- Modifier.zIndex(2f)
- .layout { measurable, constraints ->
- val size = minTouchTargetSize.roundToPx()
- val placeable = measurable.measure(Constraints(size))
- layout(placeable.width, placeable.height) {
- val iconRadius = TileBadgeSize.roundToPx() / 2
- val x = constraints.maxWidth - placeable.width / 2 - iconRadius
- val y = 0 - placeable.height / 2 + iconRadius
- placeable.place(x, y)
- }
- }
- .systemGestureExclusion { Rect(Offset.Zero, it.size.toSize()) }
- .pointerInput(Unit) { detectTapGestures { onClick() } }
- ) {
- val secondaryColor = MaterialTheme.colorScheme.secondary
- Icon(
- icon,
- contentDescription = contentDescription,
- modifier =
- Modifier.size(TileBadgeSize).align(Alignment.Center).drawBehind {
- drawCircle(secondaryColor)
- },
- )
- }
-}
-
-@Composable
private fun SpacerGridCell(modifier: Modifier = Modifier) {
// By default, spacers are invisible and exist purely to catch drag movements
Box(modifier.height(TileHeight).fillMaxWidth())
@@ -902,9 +833,8 @@
const val PLACEHOLDER_ALPHA = .3f
const val AUTO_SCROLL_DISTANCE = 100
const val AUTO_SCROLL_SPEED = 2 // 2ms per pixel
- val CurrentTilesGridPadding = 8.dp
+ val CurrentTilesGridPadding = 10.dp
val AvailableTilesGridMinHeight = 200.dp
- val TileBadgeSize = 20.dp
@Composable
fun editTileColors(): TileColors =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
index 47238d1..d73dc87 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
@@ -245,6 +245,7 @@
color = color(),
shape = shape,
modifier = modifier.clip(shape).verticalSquish(squishiness),
+ useModifierBasedImplementation = true,
) {
content(hapticsViewModel?.createStateAwareExpandable(it) ?: it)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt
index 26dfc72..3dfde86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt
@@ -32,23 +32,17 @@
return remember { MutableSelectionState() }
}
-/**
- * Holds the selected [TileSpec] and whether the selection was manual, i.e. caused by a tap from the
- * user.
- */
-data class Selection(val tileSpec: TileSpec, val manual: Boolean)
-
/** Holds the state of the current selection. */
class MutableSelectionState {
- /** The [Selection] if a tile is selected, null if not. */
- var selection by mutableStateOf<Selection?>(null)
+ /** The [TileSpec] of a tile is selected, null if not. */
+ var selection by mutableStateOf<TileSpec?>(null)
private set
val selected: Boolean
get() = selection != null
- fun select(tileSpec: TileSpec, manual: Boolean) {
- selection = Selection(tileSpec, manual)
+ fun select(tileSpec: TileSpec) {
+ selection = tileSpec
}
fun unSelect() {
@@ -68,10 +62,10 @@
return pointerInput(Unit) {
detectTapGestures(
onTap = {
- if (selectionState.selection?.tileSpec == tileSpec) {
+ if (selectionState.selection == tileSpec) {
selectionState.unSelect()
} else {
- selectionState.select(tileSpec, manual = true)
+ selectionState.select(tileSpec)
}
onClick()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt
index 7c47263..699e5f6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt
@@ -16,141 +16,232 @@
package com.android.systemui.qs.panels.ui.compose.selection
-import androidx.compose.animation.core.Spring
-import androidx.compose.animation.core.animateDpAsState
-import androidx.compose.animation.core.animateFloatAsState
-import androidx.compose.animation.core.spring
-import androidx.compose.foundation.Canvas
+import androidx.compose.animation.animateColor
+import androidx.compose.animation.core.Transition
+import androidx.compose.animation.core.animateFloat
+import androidx.compose.animation.core.animateOffset
+import androidx.compose.animation.core.animateSize
+import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.anchoredDraggable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.systemGestureExclusion
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Remove
+import androidx.compose.material3.Icon
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.geometry.center
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.layout
+import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize
import androidx.compose.ui.zIndex
+import com.android.compose.modifiers.size
import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.InactiveCornerRadius
-import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.ResizingDotSize
+import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.BADGE_ANGLE_RAD
+import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.BadgeSize
+import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.BadgeXOffset
+import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.BadgeYOffset
+import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.RESIZING_PILL_ANGLE_RAD
+import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.ResizingPillHeight
+import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.ResizingPillWidth
import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.SelectedBorderWidth
+import com.android.systemui.qs.panels.ui.compose.selection.TileState.None
+import com.android.systemui.qs.panels.ui.compose.selection.TileState.Removable
+import com.android.systemui.qs.panels.ui.compose.selection.TileState.Selected
+import kotlin.math.cos
import kotlin.math.roundToInt
-import kotlinx.coroutines.launch
+import kotlin.math.sin
/**
- * Places a dot to handle resizing drag events. Use this on tiles to resize.
+ * Draws a tile decoration and handles click and drag events for them.
*
- * The dot is placed vertically centered on the right border. The [content] will have a border when
- * selected.
+ * In states:
+ * - [TileState.Removable]: removal icon shown in the top end
+ * - [TileState.Selected]: pill shaped handle shown on the end border, as well as a colored border
+ * around the content.
+ * - [TileState.None]: nothing
*
- * @param selected whether resizing drag events should be handled
- * @param state the [ResizingState] for the tile
- * @param selectionAlpha the animated value for the dot and border alpha
- * @param selectionColor the [Color] of the dot and border
+ * @param tileState the state for the tile decoration
+ * @param resizingState the [ResizingState] for the tile
+ * @param onClick the callback when the tile decoration is clicked
*/
@Composable
-fun ResizableTileContainer(
- selected: Boolean,
- state: ResizingState,
- selectionAlpha: () -> Float,
- selectionColor: Color,
+fun InteractiveTileContainer(
+ tileState: TileState,
+ resizingState: ResizingState,
modifier: Modifier = Modifier,
+ onClick: () -> Unit = {},
+ onClickLabel: String? = null,
content: @Composable BoxScope.() -> Unit = {},
) {
- Box(modifier.resizable(selected, state).selectionBorder(selectionColor, selectionAlpha)) {
- content()
- ResizingHandle(
- enabled = selected,
- state = state,
- modifier =
- // Higher zIndex to make sure the handle is drawn above the content
- Modifier.zIndex(if (selected) 2f else 1f),
- )
- }
-}
+ val transition: Transition<TileState> = updateTransition(tileState)
+ val decorationColor by transition.animateColor()
+ val decorationAngle by transition.animateAngle()
+ val decorationSize by transition.animateSize()
+ val decorationOffset by transition.animateOffset()
+ val decorationAlpha by transition.animateFloat { state -> if (state == None) 0f else 1f }
+ val badgeIconAlpha by transition.animateFloat { state -> if (state == Removable) 1f else 0f }
+ val selectionBorderAlpha by
+ transition.animateFloat { state -> if (state == Selected) 1f else 0f }
-@Composable
-private fun ResizingHandle(enabled: Boolean, state: ResizingState, modifier: Modifier = Modifier) {
- // Manually creating the touch target around the resizing dot to ensure that the next tile
- // does not receive the touch input accidentally.
- val minTouchTargetSize = LocalMinimumInteractiveComponentSize.current
- val scope = rememberCoroutineScope()
Box(
- modifier
- .layout { measurable, constraints ->
- val size = minTouchTargetSize.roundToPx()
- val placeable = measurable.measure(Constraints(size, size, size, size))
- layout(placeable.width, placeable.height) {
- placeable.place(
- x = constraints.maxWidth - placeable.width / 2,
- y = constraints.maxHeight / 2 - placeable.height / 2,
- )
- }
- }
- .systemGestureExclusion { Rect(Offset.Zero, it.size.toSize()) }
- .anchoredDraggable(
- enabled = enabled,
- state = state.anchoredDraggableState,
- orientation = Orientation.Horizontal,
- )
- .clickable(enabled = enabled, interactionSource = null, indication = null) {
- scope.launch { state.toggleCurrentValue() }
- }
+ modifier.resizable(tileState == Selected, resizingState).selectionBorder(
+ MaterialTheme.colorScheme.primary,
+ SelectedBorderWidth,
+ ) {
+ selectionBorderAlpha
+ }
) {
- ResizingDot(enabled = enabled, modifier = Modifier.align(Alignment.Center))
- }
-}
+ content()
-@Composable
-private fun ResizingDot(
- enabled: Boolean,
- modifier: Modifier = Modifier,
- color: Color = MaterialTheme.colorScheme.primary,
-) {
- val alpha by animateFloatAsState(if (enabled) 1f else 0f)
- val radius by
- animateDpAsState(
- if (enabled) ResizingDotSize / 2 else 0.dp,
- animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy),
- )
- Canvas(modifier = modifier.size(ResizingDotSize)) {
- drawCircle(color = color, radius = radius.toPx(), alpha = alpha)
+ MinimumInteractiveSizeComponent(
+ angle = { decorationAngle },
+ offset = { decorationOffset },
+ ) {
+ Box(
+ Modifier.fillMaxSize()
+ .drawBehind {
+ drawRoundRect(
+ color = decorationColor,
+ topLeft = center - decorationSize.center,
+ size = decorationSize,
+ cornerRadius = CornerRadius(size.width / 2),
+ )
+ }
+ .graphicsLayer { this.alpha = decorationAlpha }
+ .anchoredDraggable(
+ enabled = tileState == Selected,
+ state = resizingState.anchoredDraggableState,
+ orientation = Orientation.Horizontal,
+ )
+ .clickable(
+ enabled = tileState != None,
+ interactionSource = null,
+ indication = null,
+ onClickLabel = onClickLabel,
+ onClick = onClick,
+ )
+ ) {
+ Icon(
+ Icons.Default.Remove,
+ contentDescription = null,
+ modifier =
+ Modifier.size(
+ width = { decorationSize.width.roundToInt() },
+ height = { decorationSize.height.roundToInt() },
+ )
+ .align(Alignment.Center)
+ .graphicsLayer { this.alpha = badgeIconAlpha },
+ )
+ }
+ }
}
}
private fun Modifier.selectionBorder(
selectionColor: Color,
+ selectionBorderWidth: Dp,
selectionAlpha: () -> Float = { 0f },
): Modifier {
return drawWithContent {
drawContent()
+
+ // Draw the border on the inside of the tile
+ val borderWidth = selectionBorderWidth.toPx()
drawRoundRect(
SolidColor(selectionColor),
cornerRadius = CornerRadius(InactiveCornerRadius.toPx()),
- style = Stroke(SelectedBorderWidth.toPx()),
+ topLeft = Offset(borderWidth / 2, borderWidth / 2),
+ size = Size(size.width - borderWidth, size.height - borderWidth),
+ style = Stroke(borderWidth),
alpha = selectionAlpha(),
)
}
}
@Composable
+fun StaticTileBadge(icon: ImageVector, contentDescription: String?, onClick: () -> Unit) {
+ val offset = with(LocalDensity.current) { Offset(BadgeXOffset.toPx(), BadgeYOffset.toPx()) }
+ MinimumInteractiveSizeComponent(angle = { BADGE_ANGLE_RAD }, offset = { offset }) {
+ Box(
+ Modifier.fillMaxSize()
+ .clickable(
+ interactionSource = null,
+ indication = null,
+ onClickLabel = contentDescription,
+ onClick = onClick,
+ )
+ ) {
+ val secondaryColor = MaterialTheme.colorScheme.secondary
+ Icon(
+ icon,
+ contentDescription = contentDescription,
+ modifier =
+ Modifier.size(BadgeSize).align(Alignment.Center).drawBehind {
+ drawCircle(secondaryColor)
+ },
+ )
+ }
+ }
+}
+
+@Composable
+private fun MinimumInteractiveSizeComponent(
+ angle: () -> Float,
+ offset: () -> Offset,
+ content: @Composable BoxScope.() -> Unit,
+) {
+ // Use a higher zIndex than the tile to draw over it, and manually create the touch target
+ // as we're drawing over neighbor tiles as well.
+ val minTouchTargetSize = LocalMinimumInteractiveComponentSize.current
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier =
+ Modifier.zIndex(2f)
+ .systemGestureExclusion { Rect(Offset.Zero, it.size.toSize()) }
+ .layout { measurable, constraints ->
+ val size = minTouchTargetSize.roundToPx()
+ val placeable = measurable.measure(Constraints.fixed(size, size))
+ layout(placeable.width, placeable.height) {
+ val radius = constraints.maxHeight / 2f
+ val rotationCenter = Offset(constraints.maxWidth - radius, radius)
+ val position = offsetForAngle(angle(), radius, rotationCenter) + offset()
+ placeable.place(
+ position.x.roundToInt() - placeable.width / 2,
+ position.y.roundToInt() - placeable.height / 2,
+ )
+ }
+ },
+ content = content,
+ )
+}
+
+@Composable
private fun Modifier.resizable(selected: Boolean, state: ResizingState): Modifier {
if (!selected) return zIndex(1f)
@@ -165,7 +256,69 @@
}
}
+enum class TileState {
+ None,
+ Removable,
+ Selected,
+}
+
+@Composable
+private fun Transition<TileState>.animateColor(): State<Color> {
+ return animateColor { state ->
+ when (state) {
+ None -> Color.Transparent
+ Removable -> MaterialTheme.colorScheme.secondary
+ Selected -> MaterialTheme.colorScheme.primary
+ }
+ }
+}
+
+@Composable
+private fun Transition<TileState>.animateAngle(): State<Float> {
+ return animateFloat { state ->
+ if (state == Removable) BADGE_ANGLE_RAD else RESIZING_PILL_ANGLE_RAD
+ }
+}
+
+@Composable
+private fun Transition<TileState>.animateSize(): State<Size> {
+ return animateSize { state ->
+ with(LocalDensity.current) {
+ when (state) {
+ None -> Size.Zero
+ Removable -> Size(BadgeSize.toPx())
+ Selected -> Size(ResizingPillWidth.toPx(), ResizingPillHeight.toPx())
+ }
+ }
+ }
+}
+
+@Composable
+private fun Transition<TileState>.animateOffset(): State<Offset> {
+ return animateOffset { state ->
+ with(LocalDensity.current) {
+ when (state) {
+ None -> Offset.Zero
+ Removable -> Offset(BadgeXOffset.toPx(), BadgeYOffset.toPx())
+ Selected -> Offset(-SelectedBorderWidth.toPx(), 0f)
+ }
+ }
+ }
+}
+
+private fun Size(size: Float) = Size(size, size)
+
+private fun offsetForAngle(angle: Float, radius: Float, center: Offset): Offset {
+ return Offset(x = radius * cos(angle) + center.x, y = radius * sin(angle) + center.y)
+}
+
private object SelectionDefaults {
- val ResizingDotSize = 16.dp
val SelectedBorderWidth = 2.dp
+ val BadgeSize = 24.dp
+ val BadgeXOffset = -4.dp
+ val BadgeYOffset = 4.dp
+ val ResizingPillWidth = 8.dp
+ val ResizingPillHeight = 16.dp
+ const val BADGE_ANGLE_RAD = -.8f
+ const val RESIZING_PILL_ANGLE_RAD = 0f
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt
index f3c06a4..dc02fbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt
@@ -29,17 +29,12 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
-import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.qs.panels.ui.viewmodel.toolbar.EditModeButtonViewModel
import com.android.systemui.qs.ui.compose.borderOnFocus
import com.android.systemui.res.R
@Composable
-fun EditModeButton(
- viewModelFactory: EditModeButtonViewModel.Factory,
- modifier: Modifier = Modifier,
-) {
- val viewModel = rememberViewModel(traceName = "EditModeButton") { viewModelFactory.create() }
+fun EditModeButton(viewModel: EditModeButtonViewModel, modifier: Modifier = Modifier) {
CompositionLocalProvider(
value = LocalContentColor provides MaterialTheme.colorScheme.onSurface
) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
index 59c554c..360266a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
@@ -22,28 +22,32 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.android.systemui.compose.modifiers.sysuiResTag
-import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.qs.footer.ui.compose.IconButton
import com.android.systemui.qs.panels.ui.viewmodel.toolbar.ToolbarViewModel
@Composable
-fun Toolbar(toolbarViewModelFactory: ToolbarViewModel.Factory, modifier: Modifier = Modifier) {
- val viewModel = rememberViewModel("Toolbar") { toolbarViewModelFactory.create() }
-
+fun Toolbar(viewModel: ToolbarViewModel, modifier: Modifier = Modifier) {
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
viewModel.userSwitcherViewModel?.let {
- IconButton(it, Modifier.sysuiResTag("multi_user_switch"))
+ IconButton(
+ it,
+ useModifierBasedExpandable = true,
+ Modifier.sysuiResTag("multi_user_switch"),
+ )
}
- EditModeButton(viewModel.editModeButtonViewModelFactory)
+ EditModeButton(viewModel.editModeButtonViewModel)
IconButton(
viewModel.settingsButtonViewModel,
+ useModifierBasedExpandable = true,
Modifier.sysuiResTag("settings_button_container"),
)
Spacer(modifier = Modifier.weight(1f))
- viewModel.powerButtonViewModel?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
+ viewModel.powerButtonViewModel?.let {
+ IconButton(it, useModifierBasedExpandable = true, Modifier.sysuiResTag("pm_lite"))
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegate.kt
index cbece2c..d266600 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegate.kt
@@ -28,6 +28,7 @@
import com.android.systemui.dialog.ui.composable.AlertDialogContent
import com.android.systemui.qs.panels.domain.interactor.EditTilesResetInteractor
import com.android.systemui.res.R
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
import com.android.systemui.statusbar.phone.ComponentSystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
@@ -40,6 +41,7 @@
@Inject
constructor(
private val sysuiDialogFactory: SystemUIDialogFactory,
+ private val shadeDialogContextInteractor: ShadeDialogContextInteractor,
private val resetInteractor: EditTilesResetInteractor,
) : SystemUIDialog.Delegate {
private var currentDialog: ComponentSystemUIDialog? = null
@@ -53,7 +55,9 @@
currentDialog =
sysuiDialogFactory
- .create { ResetConfirmationDialog(it) }
+ .create(context = shadeDialogContextInteractor.context) {
+ ResetConfirmationDialog(it)
+ }
.also {
it.lifecycle.addObserver(
object : DefaultLifecycleObserver {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt
index fe5eec8..846e068 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt
@@ -16,7 +16,6 @@
package com.android.systemui.qs.panels.ui.viewmodel
-import androidx.compose.runtime.getValue
import com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.development.ui.viewmodel.BuildNumberViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt
index 1a6653c..e54bfa2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt
@@ -45,7 +45,7 @@
class ToolbarViewModel
@AssistedInject
constructor(
- val editModeButtonViewModelFactory: EditModeButtonViewModel.Factory,
+ editModeButtonViewModelFactory: EditModeButtonViewModel.Factory,
private val footerActionsInteractor: FooterActionsInteractor,
private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>,
private val falsingInteractor: FalsingInteractor,
@@ -83,6 +83,8 @@
),
)
+ val editModeButtonViewModel: EditModeButtonViewModel = editModeButtonViewModelFactory.create()
+
override suspend fun onActivated(): Nothing {
coroutineScope {
launch {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index fd5861f..7daac45 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -61,6 +61,8 @@
import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.BluetoothController;
+import dagger.Lazy;
+
import kotlinx.coroutines.Job;
import java.util.List;
@@ -84,7 +86,7 @@
private final Executor mExecutor;
- private final BluetoothDetailsContentViewModel mDetailsContentViewModel;
+ private final Lazy<BluetoothDetailsContentViewModel> mDetailsContentViewModel;
private final FeatureFlags mFeatureFlags;
@Nullable
@@ -104,7 +106,7 @@
QSLogger qsLogger,
BluetoothController bluetoothController,
FeatureFlags featureFlags,
- BluetoothDetailsContentViewModel detailsContentViewModel
+ Lazy<BluetoothDetailsContentViewModel> detailsContentViewModel
) {
super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
@@ -133,7 +135,7 @@
callback.accept(new BluetoothDetailsViewModel(() -> {
longClick(null);
return null;
- }, mDetailsContentViewModel))
+ }, mDetailsContentViewModel.get()))
);
return true;
}
@@ -158,7 +160,7 @@
private void handleClickEvent(@Nullable Expandable expandable) {
if (mFeatureFlags.isEnabled(Flags.BLUETOOTH_QS_TILE_DIALOG)) {
- mDetailsContentViewModel.showDetailsContent(expandable, /* view= */ null);
+ mDetailsContentViewModel.get().showDetailsContent(expandable, /* view= */ null);
} else {
// Secondary clicks are header clicks, just toggle.
toggleBluetooth();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegate.kt
index d0f2580..76ff885 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegate.kt
@@ -16,7 +16,6 @@
package com.android.systemui.qs.tiles.impl.saver.domain
-import android.content.Context
import android.content.DialogInterface
import android.content.SharedPreferences
import android.os.Bundle
@@ -24,7 +23,7 @@
import com.android.internal.R
import com.android.systemui.coroutines.newTracingContext
import com.android.systemui.qs.tiles.impl.saver.domain.interactor.DataSaverTileUserActionInteractor
-import com.android.systemui.shade.ShadeDisplayAware
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.DataSaverController
import kotlin.coroutines.CoroutineContext
@@ -32,13 +31,13 @@
class DataSaverDialogDelegate(
private val sysuiDialogFactory: SystemUIDialog.Factory,
- @ShadeDisplayAware private val context: Context,
+ private val contextInteractor: ShadeDialogContextInteractor,
private val backgroundContext: CoroutineContext,
private val dataSaverController: DataSaverController,
private val sharedPreferences: SharedPreferences,
) : SystemUIDialog.Delegate {
override fun createDialog(): SystemUIDialog {
- return sysuiDialogFactory.create(this, context)
+ return sysuiDialogFactory.create(this, contextInteractor.context)
}
override fun beforeCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
index 05bdf0a..63a9f59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
@@ -22,7 +22,6 @@
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
-import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
@@ -33,6 +32,7 @@
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.settings.UserFileManager
import com.android.systemui.shade.ShadeDisplayAware
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.DataSaverController
import javax.inject.Inject
@@ -44,6 +44,7 @@
@Inject
constructor(
@ShadeDisplayAware private val context: Context,
+ private val contextInteractor: ShadeDialogContextInteractor,
@Main private val coroutineContext: CoroutineContext,
@Background private val backgroundContext: CoroutineContext,
private val dataSaverController: DataSaverController,
@@ -79,18 +80,19 @@
val dialogDelegate =
DataSaverDialogDelegate(
systemUIDialogFactory,
- context,
+ contextInteractor,
backgroundContext,
dataSaverController,
- sharedPreferences
+ sharedPreferences,
)
- val dialog = systemUIDialogFactory.create(dialogDelegate, context)
+ val dialog =
+ systemUIDialogFactory.create(dialogDelegate, contextInteractor.context)
action.expandable
?.dialogTransitionController(
DialogCuj(
InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG
+ INTERACTION_JANK_TAG,
)
)
?.let { controller ->
@@ -101,7 +103,7 @@
is QSTileUserAction.LongClick -> {
qsTileIntentUserActionHandler.handle(
action.expandable,
- Intent(Settings.ACTION_DATA_SAVER_SETTINGS)
+ Intent(Settings.ACTION_DATA_SAVER_SETTINGS),
)
}
is QSTileUserAction.ToggleClick -> {}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt
index 68fd2f5..f9b1a36 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt
@@ -20,6 +20,10 @@
import com.android.systemui.brightness.ui.viewmodel.BrightnessSliderViewModel
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
+import com.android.systemui.media.controls.ui.controller.MediaCarouselController
+import com.android.systemui.media.controls.ui.view.MediaHost
+import com.android.systemui.media.dagger.MediaModule
import com.android.systemui.qs.panels.ui.viewmodel.DetailsViewModel
import com.android.systemui.qs.panels.ui.viewmodel.EditModeViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
@@ -29,6 +33,7 @@
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
+import javax.inject.Named
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.map
@@ -41,10 +46,14 @@
shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
tileGridViewModelFactory: TileGridViewModel.Factory,
@Assisted supportsBrightnessMirroring: Boolean,
+ @Assisted private val expansion: Float?,
val editModeViewModel: EditModeViewModel,
val detailsViewModel: DetailsViewModel,
- val toolbarViewModelFactory: ToolbarViewModel.Factory,
+ toolbarViewModelFactory: ToolbarViewModel.Factory,
shadeModeInteractor: ShadeModeInteractor,
+ mediaCarouselInteractor: MediaCarouselInteractor,
+ val mediaCarouselController: MediaCarouselController,
+ @Named(MediaModule.QS_PANEL) val mediaHost: MediaHost,
) : ExclusiveActivatable() {
private val hydrator = Hydrator("QuickSettingsContainerViewModel.hydrator")
@@ -52,6 +61,8 @@
val brightnessSliderViewModel =
brightnessSliderViewModelFactory.create(supportsBrightnessMirroring)
+ val toolbarViewModel = toolbarViewModelFactory.create()
+
val shadeHeaderViewModel = shadeHeaderViewModelFactory.create()
val tileGridViewModel = tileGridViewModelFactory.create()
@@ -63,10 +74,18 @@
source = shadeModeInteractor.isShadeLayoutWide.map { !it },
)
+ val showMedia: Boolean by
+ hydrator.hydratedStateOf(
+ traceName = "showMedia",
+ source = mediaCarouselInteractor.hasActiveMediaOrRecommendation,
+ )
+
override suspend fun onActivated(): Nothing {
coroutineScope {
+ expansion?.let { mediaHost.expansion = it }
launch { hydrator.activate() }
launch { brightnessSliderViewModel.activate() }
+ launch { toolbarViewModel.activate() }
launch { shadeHeaderViewModel.activate() }
launch { tileGridViewModel.activate() }
awaitCancellation()
@@ -75,6 +94,9 @@
@AssistedFactory
interface Factory {
- fun create(supportsBrightnessMirroring: Boolean): QuickSettingsContainerViewModel
+ fun create(
+ supportsBrightnessMirroring: Boolean,
+ expansion: Float? = null,
+ ): QuickSettingsContainerViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
index 862dba1..e775231 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
@@ -65,8 +65,7 @@
* [userDetailViewAdapterProvider] and show it as launched from [expandable].
*/
fun showDialog(expandable: Expandable) {
- val context = shadeDialogContextInteractor.context
- with(dialogFactory.create(context)) {
+ with(dialogFactory.create(shadeDialogContextInteractor.context)) {
setShowForAllUsers(true)
setCanceledOnTouchOutside(true)
diff --git a/packages/SystemUI/src/com/android/systemui/rotationlock/DeviceStateAutoRotateModule.kt b/packages/SystemUI/src/com/android/systemui/rotationlock/DeviceStateAutoRotateModule.kt
new file mode 100644
index 0000000..6282802
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/rotationlock/DeviceStateAutoRotateModule.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.rotationlock
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.policy.DeviceStateRotationLockSettingController
+import com.android.window.flags.Flags
+import dagger.Module
+import dagger.Provides
+import java.util.Optional
+import javax.inject.Provider
+import javax.inject.Qualifier
+
+@Module
+class DeviceStateAutoRotateModule {
+ /** Qualifier for dependencies to be bound with [DeviceStateAutoRotateModule]. */
+ @Qualifier
+ @MustBeDocumented
+ @Retention(AnnotationRetention.RUNTIME)
+ annotation class BoundsDeviceStateAutoRotateModule
+
+ /**
+ * Provides an instance of [DeviceStateRotationLockSettingController].
+ *
+ * @param controllerProvider The provider for [DeviceStateRotationLockSettingController].
+ * @return An [Optional] containing the [DeviceStateRotationLockSettingController] instance if
+ * the `Flags.enableDeviceStateAutoRotateSettingRefactor()` flag is disabled, or an empty
+ * [Optional] otherwise.
+ */
+ @Provides
+ @BoundsDeviceStateAutoRotateModule
+ @SysUISingleton
+ fun provideDeviceStateRotationLockSettingController(
+ controllerProvider: Provider<DeviceStateRotationLockSettingController>
+ ): Optional<DeviceStateRotationLockSettingController> =
+ if (Flags.enableDeviceStateAutoRotateSettingRefactor()) {
+ Optional.empty()
+ } else {
+ Optional.of(controllerProvider.get())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
index d058372..34b3324 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
@@ -105,15 +105,14 @@
import dalvik.annotation.optimization.NeverCompile;
-import dagger.Lazy;
-
-import kotlin.Unit;
-
import java.io.PrintWriter;
import javax.inject.Inject;
import javax.inject.Provider;
+import dagger.Lazy;
+import kotlin.Unit;
+
/** Handles QuickSettings touch handling, expansion and animation state. */
@SysUISingleton
public class QuickSettingsControllerImpl implements QuickSettingsController, Dumpable {
@@ -2366,8 +2365,16 @@
return;
}
if (startTracing) {
+ if (mQs != null) {
+ mQs.setQSExpandingOrCollapsing(true);
+ }
+
monitor.begin(mPanelView, Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
} else {
+ if (mQs != null) {
+ mQs.setQSExpandingOrCollapsing(false);
+ }
+
if (wasCancelled) {
monitor.cancel(Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt
index 4eb7072..2a14ca4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt
@@ -20,6 +20,7 @@
import android.view.Display
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.display.data.repository.DisplayRepository
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.shade.ShadeOnDefaultDisplayWhenLocked
import com.android.systemui.shade.display.ShadeDisplayPolicy
@@ -45,7 +46,12 @@
val currentPolicy: ShadeDisplayPolicy
}
-/** Keeps the policy and propagates the display id for the shade from it. */
+/**
+ * Keeps the policy and propagates the display id for the shade from it.
+ *
+ * If the display set by the policy is not available (e.g. after the cable is disconnected), this
+ * falls back to the [Display.DEFAULT_DISPLAY].
+ */
@SysUISingleton
class ShadeDisplaysRepositoryImpl
@Inject
@@ -56,6 +62,7 @@
policies: Set<@JvmSuppressWildcards ShadeDisplayPolicy>,
@ShadeOnDefaultDisplayWhenLocked private val shadeOnDefaultDisplayWhenLocked: Boolean,
keyguardRepository: KeyguardRepository,
+ displayRepository: DisplayRepository,
) : ShadeDisplaysRepository {
private val policy: StateFlow<ShadeDisplayPolicy> =
@@ -73,7 +80,12 @@
.distinctUntilChanged()
.stateIn(bgScope, SharingStarted.Eagerly, defaultPolicy)
- private val displayIdFromPolicy: Flow<Int> = policy.flatMapLatest { it.displayId }
+ private val displayIdFromPolicy: Flow<Int> =
+ policy
+ .flatMapLatest { it.displayId }
+ .combine(displayRepository.displayIds) { policyDisplayId, availableIds ->
+ if (policyDisplayId !in availableIds) Display.DEFAULT_DISPLAY else policyDisplayId
+ }
private val keyguardAwareDisplayPolicy: Flow<Int> =
if (!shadeOnDefaultDisplayWhenLocked) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/display/ShadeDisplayPolicy.kt b/packages/SystemUI/src/com/android/systemui/shade/display/ShadeDisplayPolicy.kt
index 677e41a..0002fba 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/display/ShadeDisplayPolicy.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/display/ShadeDisplayPolicy.kt
@@ -57,7 +57,7 @@
@Module(includes = [AllShadeDisplayPoliciesModule::class])
interface ShadeDisplayPolicyModule {
- @Binds fun provideDefaultPolicy(impl: DefaultDisplayShadePolicy): ShadeDisplayPolicy
+ @Binds fun provideDefaultPolicy(impl: StatusBarTouchShadeDisplayPolicy): ShadeDisplayPolicy
@Binds
fun provideShadeExpansionIntent(impl: StatusBarTouchShadeDisplayPolicy): ShadeExpansionIntent
diff --git a/packages/SystemUI/src/com/android/systemui/shade/display/StatusBarTouchShadeDisplayPolicy.kt b/packages/SystemUI/src/com/android/systemui/shade/display/StatusBarTouchShadeDisplayPolicy.kt
index 1f534a5..4ebdb60 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/display/StatusBarTouchShadeDisplayPolicy.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/display/StatusBarTouchShadeDisplayPolicy.kt
@@ -26,7 +26,6 @@
import com.android.systemui.shade.domain.interactor.NotificationShadeElement
import com.android.systemui.shade.domain.interactor.QSShadeElement
import com.android.systemui.shade.domain.interactor.ShadeExpandedStateInteractor.ShadeElement
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import dagger.Lazy
import java.util.concurrent.atomic.AtomicReference
@@ -53,7 +52,6 @@
constructor(
displayRepository: DisplayRepository,
@Background private val backgroundScope: CoroutineScope,
- private val shadeInteractor: Lazy<ShadeInteractor>,
private val qsShadeElement: Lazy<QSShadeElement>,
private val notificationElement: Lazy<NotificationShadeElement>,
) : ShadeDisplayPolicy, ShadeExpansionIntent {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractor.kt
index 186bfcb..a4de1d67 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractor.kt
@@ -17,11 +17,19 @@
package com.android.systemui.shade.domain.interactor
import android.content.Intent
+import android.content.IntentFilter
+import android.os.UserHandle
import android.provider.AlarmClock
+import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shade.data.repository.ShadeHeaderClockRepository
+import com.android.systemui.util.kotlin.emitOnStart
+import com.android.systemui.util.time.SystemClock
+import java.util.Date
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
@SysUISingleton
class ShadeHeaderClockInteractor
@@ -29,7 +37,20 @@
constructor(
private val repository: ShadeHeaderClockRepository,
private val activityStarter: ActivityStarter,
+ private val broadcastDispatcher: BroadcastDispatcher,
+ private val systemClock: SystemClock,
) {
+ /** [Flow] that emits `Unit` whenever the timezone or locale has changed. */
+ val onTimezoneOrLocaleChanged: Flow<Unit> =
+ broadcastFlowForActions(Intent.ACTION_TIMEZONE_CHANGED, Intent.ACTION_LOCALE_CHANGED)
+ .emitOnStart()
+
+ /** [Flow] that emits the current `Date` every minute, or when the system time has changed. */
+ val currentTime: Flow<Date> =
+ broadcastFlowForActions(Intent.ACTION_TIME_TICK, Intent.ACTION_TIME_CHANGED)
+ .emitOnStart()
+ .map { Date(systemClock.currentTimeMillis()) }
+
/** Launch the clock activity. */
fun launchClockActivity() {
val nextAlarmIntent = repository.nextAlarmIntent
@@ -38,8 +59,22 @@
} else {
activityStarter.postStartActivityDismissingKeyguard(
Intent(AlarmClock.ACTION_SHOW_ALARMS),
- 0
+ 0,
)
}
}
+
+ /**
+ * Returns a `Flow` that, when collected, emits `Unit` whenever a broadcast matching one of the
+ * given [actionsToFilter] is received.
+ */
+ private fun broadcastFlowForActions(
+ vararg actionsToFilter: String,
+ user: UserHandle = UserHandle.SYSTEM,
+ ): Flow<Unit> {
+ return broadcastDispatcher.broadcastFlow(
+ filter = IntentFilter().apply { actionsToFilter.forEach(::addAction) },
+ user = user,
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt
index 8c38d2e..20b44d7 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt
@@ -18,16 +18,15 @@
import android.content.Context
import android.content.Intent
-import android.content.IntentFilter
import android.icu.text.DateFormat
import android.icu.text.DisplayContext
-import android.os.UserHandle
import android.provider.Settings
import android.view.ViewGroup
+import androidx.compose.material3.ColorScheme
import androidx.compose.runtime.getValue
+import androidx.compose.ui.graphics.Color
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.battery.BatteryMeterViewController
-import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.plugins.ActivityStarter
@@ -42,7 +41,6 @@
import com.android.systemui.shade.domain.interactor.ShadeHeaderClockInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
-import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
@@ -50,18 +48,18 @@
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
-import java.util.Date
import java.util.Locale
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.mapLatest
/** Models UI state for the shade header. */
+@OptIn(ExperimentalCoroutinesApi::class)
class ShadeHeaderViewModel
@AssistedInject
constructor(
@@ -70,16 +68,15 @@
private val sceneInteractor: SceneInteractor,
private val shadeInteractor: ShadeInteractor,
private val shadeModeInteractor: ShadeModeInteractor,
- private val mobileIconsInteractor: MobileIconsInteractor,
+ mobileIconsInteractor: MobileIconsInteractor,
val mobileIconsViewModel: MobileIconsViewModel,
private val privacyChipInteractor: PrivacyChipInteractor,
private val clockInteractor: ShadeHeaderClockInteractor,
private val tintedIconManagerFactory: TintedIconManager.Factory,
private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
val statusBarIconController: StatusBarIconController,
- val notificationIconContainerStatusBarViewBinder: NotificationIconContainerStatusBarViewBinder,
- private val broadcastDispatcher: BroadcastDispatcher,
) : ExclusiveActivatable() {
+
private val hydrator = Hydrator("ShadeHeaderViewModel.hydrator")
val createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager =
@@ -127,9 +124,16 @@
/** True if there is exactly one mobile connection. */
val isSingleCarrier: StateFlow<Boolean> = mobileIconsInteractor.isSingleCarrier
- private val _mobileSubIds = MutableStateFlow(emptyList<Int>())
/** The list of subscription Ids for current mobile connections. */
- val mobileSubIds: StateFlow<List<Int>> = _mobileSubIds.asStateFlow()
+ val mobileSubIds: List<Int> by
+ hydrator.hydratedStateOf(
+ traceName = "mobileSubIds",
+ initialValue = emptyList(),
+ source =
+ mobileIconsInteractor.filteredSubscriptions.map { list ->
+ list.map { it.subscriptionId }
+ },
+ )
/** The list of PrivacyItems to be displayed by the privacy chip. */
val privacyItems: StateFlow<List<PrivacyItem>> = privacyChipInteractor.privacyItems
@@ -150,45 +154,34 @@
private val longerPattern = context.getString(R.string.abbrev_wday_month_day_no_year_alarm)
private val shorterPattern = context.getString(R.string.abbrev_month_day_no_year)
- private val longerDateFormat = MutableStateFlow(getFormatFromPattern(longerPattern))
- private val shorterDateFormat = MutableStateFlow(getFormatFromPattern(shorterPattern))
- private val _shorterDateText: MutableStateFlow<String> = MutableStateFlow("")
- val shorterDateText: StateFlow<String> = _shorterDateText.asStateFlow()
+ private val longerDateFormat: Flow<DateFormat> =
+ clockInteractor.onTimezoneOrLocaleChanged.mapLatest { getFormatFromPattern(longerPattern) }
+ private val shorterDateFormat: Flow<DateFormat> =
+ clockInteractor.onTimezoneOrLocaleChanged.mapLatest { getFormatFromPattern(shorterPattern) }
- private val _longerDateText: MutableStateFlow<String> = MutableStateFlow("")
- val longerDateText: StateFlow<String> = _longerDateText.asStateFlow()
+ val longerDateText: String by
+ hydrator.hydratedStateOf(
+ traceName = "longerDateText",
+ initialValue = "",
+ source =
+ combine(longerDateFormat, clockInteractor.currentTime) { format, time ->
+ format.format(time)
+ },
+ )
+
+ val shorterDateText: String by
+ hydrator.hydratedStateOf(
+ traceName = "shorterDateText",
+ initialValue = "",
+ source =
+ combine(shorterDateFormat, clockInteractor.currentTime) { format, time ->
+ format.format(time)
+ },
+ )
override suspend fun onActivated(): Nothing {
coroutineScope {
- launch {
- broadcastDispatcher
- .broadcastFlow(
- filter =
- IntentFilter().apply {
- addAction(Intent.ACTION_TIME_TICK)
- addAction(Intent.ACTION_TIME_CHANGED)
- addAction(Intent.ACTION_TIMEZONE_CHANGED)
- addAction(Intent.ACTION_LOCALE_CHANGED)
- },
- user = UserHandle.SYSTEM,
- map = { intent, _ ->
- intent.action == Intent.ACTION_TIMEZONE_CHANGED ||
- intent.action == Intent.ACTION_LOCALE_CHANGED
- },
- )
- .onEach { invalidateFormats -> updateDateTexts(invalidateFormats) }
- .launchIn(this)
- }
-
- launch { updateDateTexts(false) }
-
- launch {
- mobileIconsInteractor.filteredSubscriptions
- .map { list -> list.map { it.subscriptionId } }
- .collect { _mobileSubIds.value = it }
- }
-
launch { hydrator.activate() }
awaitCancellation()
@@ -253,33 +246,34 @@
/** Represents the background highlight of a header icons chip. */
sealed interface HeaderChipHighlight {
- data object None : HeaderChipHighlight
- data object Weak : HeaderChipHighlight
+ fun backgroundColor(colorScheme: ColorScheme): Color
- data object Strong : HeaderChipHighlight
- }
+ fun foregroundColor(colorScheme: ColorScheme): Color
- private fun updateDateTexts(invalidateFormats: Boolean) {
- if (invalidateFormats) {
- longerDateFormat.value = getFormatFromPattern(longerPattern)
- shorterDateFormat.value = getFormatFromPattern(shorterPattern)
+ data object None : HeaderChipHighlight {
+ override fun backgroundColor(colorScheme: ColorScheme): Color = Color.Unspecified
+
+ override fun foregroundColor(colorScheme: ColorScheme): Color = colorScheme.primary
}
- val currentTime = Date()
+ data object Weak : HeaderChipHighlight {
+ override fun backgroundColor(colorScheme: ColorScheme): Color =
+ colorScheme.primary.copy(alpha = 0.1f)
- _longerDateText.value = longerDateFormat.value.format(currentTime)
- _shorterDateText.value = shorterDateFormat.value.format(currentTime)
+ override fun foregroundColor(colorScheme: ColorScheme): Color = colorScheme.primary
+ }
+
+ data object Strong : HeaderChipHighlight {
+ override fun backgroundColor(colorScheme: ColorScheme): Color = colorScheme.secondary
+
+ override fun foregroundColor(colorScheme: ColorScheme): Color = colorScheme.onSecondary
+ }
}
private fun getFormatFromPattern(pattern: String?): DateFormat {
- val l = Locale.getDefault()
- val format = DateFormat.getInstanceForSkeleton(pattern, l)
- // The use of CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE instead of
- // CAPITALIZATION_FOR_STANDALONE is to address
- // https://unicode-org.atlassian.net/browse/ICU-21631
- // TODO(b/229287642): Switch back to CAPITALIZATION_FOR_STANDALONE
- format.setContext(DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE)
+ val format = DateFormat.getInstanceForSkeleton(pattern, Locale.getDefault())
+ format.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE)
return format
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index f30043e..f45971b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -45,7 +45,7 @@
private val crossWindowBlurListeners: CrossWindowBlurListeners,
dumpManager: DumpManager
) : Dumpable {
- val minBlurRadius = blurConfig.minBlurRadiusPx
+ val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius).toFloat();
val maxBlurRadius = if (Flags.notificationShadeBlur()) {
blurConfig.maxBlurRadiusPx
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 97de619..7dc2ae7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -58,7 +58,6 @@
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
-import android.view.accessibility.Flags;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -987,13 +986,7 @@
@Override
public void addQsTile(ComponentName tile) {
- if (Flags.a11yQsShortcut()) {
- addQsTileToFrontOrEnd(tile, false);
- } else {
- synchronized (mLock) {
- mHandler.obtainMessage(MSG_ADD_QS_TILE, tile).sendToTarget();
- }
- }
+ addQsTileToFrontOrEnd(tile, false);
}
/**
@@ -1003,13 +996,11 @@
*/
@Override
public void addQsTileToFrontOrEnd(ComponentName tile, boolean end) {
- if (Flags.a11yQsShortcut()) {
- synchronized (mLock) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = tile;
- args.arg2 = end;
- mHandler.obtainMessage(MSG_ADD_QS_TILE, args).sendToTarget();
- }
+ synchronized (mLock) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = tile;
+ args.arg2 = end;
+ mHandler.obtainMessage(MSG_ADD_QS_TILE, args).sendToTarget();
}
}
@@ -1692,18 +1683,12 @@
}
break;
case MSG_ADD_QS_TILE: {
- if (Flags.a11yQsShortcut()) {
- SomeArgs someArgs = (SomeArgs) msg.obj;
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).addQsTileToFrontOrEnd(
- (ComponentName) someArgs.arg1, (boolean) someArgs.arg2);
- }
- someArgs.recycle();
- } else {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).addQsTile((ComponentName) msg.obj);
- }
+ SomeArgs someArgs = (SomeArgs) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).addQsTileToFrontOrEnd(
+ (ComponentName) someArgs.arg1, (boolean) someArgs.arg2);
}
+ someArgs.recycle();
break;
}
case MSG_REMOVE_QS_TILE:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
index 79a872e..bfd512f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
@@ -607,13 +607,6 @@
context.getString(R.string.group_system_lock_screen),
Arrays.asList(
Pair.create(KeyEvent.KEYCODE_L, KeyEvent.META_META_ON))),
- /* Pull up Notes app for quick memo: Meta + Ctrl + N */
- new ShortcutKeyGroupMultiMappingInfo(
- context.getString(R.string.group_system_quick_memo),
- Arrays.asList(
- Pair.create(
- KeyEvent.KEYCODE_N,
- KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON))),
/* Access system settings: Meta + I */
new ShortcutKeyGroupMultiMappingInfo(
context.getString(R.string.group_system_access_system_settings),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 10f61c6..5b5058f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -798,6 +798,7 @@
initialTouchY = y
initialTouchX = x
}
+
MotionEvent.ACTION_MOVE -> {
val h = y - initialTouchY
// Adjust the touch slop if another gesture may be being performed.
@@ -852,6 +853,7 @@
}
return true
}
+
MotionEvent.ACTION_UP ->
if (
!falsingManager.isUnlockingDisabled &&
@@ -871,6 +873,7 @@
stopDragging()
return false
}
+
MotionEvent.ACTION_CANCEL -> {
stopDragging()
return false
@@ -910,7 +913,7 @@
overshoot *= 1 - RUBBERBAND_FACTOR_STATIC
rubberband -= overshoot
}
- child.actualHeight = (child.collapsedHeight + rubberband).toInt()
+ child.setFinalActualHeight((child.collapsedHeight + rubberband).toInt())
}
@VisibleForTesting
@@ -927,7 +930,7 @@
anim.duration = animationDuration
anim.addUpdateListener { animation: ValueAnimator ->
// don't use reflection, because the `actualHeight` field may be obfuscated
- child.actualHeight = animation.animatedValue as Int
+ child.setFinalActualHeight(animation.animatedValue as Int)
}
anim.addListener(
object : AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
index c1b8d9d..6ebe024 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import static android.app.Flags.notificationsRedesignTemplates;
+
import android.app.Flags;
import android.app.Notification;
import android.graphics.drawable.Drawable;
@@ -427,7 +429,8 @@
@Override
public void apply(View parent, View view, boolean apply, boolean reset) {
- if (reset && parent instanceof ConversationLayout) {
+ if (!notificationsRedesignTemplates()
+ && reset && parent instanceof ConversationLayout) {
ConversationLayout layout = (ConversationLayout) parent;
apply = layout.shouldHideAppName();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index f06565f..32da6ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -24,7 +24,7 @@
import static android.os.Flags.allowPrivateProfile;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_NULL;
-import static android.provider.Settings.Secure.REDACT_OTP_NOTIFICATION_IMMEDIATELY;
+import static android.provider.Settings.Secure.OTP_NOTIFICATION_REDACTION_LOCK_TIME;
import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS;
import static android.provider.Settings.Secure.REDACT_OTP_NOTIFICATION_WHILE_CONNECTED_TO_WIFI;
@@ -124,10 +124,10 @@
private static final Uri REDACT_OTP_ON_WIFI =
Settings.Secure.getUriFor(REDACT_OTP_NOTIFICATION_WHILE_CONNECTED_TO_WIFI);
- private static final Uri REDACT_OTP_IMMEDIATELY =
- Settings.Secure.getUriFor(REDACT_OTP_NOTIFICATION_IMMEDIATELY);
+ private static final Uri OTP_REDACTION_LOCK_TIME =
+ Settings.Secure.getUriFor(OTP_NOTIFICATION_REDACTION_LOCK_TIME);
- private static final long LOCK_TIME_FOR_SENSITIVE_REDACTION_MS =
+ private static final long DEFAULT_LOCK_TIME_FOR_SENSITIVE_REDACTION_MS =
TimeUnit.MINUTES.toMillis(10);
private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy;
private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy;
@@ -316,7 +316,8 @@
protected final AtomicBoolean mConnectedToWifi = new AtomicBoolean(false);
protected final AtomicBoolean mRedactOtpOnWifi = new AtomicBoolean(true);
- protected final AtomicBoolean mRedactOtpImmediately = new AtomicBoolean(false);
+ protected final AtomicLong mOtpRedactionRequiredLockTimeMs =
+ new AtomicLong(DEFAULT_LOCK_TIME_FOR_SENSITIVE_REDACTION_MS);
protected int mCurrentUserId = 0;
@@ -375,7 +376,7 @@
mLockScreenUris.add(SHOW_LOCKSCREEN);
mLockScreenUris.add(SHOW_PRIVATE_LOCKSCREEN);
mLockScreenUris.add(REDACT_OTP_ON_WIFI);
- mLockScreenUris.add(REDACT_OTP_IMMEDIATELY);
+ mLockScreenUris.add(OTP_REDACTION_LOCK_TIME);
dumpManager.registerDumpable(this);
@@ -447,8 +448,8 @@
changed |= updateUserShowPrivateSettings(user.getIdentifier());
} else if (REDACT_OTP_ON_WIFI.equals(uri)) {
changed |= updateRedactOtpOnWifiSetting();
- } else if (REDACT_OTP_IMMEDIATELY.equals(uri)) {
- changed |= updateRedactOtpImmediatelySetting();
+ } else if (OTP_REDACTION_LOCK_TIME.equals(uri)) {
+ changed |= updateOtpLockTimeSetting();
}
}
@@ -487,7 +488,7 @@
mLockscreenSettingsObserver
);
mSecureSettings.registerContentObserverAsync(
- REDACT_OTP_IMMEDIATELY,
+ OTP_REDACTION_LOCK_TIME,
mLockscreenSettingsObserver
);
@@ -638,13 +639,13 @@
}
@WorkerThread
- private boolean updateRedactOtpImmediatelySetting() {
- boolean originalValue = mRedactOtpImmediately.get();
- boolean newValue = mSecureSettings.getIntForUser(
- REDACT_OTP_NOTIFICATION_IMMEDIATELY,
- 0,
- Process.myUserHandle().getIdentifier()) != 0;
- mRedactOtpImmediately.set(newValue);
+ private boolean updateOtpLockTimeSetting() {
+ long originalValue = mOtpRedactionRequiredLockTimeMs.get();
+ long newValue = mSecureSettings.getLongForUser(
+ OTP_NOTIFICATION_REDACTION_LOCK_TIME,
+ DEFAULT_LOCK_TIME_FOR_SENSITIVE_REDACTION_MS,
+ Process.myUserHandle().getIdentifier());
+ mOtpRedactionRequiredLockTimeMs.set(newValue);
return originalValue != newValue;
}
@@ -832,14 +833,9 @@
return false;
}
- long latestTimeForRedaction;
- if (mRedactOtpImmediately.get()) {
- latestTimeForRedaction = mLastLockTime.get();
- } else {
- // If the lock screen was not already locked for LOCK_TIME_FOR_SENSITIVE_REDACTION_MS
- // when this notification arrived, do not redact
- latestTimeForRedaction = mLastLockTime.get() + LOCK_TIME_FOR_SENSITIVE_REDACTION_MS;
- }
+ // If the lock screen was not already locked for at least mOtpRedactionRequiredLockTimeMs
+ // when this notification arrived, do not redact
+ long latestTimeForRedaction = mLastLockTime.get() + mOtpRedactionRequiredLockTimeMs.get();
if (ent.getSbn().getPostTime() < latestTimeForRedaction) {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 6aa2fe2..3db0048 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -110,6 +110,10 @@
private var prevTimestamp: Long = -1
private var prevShadeDirection = 0
private var prevShadeVelocity = 0f
+ // tracks whether app launch transition is in progress. This involves two independent factors
+ // that control blur, shade expansion and app launch animation from outside sysui.
+ // They can complete out of order, this flag will be reset by the animation that finishes later.
+ private var appLaunchTransitionIsInProgress = false
// Only for dumpsys
private var lastAppliedBlur = 0
@@ -158,6 +162,18 @@
if (field == value) {
return
}
+ // Set this to true now, this will be reset when the next shade expansion finishes or
+ // when the app launch finishes, whichever happens later.
+ if (value) {
+ appLaunchTransitionIsInProgress = true
+ } else {
+ // App was launching and now it has finished launching
+ if (shadeExpansion == 0.0f) {
+ // this means shade expansion finished before app launch was done.
+ // reset the flag here
+ appLaunchTransitionIsInProgress = false
+ }
+ }
field = value
scheduleUpdate()
@@ -172,6 +188,12 @@
shadeAnimation.animateTo(0)
shadeAnimation.finishIfRunning()
}
+ @Deprecated(
+ message =
+ "This might get reset to false before shade expansion is fully done, " +
+ "consider using areBlursDisabledForAppLaunch"
+ )
+ get() = field
private var zoomOutCalculatedFromShadeRadius: Float = 0.0f
@@ -183,6 +205,11 @@
scheduleUpdate()
}
+ private val areBlursDisabledForAppLaunch: Boolean
+ get() =
+ blursDisabledForAppLaunch ||
+ (Flags.bouncerUiRevamp() && appLaunchTransitionIsInProgress)
+
/** Force stop blur effect when necessary. */
private var scrimsVisible: Boolean = false
set(value) {
@@ -221,7 +248,7 @@
combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress))
var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius)
- if (blursDisabledForAppLaunch || blursDisabledForUnlock) {
+ if (areBlursDisabledForAppLaunch || blursDisabledForUnlock) {
shadeRadius = 0f
}
@@ -259,7 +286,7 @@
private val shouldBlurBeOpaque: Boolean
get() =
if (Flags.notificationShadeBlur()) false
- else scrimsVisible && !blursDisabledForAppLaunch
+ else scrimsVisible && !areBlursDisabledForAppLaunch
/** Callback that updates the window blur value and is called only once per frame. */
@VisibleForTesting
@@ -442,6 +469,13 @@
val shadeDirection = sign(diff).toInt()
val shadeVelocity =
MathUtils.constrain(VELOCITY_SCALE * diff / deltaTime, MIN_VELOCITY, MAX_VELOCITY)
+ if (expansion == 0.0f && appLaunchTransitionIsInProgress && !blursDisabledForAppLaunch) {
+ // Shade expansion finished but the app launch is already done, then this should mark
+ // the transition as done.
+ Log.d(TAG, "appLaunchTransitionIsInProgress is now false from shade expansion event")
+ appLaunchTransitionIsInProgress = false
+ }
+
updateShadeAnimationBlur(expansion, tracking, shadeVelocity, shadeDirection)
prevShadeDirection = shadeDirection
@@ -553,6 +587,7 @@
it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
it.println("blursDisabledForAppLaunch: $blursDisabledForAppLaunch")
+ it.println("appLaunchTransitionIsInProgress: $appLaunchTransitionIsInProgress")
it.println("qsPanelExpansion: $qsPanelExpansion")
it.println("transitionToFullShadeProgress: $transitionToFullShadeProgress")
it.println("lastAppliedBlur: $lastAppliedBlur")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 85b8bf9..3be7682 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -140,8 +140,8 @@
private fun canHandleMotionEvent(): Boolean {
return wakeUpCoordinator.canShowPulsingHuns &&
- !shadeInteractor.isQsExpanded.value &&
- !bouncerShowing
+ !shadeInteractor.isQsExpanded.value &&
+ !bouncerShowing
}
private fun startExpansion(event: MotionEvent): Boolean {
@@ -194,7 +194,7 @@
override fun onTouchEvent(event: MotionEvent): Boolean {
val finishExpanding =
(event.action == MotionEvent.ACTION_CANCEL || event.action == MotionEvent.ACTION_UP) &&
- isExpanding
+ isExpanding
val isDraggingNotificationOrCanBypass =
mStartingChild?.showingPulsing() == true || bypassController.canBypass()
@@ -218,8 +218,8 @@
velocityTracker!!.computeCurrentVelocity(/* units= */ 1000)
val canExpand =
moveDistance > 0 &&
- velocityTracker!!.getYVelocity() > -1000 &&
- statusBarStateController.state != StatusBarState.SHADE
+ velocityTracker!!.getYVelocity() > -1000 &&
+ statusBarStateController.state != StatusBarState.SHADE
if (!falsingManager.isUnlockingDisabled && !isFalseTouch && canExpand) {
finishExpansion()
} else {
@@ -266,11 +266,11 @@
val child = mStartingChild!!
val newHeight =
Math.min((child.collapsedHeight + expansionHeight).toInt(), child.maxContentHeight)
- child.actualHeight = newHeight
+ child.setFinalActualHeight(newHeight)
} else {
wakeUpCoordinator.setNotificationsVisibleForExpansion(
height >
- lockscreenShadeTransitionController.distanceUntilShowingPulsingNotifications,
+ lockscreenShadeTransitionController.distanceUntilShowingPulsingNotifications,
/*animate= */ true,
/*increaseSpeed= */ true,
)
@@ -301,7 +301,7 @@
anim.duration = animationDuration
anim.addUpdateListener { animation: ValueAnimator ->
// don't use reflection, because the `actualHeight` field may be obfuscated
- child.actualHeight = animation.animatedValue as Int
+ child.setFinalActualHeight(animation.animatedValue as Int)
}
anim.addListener(
object : AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractor.kt
index 2eae3eb..7548f6ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/domain/interactor/CallChipInteractor.kt
@@ -22,9 +22,9 @@
import com.android.systemui.log.core.LogLevel
import com.android.systemui.statusbar.chips.StatusBarChipLogTags.pad
import com.android.systemui.statusbar.chips.StatusBarChipsLog
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.OngoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.domain.interactor.OngoingCallInteractor
-import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -44,25 +44,17 @@
@StatusBarChipsLog private val logger: LogBuffer,
) {
val ongoingCallState: StateFlow<OngoingCallModel> =
- (if (StatusBarChipsModernization.isEnabled)
- ongoingCallInteractor.ongoingCallState
- else
- repository.ongoingCallState)
+ (if (StatusBarChipsModernization.isEnabled) {
+ ongoingCallInteractor.ongoingCallState
+ } else {
+ repository.ongoingCallState
+ })
.onEach {
- logger.log(
- TAG,
- LogLevel.INFO,
- { str1 = it::class.simpleName },
- { "State: $str1" }
- )
+ logger.log(TAG, LogLevel.INFO, { str1 = it::class.simpleName }, { "State: $str1" })
}
- .stateIn(
- scope,
- SharingStarted.Lazily,
- OngoingCallModel.NoCall
- )
+ .stateIn(scope, SharingStarted.Lazily, OngoingCallModel.NoCall)
companion object {
private val TAG = "OngoingCall".pad()
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
index 11e9fd5..994357f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
@@ -161,17 +161,17 @@
)
}
- when (this.promotedContent.time.mode) {
- PromotedNotificationContentModel.When.Mode.BasicTime -> {
+ when (this.promotedContent.time) {
+ is PromotedNotificationContentModel.When.Time -> {
return if (
- this.promotedContent.time.time >=
+ this.promotedContent.time.currentTimeMillis >=
systemClock.currentTimeMillis() + FUTURE_TIME_THRESHOLD_MILLIS
) {
OngoingActivityChipModel.Active.ShortTimeDelta(
this.key,
icon,
colors,
- time = this.promotedContent.time.time,
+ time = this.promotedContent.time.currentTimeMillis,
onClickListenerLegacy,
clickBehavior,
)
@@ -193,23 +193,13 @@
)
}
}
- PromotedNotificationContentModel.When.Mode.CountUp -> {
+ is PromotedNotificationContentModel.When.Chronometer -> {
+ // TODO(b/364653005): Check isCountDown and support CountDown.
return OngoingActivityChipModel.Active.Timer(
this.key,
icon,
colors,
- startTimeMs = this.promotedContent.time.time,
- onClickListenerLegacy,
- clickBehavior,
- )
- }
- PromotedNotificationContentModel.When.Mode.CountDown -> {
- // TODO(b/364653005): Support CountDown.
- return OngoingActivityChipModel.Active.Timer(
- this.key,
- icon,
- colors,
- startTimeMs = this.promotedContent.time.time,
+ startTimeMs = this.promotedContent.time.elapsedRealtimeMillis,
onClickListenerLegacy,
clickBehavior,
)
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 6cb8a53..cf0342b 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
@@ -128,7 +128,10 @@
override val key: String,
override val icon: ChipIcon,
override val colors: ColorsModel,
- /** The time of the event that this chip represents. */
+ /**
+ * The time of the event that this chip represents, relative to
+ * [com.android.systemui.util.time.SystemClock.currentTimeMillis].
+ */
val time: Long,
override val onClickListenerLegacy: View.OnClickListener?,
override val clickBehavior: ClickBehavior,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
index dbcda41..cfc0055 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
@@ -32,12 +32,16 @@
*/
private static int[] getIconsBasedOnFlag() {
if (newStatusBarIcons()) {
+ // TODO(b/396664075):
+ // The new wifi icons only define a range of [0, 3]. Since this array is indexed on
+ // level, we can simulate the range squash by mapping both level 3 to drawn-level 2, and
+ // level 4 to drawn-level 3
return new int[] {
R.drawable.ic_wifi_0,
R.drawable.ic_wifi_1,
R.drawable.ic_wifi_2,
- R.drawable.ic_wifi_3,
- R.drawable.ic_wifi_4
+ R.drawable.ic_wifi_2,
+ R.drawable.ic_wifi_3
};
} else {
return new int[] {
@@ -54,12 +58,13 @@
private static int [] getErrorIconsBasedOnFlag() {
if (newStatusBarIcons()) {
+ // See above note, new wifi icons only have 3 bars, so levels 2 and 3 are the same
return new int[] {
R.drawable.ic_wifi_0_error,
R.drawable.ic_wifi_1_error,
R.drawable.ic_wifi_2_error,
+ R.drawable.ic_wifi_2_error,
R.drawable.ic_wifi_3_error,
- R.drawable.ic_wifi_4_error
};
} else {
return new int[] {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/NewStatusBarIcons.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/NewStatusBarIcons.kt
index e3be953..402881d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/core/NewStatusBarIcons.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/NewStatusBarIcons.kt
@@ -29,10 +29,10 @@
val token: FlagToken
get() = FlagToken(FLAG_NAME, isEnabled)
- /** Is the refactor enabled */
+ /** Is the refactor enabled. Dependency on [StatusBarRootModernization] */
@JvmStatic
inline val isEnabled
- get() = Flags.newStatusBarIcons()
+ get() = Flags.newStatusBarIcons() && StatusBarRootModernization.isEnabled
/**
* 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/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 7b5f5f6..e6dd09b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -97,7 +97,7 @@
private val secureSettings: SecureSettings,
private val userTracker: UserTracker,
private val contentResolver: ContentResolver,
- private val configurationController: ConfigurationController,
+ @ShadeDisplayAware private val configurationController: ConfigurationController,
private val statusBarStateController: StatusBarStateController,
private val deviceProvisionedController: DeviceProvisionedController,
private val bypassController: KeyguardBypassController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt
index 383227d..ab40582 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt
@@ -21,6 +21,7 @@
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.ActivityTransitionAnimator
import com.android.systemui.animation.TransitionAnimator
+import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager
import com.android.systemui.statusbar.notification.headsup.HeadsUpUtil
@@ -157,8 +158,8 @@
private val headsUpNotificationRow: ExpandableNotificationRow?
get() {
- val summaryEntry = notificationEntry.parent?.summary
-
+ val pipelineParent = notificationEntry.parent
+ val summaryEntry = (pipelineParent as? GroupEntry)?.summary
return when {
headsUpManager.isHeadsUpEntry(notificationKey) -> notification
summaryEntry == null -> null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index eb1be67..31bcf2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -24,7 +24,9 @@
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.res.R;
+import com.android.systemui.statusbar.notification.collection.EntryAdapter;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.util.Compile;
@@ -79,7 +81,7 @@
private static final boolean INCLUDE_HASH_CODE_IN_LIST_ENTRY_LOG_KEY = false;
/** Get the notification key, reformatted for logging, for the (optional) entry */
- public static String logKey(ListEntry entry) {
+ public static String logKey(PipelineEntry entry) {
if (entry == null) {
return "null";
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
index 432bac4..2c29e30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
@@ -17,10 +17,10 @@
package com.android.systemui.statusbar.notification
import android.service.notification.StatusBarNotification
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
/** Get the notification key, reformatted for logging, for the (optional) entry */
-val ListEntry?.logKey: String?
+val PipelineEntry?.logKey: String?
get() = this?.let { NotificationUtils.logKey(it) }
/** Get the notification key, reformatted for logging, for the (optional) sbn */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
new file mode 100644
index 0000000..74faf25
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.statusbar.notification
+
+import android.util.Property
+import android.view.View
+import androidx.dynamicanimation.animation.DynamicAnimation
+import androidx.dynamicanimation.animation.FloatPropertyCompat
+import androidx.dynamicanimation.animation.SpringAnimation
+import androidx.dynamicanimation.animation.SpringForce
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.createDefaultSpring
+import com.android.systemui.statusbar.notification.stack.AnimationProperties
+
+/**
+ * A physically animatable property of a view.
+ *
+ * @param tag the view tag to safe this property in
+ * @param property the property to animate.
+ */
+data class PhysicsProperty(val tag: Int, val property: Property<View, Float>) {
+ val offsetProperty =
+ object : FloatPropertyCompat<View>(property.name) {
+ override fun getValue(view: View): Float {
+ return property.get(view)
+ }
+
+ override fun setValue(view: View, offset: Float) {
+ val propertyData = view.getTag(tag) as PropertyData? ?: return
+ propertyData.offset = offset
+ property.set(view, propertyData.finalValue + offset)
+ }
+ }
+
+ fun setFinalValue(view: View, finalValue: Float) {
+ val propertyData = obtainPropertyData(view, this)
+ val previousValue = propertyData.finalValue
+ if (previousValue != finalValue) {
+ propertyData.finalValue = finalValue
+ property.set(view, propertyData.finalValue + propertyData.offset)
+ }
+ }
+}
+
+/** The propertyData associated with each animation running */
+data class PropertyData(
+ var finalValue: Float = 0f,
+ var offset: Float = 0f,
+ var animator: SpringAnimation? = null,
+ var delayRunnable: Runnable? = null,
+)
+
+/**
+ * A utility that can run physics based animations in a simple way. It properly handles overlapping
+ * calls where sometimes a property can be set without animation, while also having instances where
+ * it's supposed to start animations.
+ *
+ * This overall helps making sure that physics based animations complete and don't constantly start
+ * new transitions which can lead to a feeling of lagging behind.
+ *
+ * Overall it is achieved by starting offset animations to an end value as soon as an animation is
+ * requested and updating the end value immediately when no animation is needed. With the offset
+ * always going to 0, this ensures that animations complete within a short time after an animation
+ * has been requested.
+ */
+class PhysicsPropertyAnimator {
+ companion object {
+ @JvmField val TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag
+
+ @JvmField
+ val Y_TRANSLATION: PhysicsProperty =
+ PhysicsProperty(TAG_ANIMATOR_TRANSLATION_Y, View.TRANSLATION_Y)
+
+ // Uses the standard spatial material spring by default
+ @JvmStatic
+ fun createDefaultSpring(): SpringForce {
+ return SpringForce()
+ .setStiffness(380f) // MEDIUM LOW STIFFNESS
+ .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY) // LOW BOUNCINESS
+ }
+
+ @JvmStatic
+ @JvmOverloads
+ /**
+ * Set a property on a view, updating its value, even if it's already animating. The @param
+ * animated can be used to request an animation. If the view isn't animated, this utility
+ * will update the current animation if existent, such that the end value will point
+ * to @param newEndValue or apply it directly if there's no animation.
+ */
+ fun setProperty(
+ view: View,
+ animatableProperty: PhysicsProperty,
+ newEndValue: Float,
+ properties: AnimationProperties? = null,
+ animated: Boolean = false,
+ endListener: DynamicAnimation.OnAnimationEndListener? = null,
+ ) {
+ if (animated) {
+ startAnimation(view, animatableProperty, newEndValue, properties, endListener)
+ } else {
+ animatableProperty.setFinalValue(view, newEndValue)
+ }
+ }
+
+ fun isAnimating(view: View, property: PhysicsProperty): Boolean {
+ val (_, _, animator, _) = obtainPropertyData(view, property)
+ return animator?.isRunning ?: false
+ }
+ }
+}
+
+private fun startAnimation(
+ view: View,
+ animatableProperty: PhysicsProperty,
+ newEndValue: Float,
+ properties: AnimationProperties?,
+ endListener: DynamicAnimation.OnAnimationEndListener?,
+) {
+ val property = animatableProperty.property
+ val propertyData = obtainPropertyData(view, animatableProperty)
+ val previousEndValue = propertyData.finalValue
+ if (previousEndValue == newEndValue) {
+ return
+ }
+ propertyData.finalValue = newEndValue
+ var animator = propertyData.animator
+ if (animator == null) {
+ animator = SpringAnimation(view, animatableProperty.offsetProperty)
+ propertyData.animator = animator
+ animator.setSpring(createDefaultSpring())
+ val listener = properties?.getAnimationEndListener(animatableProperty.property)
+ if (listener != null) {
+ animator.addEndListener(listener)
+ // We always notify things as started even if we have a delay
+ properties.getAnimationStartListener(animatableProperty.property)?.accept(animator)
+ }
+ // remove the tag when the animation is finished
+ animator.addEndListener { _, _, _, _ -> propertyData.animator = null }
+ }
+ // TODO(b/393581344): look at custom spring
+ endListener?.let { animator.addEndListener(it) }
+ val newOffset = previousEndValue - newEndValue + propertyData.offset
+
+ // Immedialely set the new offset that compensates for the immediate end value change
+ propertyData.offset = newOffset
+ property.set(view, newEndValue + newOffset)
+
+ // cancel previous starters still pending
+ view.removeCallbacks(propertyData.delayRunnable)
+ animator.setStartValue(newOffset)
+ val startRunnable = Runnable {
+ animator.animateToFinalPosition(0f)
+ propertyData.delayRunnable = null
+ }
+ if (properties != null && properties.delay > 0 && !animator.isRunning) {
+ propertyData.delayRunnable = startRunnable
+ view.postDelayed(propertyData.delayRunnable, properties.delay)
+ } else {
+ startRunnable.run()
+ }
+}
+
+private fun obtainPropertyData(view: View, animatableProperty: PhysicsProperty): PropertyData {
+ var propertyData = view.getTag(animatableProperty.tag) as PropertyData?
+ if (propertyData == null) {
+ propertyData =
+ PropertyData(finalValue = animatableProperty.property.get(view), offset = 0f, null)
+ view.setTag(animatableProperty.tag, propertyData)
+ }
+ return propertyData
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java
index 0e3f103..35a2828 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/BundleEntry.java
@@ -21,29 +21,62 @@
import static android.app.NotificationChannel.RECS_ID;
import static android.app.NotificationChannel.SOCIAL_MEDIA_ID;
+import android.app.Notification;
+import android.content.Context;
+import android.os.Build;
+
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.systemui.statusbar.notification.icon.IconPack;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import java.util.List;
/**
- * Abstract class to represent notification section bundled by AI.
+ * Class to represent notifications bundled by classification.
*/
public class BundleEntry extends PipelineEntry {
- private final String mKey;
private final BundleEntryAdapter mEntryAdapter;
// TODO (b/389839319): implement the row
private ExpandableNotificationRow mRow;
public BundleEntry(String key) {
- mKey = key;
+ super(key);
mEntryAdapter = new BundleEntryAdapter();
}
+ @Nullable
+ @Override
+ public NotificationEntry getRepresentativeEntry() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public NotifSection getSection() {
+ return null;
+ }
+
+ @Override
+ public int getSectionIndex() {
+ return 0;
+ }
+
+ @Nullable
+ @Override
+ public PipelineEntry getParent() {
+ return null;
+ }
+
+ @Override
+ public boolean wasAttachedInPreviousPass() {
+ return false;
+ }
+
@VisibleForTesting
public BundleEntryAdapter getEntryAdapter() {
return mEntryAdapter;
@@ -79,6 +112,43 @@
public EntryAdapter getGroupRoot() {
return this;
}
+
+ @Override
+ public boolean isClearable() {
+ // TODO(b/394483200): check whether all of the children are clearable, when implemented
+ return true;
+ }
+
+ @Override
+ public int getTargetSdk() {
+ return Build.VERSION_CODES.CUR_DEVELOPMENT;
+ }
+
+ @Override
+ public String getSummarization() {
+ return null;
+ }
+
+ @Override
+ public int getContrastedColor(Context context, boolean isLowPriority, int backgroundColor) {
+ return Notification.COLOR_DEFAULT;
+ }
+
+ @Override
+ public boolean canPeek() {
+ return false;
+ }
+
+ @Override
+ public long getWhen() {
+ return 0;
+ }
+
+ @Override
+ public IconPack getIcons() {
+ // TODO(b/396446620): implement bundle icons
+ return null;
+ }
}
public static final List<BundleEntry> ROOT_BUNDLES = List.of(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/EntryAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/EntryAdapter.java
index 4df81c9..6431cac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/EntryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/EntryAdapter.java
@@ -16,9 +16,12 @@
package com.android.systemui.statusbar.notification.collection;
+import android.content.Context;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.systemui.statusbar.notification.icon.IconPack;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
@@ -59,9 +62,49 @@
EntryAdapter getGroupRoot();
/**
+ * @return whether the row can be removed with the 'Clear All' action
+ */
+ boolean isClearable();
+
+ /**
* Returns whether the entry is attached to the current shade list
*/
default boolean isAttached() {
return getParent() != null;
}
+
+ /**
+ * Returns the target sdk of the package that owns this entry.
+ */
+ int getTargetSdk();
+
+ /**
+ * Returns the summarization for this entry, if there is one
+ */
+ @Nullable String getSummarization();
+
+ /**
+ * Performs any steps needed to set or reset data before an inflation or reinflation.
+ */
+ default void prepareForInflation() {}
+
+ /**
+ * Gets a color that would have sufficient contrast on the given background color.
+ */
+ int getContrastedColor(Context context, boolean isLowPriority, int backgroundColor);
+
+ /**
+ * Whether this entry can peek on screen as a heads up view
+ */
+ boolean canPeek();
+
+ /**
+ * Returns the visible 'time', in milliseconds, of the entry
+ */
+ long getWhen();
+
+ /**
+ * Retrieves the pack of icons associated with this entry
+ */
+ IconPack getIcons();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
index 918843c..8726e83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
@@ -75,6 +75,7 @@
return mChildren;
}
+ // TODO(b/394483200) Change ROOT_ENTRY to PipelineEntry
public static final GroupEntry ROOT_ENTRY = new GroupEntry("<root>", 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
index b5fce41..4a1b956 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
@@ -21,14 +21,14 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
/**
- * Stores the state that [ShadeListBuilder] assigns to this [ListEntry]
+ * Stores the state that [ShadeListBuilder] assigns to this [PipelineEntry]
*/
data class ListAttachState private constructor(
/**
* Null if not attached to the current shade list. If top-level, then the shade list root. If
* part of a group, then that group's GroupEntry.
*/
- var parent: GroupEntry?,
+ var parent: PipelineEntry?,
/**
* The section that this ListEntry was sorted into. If the child of the group, this will be the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index f6a572e..60b75b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -39,14 +39,14 @@
* entry to be in its current state (ie: filter, lifeExtender)
*/
public static String dumpTree(
- List<ListEntry> entries,
+ List<PipelineEntry> entries,
NotificationInteractionTracker interactionTracker,
boolean includeRecordKeeping,
String indent) {
StringBuilder sb = new StringBuilder();
final String childEntryIndent = indent + INDENT;
for (int topEntryIndex = 0; topEntryIndex < entries.size(); topEntryIndex++) {
- ListEntry entry = entries.get(topEntryIndex);
+ PipelineEntry entry = entries.get(topEntryIndex);
dumpEntry(entry,
Integer.toString(topEntryIndex),
indent,
@@ -106,7 +106,7 @@
}
private static void dumpEntry(
- ListEntry entry,
+ PipelineEntry entry,
String index,
String indent,
StringBuilder sb,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index c8e3be4..697d0a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -21,28 +21,18 @@
import androidx.annotation.Nullable;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
-
/**
* Abstract superclass for top-level entries, i.e. things that can appear in the final notification
* list shown to users. In practice, this means either GroupEntries or NotificationEntries.
*/
public abstract class ListEntry extends PipelineEntry {
- private final String mKey;
private final long mCreationTime;
- private final ListAttachState mPreviousAttachState = ListAttachState.create();
- private final ListAttachState mAttachState = ListAttachState.create();
-
protected ListEntry(String key, long creationTime) {
- mKey = key;
+ super(key);
mCreationTime = creationTime;
}
- public String getKey() {
- return mKey;
- }
-
/**
* The SystemClock.uptimeMillis() when this object was created. In general, this means the
* moment when NotificationManager notifies our listener about the existence of this entry.
@@ -64,34 +54,22 @@
*/
public abstract @Nullable NotificationEntry getRepresentativeEntry();
- @Nullable public GroupEntry getParent() {
+ @Nullable public PipelineEntry getParent() {
return mAttachState.getParent();
}
- void setParent(@Nullable GroupEntry parent) {
+ void setParent(@Nullable PipelineEntry parent) {
mAttachState.setParent(parent);
}
- @Nullable public GroupEntry getPreviousParent() {
+ @Nullable public PipelineEntry getPreviousParent() {
return mPreviousAttachState.getParent();
}
- @Nullable public NotifSection getSection() {
- return mAttachState.getSection();
- }
-
public int getSectionIndex() {
return mAttachState.getSection() != null ? mAttachState.getSection().getIndex() : -1;
}
- ListAttachState getAttachState() {
- return mAttachState;
- }
-
- ListAttachState getPreviousAttachState() {
- return mPreviousAttachState;
- }
-
/**
* Stores the current attach state into {@link #getPreviousAttachState()}} and then starts a
* fresh attach state (all entries will be null/default-initialized).
@@ -100,11 +78,4 @@
mPreviousAttachState.clone(mAttachState);
mAttachState.reset();
}
-
- /**
- * True if this entry was attached in the last pass, else false.
- */
- public boolean wasAttachedInPreviousPass() {
- return getPreviousAttachState().getParent() != null;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 90f9525..e5b72d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -78,6 +78,7 @@
import com.android.systemui.statusbar.notification.row.shared.HeadsUpStatusBarModel;
import com.android.systemui.statusbar.notification.row.shared.NotificationContentModel;
import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor;
+import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.statusbar.notification.stack.PriorityBucket;
import com.android.systemui.util.ListenerSet;
@@ -304,11 +305,54 @@
if (isTopLevelEntry() || getParent() == null) {
return null;
}
- if (NotificationEntry.this.getParent().getSummary() != null) {
- return NotificationEntry.this.getParent().getSummary().mEntryAdapter;
+ if (NotificationEntry.this.getParent() instanceof GroupEntry parentGroupEntry) {
+ if (parentGroupEntry.getSummary() != null) {
+ return parentGroupEntry.getSummary().mEntryAdapter;
+ }
}
return null;
}
+
+ @Override
+ public boolean isClearable() {
+ return NotificationEntry.this.isClearable();
+ }
+
+ @Override
+ public int getTargetSdk() {
+ return NotificationEntry.this.targetSdk;
+ }
+
+ @Override
+ public String getSummarization() {
+ return getRanking().getSummarization();
+ }
+
+ @Override
+ public void prepareForInflation() {
+ getSbn().clearPackageContext();
+ }
+
+ @Override
+ public int getContrastedColor(Context context, boolean isLowPriority, int backgroundColor) {
+ return NotificationEntry.this.getContrastedColor(
+ context, isLowPriority, backgroundColor);
+ }
+
+ @Override
+ public boolean canPeek() {
+ return isStickyAndNotDemoted();
+ }
+
+ @Override
+ public long getWhen() {
+ return getSbn().getNotification().getWhen();
+ }
+
+ @Override
+ public IconPack getIcons() {
+ return NotificationEntry.this.getIcons();
+ }
}
public EntryAdapter getEntryAdapter() {
@@ -546,7 +590,7 @@
* Get the children that are actually attached to this notification's row.
*
* TODO: Seems like most callers here should probably be using
- * {@link GroupMembershipManager#getChildren(ListEntry)}
+ * {@link GroupMembershipManager#getChildren(PipelineEntry)}
*/
public @Nullable List<NotificationEntry> getAttachedNotifChildren() {
if (row == null) {
@@ -580,6 +624,7 @@
}
public boolean hasFinishedInitialization() {
+ NotificationBundleUi.assertInLegacyMode();
return initializationTime != -1
&& SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
}
@@ -663,10 +708,12 @@
}
public void resetInitializationTime() {
+ NotificationBundleUi.assertInLegacyMode();
initializationTime = -1;
}
public void setInitializationTime(long time) {
+ NotificationBundleUi.assertInLegacyMode();
if (initializationTime == -1) {
initializationTime = time;
}
@@ -683,9 +730,13 @@
* @return {@code true} if we are a media notification
*/
public boolean isMediaNotification() {
- if (row == null) return false;
+ if (NotificationBundleUi.isEnabled()) {
+ return getSbn().getNotification().isMediaNotification();
+ } else {
+ if (row == null) return false;
- return row.isMediaRow();
+ return row.isMediaRow();
+ }
}
public boolean containsCustomViews() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java
index c5a4791..78652cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineEntry.java
@@ -16,8 +16,74 @@
package com.android.systemui.statusbar.notification.collection;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
+
/**
* Class to represent a notification, group, or bundle in the pipeline.
*/
public abstract class PipelineEntry {
+
+ final String mKey;
+ final ListAttachState mAttachState = ListAttachState.create();
+ final ListAttachState mPreviousAttachState = ListAttachState.create();
+
+ public PipelineEntry(String key) {
+ this.mKey = key;
+ }
+
+ /**
+ * Key of the representative entry.
+ */
+ public @NonNull String getKey() {
+ return mKey;
+ }
+
+ /**
+ * @return The representative NotificationEntry:
+ * for NotificationEntry, return itself
+ * for GroupEntry, return the summary NotificationEntry, or null if it does not exist
+ * for BundleEntry, return null
+ */
+ public abstract @Nullable NotificationEntry getRepresentativeEntry();
+
+ /**
+ * @return NotifSection that ShadeListBuilder assigned to this PipelineEntry.
+ */
+ @Nullable public NotifSection getSection() {
+ return mAttachState.getSection();
+ }
+
+ /**
+ * @return True if this entry was attached in the last pass, else false.
+ */
+ public boolean wasAttachedInPreviousPass() {
+ return getPreviousAttachState().getParent() != null;
+ }
+
+ /**
+ * @return Index of section assigned to this entry.
+ */
+ public abstract int getSectionIndex();
+
+ /**
+ * @return Parent PipelineEntry
+ */
+ public abstract @Nullable PipelineEntry getParent();
+
+ /**
+ * @return Current state that ShadeListBuilder assigned to this PipelineEntry.
+ */
+ final ListAttachState getAttachState() {
+ return mAttachState;
+ }
+
+ /**
+ * @return Previous state that ShadeListBuilder assigned to this PipelineEntry.
+ */
+ final ListAttachState getPreviousAttachState() {
+ return mPreviousAttachState;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 9c1d073..bb84ab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -67,6 +67,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
+import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
import com.android.systemui.util.Assert;
import com.android.systemui.util.NamedListenerSet;
@@ -99,15 +100,15 @@
private final DumpManager mDumpManager;
// used exclusivly by ShadeListBuilder#notifySectionEntriesUpdated
// TODO replace temp with collection pool for readability
- private final ArrayList<ListEntry> mTempSectionMembers = new ArrayList<>();
+ private final ArrayList<PipelineEntry> mTempSectionMembers = new ArrayList<>();
private NotifPipelineFlags mFlags;
private final boolean mAlwaysLogList;
- private List<ListEntry> mNotifList = new ArrayList<>();
- private List<ListEntry> mNewNotifList = new ArrayList<>();
+ private List<PipelineEntry> mNotifList = new ArrayList<>();
+ private List<PipelineEntry> mNewNotifList = new ArrayList<>();
private final SemiStableSort mSemiStableSort = new SemiStableSort();
- private final StableOrder<ListEntry> mStableOrder = this::getStableOrderRank;
+ private final StableOrder<PipelineEntry> mStableOrder = this::getStableOrderRank;
private final PipelineState mPipelineState = new PipelineState();
private final Map<String, GroupEntry> mGroups = new ArrayMap<>();
private Collection<NotificationEntry> mAllEntries = Collections.emptyList();
@@ -132,8 +133,8 @@
mOnBeforeRenderListListeners = new NamedListenerSet<>();
@Nullable private OnRenderListListener mOnRenderListListener;
- private List<ListEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList);
- private List<ListEntry> mReadOnlyNewNotifList = Collections.unmodifiableList(mNewNotifList);
+ private List<PipelineEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList);
+ private List<PipelineEntry> mReadOnlyNewNotifList = Collections.unmodifiableList(mNewNotifList);
private final NotifPipelineChoreographer mChoreographer;
private int mConsecutiveReentrantRebuilds = 0;
@@ -307,7 +308,7 @@
}
}
- List<ListEntry> getShadeList() {
+ List<PipelineEntry> getShadeList() {
Assert.isMainThread();
// NOTE: Accessing this method when the pipeline is running is generally going to provide
// incorrect results, and indicates a poorly behaved component of the pipeline.
@@ -492,7 +493,7 @@
Trace.beginSection("ShadeListBuilder.notifySectionEntriesUpdated");
mTempSectionMembers.clear();
for (NotifSection section : mNotifSections) {
- for (ListEntry entry : mNotifList) {
+ for (PipelineEntry entry : mNotifList) {
if (section == entry.getSection()) {
mTempSectionMembers.add(entry);
}
@@ -513,11 +514,11 @@
*/
private void applyNewNotifList() {
mNotifList.clear();
- List<ListEntry> emptyList = mNotifList;
+ List<PipelineEntry> emptyList = mNotifList;
mNotifList = mNewNotifList;
mNewNotifList = emptyList;
- List<ListEntry> readOnlyNotifList = mReadOnlyNotifList;
+ List<PipelineEntry> readOnlyNotifList = mReadOnlyNotifList;
mReadOnlyNotifList = mReadOnlyNewNotifList;
mReadOnlyNewNotifList = readOnlyNotifList;
}
@@ -537,12 +538,12 @@
}
private void filterNotifs(
- Collection<? extends ListEntry> entries,
- List<ListEntry> out,
+ Collection<? extends PipelineEntry> entries,
+ List<PipelineEntry> out,
List<NotifFilter> filters) {
Trace.beginSection("ShadeListBuilder.filterNotifs");
final long now = mSystemClock.uptimeMillis();
- for (ListEntry entry : entries) {
+ for (PipelineEntry entry : entries) {
if (entry instanceof GroupEntry) {
final GroupEntry groupEntry = (GroupEntry) entry;
@@ -575,11 +576,11 @@
Trace.endSection();
}
- private void groupNotifs(List<ListEntry> entries, List<ListEntry> out) {
+ private void groupNotifs(List<PipelineEntry> entries, List<PipelineEntry> out) {
Trace.beginSection("ShadeListBuilder.groupNotifs");
- for (ListEntry listEntry : entries) {
+ for (PipelineEntry PipelineEntry : entries) {
// since grouping hasn't happened yet, all notifs are NotificationEntries
- NotificationEntry entry = (NotificationEntry) listEntry;
+ NotificationEntry entry = (NotificationEntry) PipelineEntry;
if (entry.getSbn().isGroup()) {
final String topLevelKey = entry.getSbn().getGroupKey();
@@ -630,14 +631,14 @@
Trace.endSection();
}
- private void stabilizeGroupingNotifs(List<ListEntry> topLevelList) {
+ private void stabilizeGroupingNotifs(List<PipelineEntry> topLevelList) {
if (getStabilityManager().isEveryChangeAllowed()) {
return;
}
Trace.beginSection("ShadeListBuilder.stabilizeGroupingNotifs");
for (int i = 0; i < topLevelList.size(); i++) {
- final ListEntry tle = topLevelList.get(i);
+ final PipelineEntry tle = topLevelList.get(i);
if (tle instanceof GroupEntry) {
// maybe put children back into their old group (including moving back to top-level)
GroupEntry groupEntry = (GroupEntry) tle;
@@ -666,13 +667,13 @@
/**
* Returns true if the group change was suppressed, else false
*/
- private boolean maybeSuppressGroupChange(NotificationEntry entry, List<ListEntry> out) {
- final GroupEntry prevParent = entry.getPreviousAttachState().getParent();
+ private boolean maybeSuppressGroupChange(NotificationEntry entry, List<PipelineEntry> out) {
+ final PipelineEntry prevParent = entry.getPreviousAttachState().getParent();
if (prevParent == null) {
// New entries are always allowed.
return false;
}
- final GroupEntry assignedParent = entry.getParent();
+ final PipelineEntry assignedParent = entry.getParent();
if (prevParent == assignedParent) {
// Nothing to change.
return false;
@@ -690,21 +691,22 @@
entry.setParent(prevParent);
if (prevParent == ROOT_ENTRY) {
out.add(entry);
- } else {
- prevParent.addChild(entry);
+ } else if (prevParent instanceof GroupEntry) {
+ ((GroupEntry) prevParent).addChild(entry);
if (!mGroups.containsKey(prevParent.getKey())) {
- mGroups.put(prevParent.getKey(), prevParent);
+ mGroups.put(prevParent.getKey(), (GroupEntry) prevParent);
}
}
+ // TODO(b/394483200): Revisit group stability for BundleEntry
return true;
}
return false;
}
- private void promoteNotifs(List<ListEntry> list) {
+ private void promoteNotifs(List<PipelineEntry> list) {
Trace.beginSection("ShadeListBuilder.promoteNotifs");
for (int i = 0; i < list.size(); i++) {
- final ListEntry tle = list.get(i);
+ final PipelineEntry tle = list.get(i);
if (tle instanceof GroupEntry) {
final GroupEntry group = (GroupEntry) tle;
@@ -724,7 +726,7 @@
Trace.endSection();
}
- private void pruneIncompleteGroups(List<ListEntry> shadeList) {
+ private void pruneIncompleteGroups(List<PipelineEntry> shadeList) {
Trace.beginSection("ShadeListBuilder.pruneIncompleteGroups");
// Any group which lost a child on this run to stability is exempt from being pruned or
// having its summary promoted, regardless of how many children it has
@@ -741,7 +743,7 @@
// Iterate backwards, so that we can remove elements without affecting indices of
// yet-to-be-accessed entries.
for (int i = shadeList.size() - 1; i >= 0; i--) {
- final ListEntry tle = shadeList.get(i);
+ final PipelineEntry tle = shadeList.get(i);
if (tle instanceof GroupEntry) {
final GroupEntry group = (GroupEntry) tle;
@@ -792,7 +794,7 @@
Trace.endSection();
}
- private void pruneGroupAtIndexAndPromoteSummary(List<ListEntry> shadeList,
+ private void pruneGroupAtIndexAndPromoteSummary(List<PipelineEntry> shadeList,
GroupEntry group, int index) {
// Validate that the group has no children
checkArgument(group.getChildren().isEmpty(), "group should have no children");
@@ -800,7 +802,7 @@
NotificationEntry summary = group.getSummary();
summary.setParent(ROOT_ENTRY);
// The list may be sorted; replace the group with the summary, in its place
- ListEntry oldEntry = shadeList.set(index, summary);
+ PipelineEntry oldEntry = shadeList.set(index, summary);
// Validate that the replaced entry was the group entry
checkState(oldEntry == group);
@@ -811,10 +813,10 @@
"SUMMARY with no children @ " + mPipelineState.getStateName());
}
- private void pruneGroupAtIndexAndPromoteAnyChildren(List<ListEntry> shadeList,
+ private void pruneGroupAtIndexAndPromoteAnyChildren(List<PipelineEntry> shadeList,
GroupEntry group, int index) {
// REMOVE the GroupEntry at this index
- ListEntry oldEntry = shadeList.remove(index);
+ PipelineEntry oldEntry = shadeList.remove(index);
// Validate that the replaced entry was the group entry
checkState(oldEntry == group);
@@ -867,14 +869,14 @@
* top level (ungrouped) notifications.
*/
@NonNull
- private Set<String> getGroupsWithChildrenLostToStability(List<ListEntry> shadeList) {
+ private Set<String> getGroupsWithChildrenLostToStability(List<PipelineEntry> shadeList) {
if (getStabilityManager().isEveryChangeAllowed()) {
return Collections.emptySet();
}
ArraySet<String> groupsWithChildrenLostToStability = new ArraySet<>();
for (int i = 0; i < shadeList.size(); i++) {
- final ListEntry tle = shadeList.get(i);
- final GroupEntry suppressedParent =
+ final PipelineEntry tle = shadeList.get(i);
+ final PipelineEntry suppressedParent =
tle.getAttachState().getSuppressedChanges().getParent();
if (suppressedParent != null) {
// This top-level-entry was supposed to be attached to this group,
@@ -891,9 +893,10 @@
*
* These groups will be exempt from appearing without any children.
*/
- private void addGroupsWithChildrenLostToPromotion(List<ListEntry> shadeList, Set<String> out) {
+ private void addGroupsWithChildrenLostToPromotion(List<PipelineEntry> shadeList,
+ Set<String> out) {
for (int i = 0; i < shadeList.size(); i++) {
- final ListEntry tle = shadeList.get(i);
+ final PipelineEntry tle = shadeList.get(i);
if (tle.getAttachState().getPromoter() != null) {
// This top-level-entry was part of a group, but was promoted out of it.
final String groupKey = tle.getRepresentativeEntry().getSbn().getGroupKey();
@@ -909,7 +912,7 @@
* These groups will be exempt from appearing without any children.
*/
private void addGroupsWithChildrenLostToFiltering(Set<String> out) {
- for (ListEntry tle : mAllEntries) {
+ for (PipelineEntry tle : mAllEntries) {
StatusBarNotification sbn = tle.getRepresentativeEntry().getSbn();
if (sbn.isGroup()
&& !sbn.getNotification().isGroupSummary()
@@ -920,14 +923,14 @@
}
/**
- * If a ListEntry was added to the shade list and then later removed (e.g. because it was a
+ * If a PipelineEntry was added to the shade list and then later removed (e.g. because it was a
* group that was broken up), this method will erase any bookkeeping traces of that addition
* and/or check that they were already erased.
*
* Before calling this method, the entry must already have been removed from its parent. If
* it's a group, its summary must be null and its children must be empty.
*/
- private void annulAddition(ListEntry entry, List<ListEntry> shadeList) {
+ private void annulAddition(PipelineEntry entry, List<PipelineEntry> shadeList) {
// This function does very little, but if any of its assumptions are violated (and it has a
// lot of them), it will put the system into an inconsistent state. So we check all of them
@@ -955,9 +958,11 @@
throw new IllegalStateException(
"Cannot nullify group " + ge.getKey() + ": still has children");
}
- } else if (entry instanceof NotificationEntry) {
- if (entry == entry.getParent().getSummary()
- || entry.getParent().getChildren().contains(entry)) {
+ } else if (entry instanceof NotificationEntry
+ && entry.getParent() instanceof GroupEntry) {
+ GroupEntry parentGroupEntry = (GroupEntry) entry.getParent();
+ if (entry == parentGroupEntry.getSummary()
+ || parentGroupEntry.getChildren().contains(entry)) {
throw new IllegalStateException("Cannot nullify addition of child "
+ entry.getKey() + ": it's still attached to its parent.");
}
@@ -972,14 +977,14 @@
* This can happen if the entry is removed from a group that was broken up or if the entry was
* filtered out during any of the filtering steps.
*/
- private void annulAddition(ListEntry entry) {
+ private void annulAddition(PipelineEntry entry) {
entry.getAttachState().detach();
}
private void assignSections() {
Trace.beginSection("ShadeListBuilder.assignSections");
// Assign sections to top-level elements and their children
- for (ListEntry entry : mNotifList) {
+ for (PipelineEntry entry : mNotifList) {
NotifSection section = applySections(entry);
if (entry instanceof GroupEntry) {
GroupEntry parent = (GroupEntry) entry;
@@ -1000,7 +1005,7 @@
private void sortWithSemiStableSort() {
// Sort each group's children
boolean allSorted = true;
- for (ListEntry entry : mNotifList) {
+ for (PipelineEntry entry : mNotifList) {
if (entry instanceof GroupEntry) {
GroupEntry parent = (GroupEntry) entry;
allSorted &= sortGroupChildren(parent.getRawChildren());
@@ -1009,7 +1014,7 @@
// Sort each section within the top level list
mNotifList.sort(mTopLevelComparator);
if (!getStabilityManager().isEveryChangeAllowed()) {
- for (List<ListEntry> subList : getSectionSubLists(mNotifList)) {
+ for (List<PipelineEntry> subList : getSectionSubLists(mNotifList)) {
allSorted &= mSemiStableSort.stabilizeTo(subList, mStableOrder, mNewNotifList);
}
applyNewNotifList();
@@ -1021,7 +1026,7 @@
}
}
- private Iterable<List<ListEntry>> getSectionSubLists(List<ListEntry> entries) {
+ private Iterable<List<PipelineEntry>> getSectionSubLists(List<PipelineEntry> entries) {
return ShadeListBuilderHelper.INSTANCE.getSectionSubLists(entries);
}
@@ -1056,12 +1061,12 @@
/**
* Assign the index of each notification relative to the total order
*/
- private void assignIndexes(List<ListEntry> notifList) {
+ private void assignIndexes(List<PipelineEntry> notifList) {
if (notifList.size() == 0) return;
NotifSection currentSection = requireNonNull(notifList.get(0).getSection());
int sectionMemberIndex = 0;
for (int i = 0; i < notifList.size(); i++) {
- final ListEntry entry = notifList.get(i);
+ final PipelineEntry entry = notifList.get(i);
NotifSection section = requireNonNull(entry.getSection());
if (section.getIndex() != currentSection.getIndex()) {
sectionMemberIndex = 0;
@@ -1098,7 +1103,7 @@
Trace.endSection();
}
- private void logAttachStateChanges(ListEntry entry) {
+ private void logAttachStateChanges(PipelineEntry entry) {
final ListAttachState curr = entry.getAttachState();
final ListAttachState prev = entry.getPreviousAttachState();
@@ -1114,8 +1119,8 @@
mLogger.logParentChanged(mIterationCount, prev.getParent(), curr.getParent());
}
- GroupEntry currSuppressedParent = curr.getSuppressedChanges().getParent();
- GroupEntry prevSuppressedParent = prev.getSuppressedChanges().getParent();
+ PipelineEntry currSuppressedParent = curr.getSuppressedChanges().getParent();
+ PipelineEntry prevSuppressedParent = prev.getSuppressedChanges().getParent();
if (currSuppressedParent != null && (prevSuppressedParent == null
|| !prevSuppressedParent.getKey().equals(currSuppressedParent.getKey()))) {
mLogger.logParentChangeSuppressedStarted(
@@ -1209,7 +1214,7 @@
@Nullable
private NotifComparator getSectionComparator(
- @NonNull ListEntry o1, @NonNull ListEntry o2) {
+ @NonNull PipelineEntry o1, @NonNull PipelineEntry o2) {
final NotifSection section = o1.getSection();
if (section != o2.getSection()) {
throw new RuntimeException("Entry ordering should only be done within sections");
@@ -1220,7 +1225,7 @@
return null;
}
- private final Comparator<ListEntry> mTopLevelComparator = (o1, o2) -> {
+ private final Comparator<PipelineEntry> mTopLevelComparator = (o1, o2) -> {
int cmp = Integer.compare(
o1.getSectionIndex(),
o2.getSectionIndex());
@@ -1263,7 +1268,7 @@
};
@Nullable
- private Integer getStableOrderRank(ListEntry entry) {
+ private Integer getStableOrderRank(PipelineEntry entry) {
if (getStabilityManager().isEntryReorderingAllowed(entry)) {
// let the stability manager constrain or allow reordering
return null;
@@ -1282,7 +1287,13 @@
entry.getAttachState().setExcludingFilter(filter);
if (filter != null) {
// notification is removed from the list, so we reset its initialization time
- entry.resetInitializationTime();
+ if (NotificationBundleUi.isEnabled()) {
+ if (entry.getRow() != null) {
+ entry.getRow().resetInitializationTime();
+ }
+ } else {
+ entry.resetInitializationTime();
+ }
}
return filter != null;
}
@@ -1316,7 +1327,7 @@
return null;
}
- private NotifSection applySections(ListEntry entry) {
+ private NotifSection applySections(PipelineEntry entry) {
final NotifSection newSection = findSection(entry);
final ListAttachState prevAttachState = entry.getPreviousAttachState();
@@ -1339,7 +1350,7 @@
return finalSection;
}
- private void setEntrySection(ListEntry entry, NotifSection finalSection) {
+ private void setEntrySection(PipelineEntry entry, NotifSection finalSection) {
entry.getAttachState().setSection(finalSection);
NotificationEntry representativeEntry = entry.getRepresentativeEntry();
if (representativeEntry != null) {
@@ -1351,7 +1362,7 @@
}
@NonNull
- private NotifSection findSection(ListEntry entry) {
+ private NotifSection findSection(PipelineEntry entry) {
for (int i = 0; i < mNotifSections.size(); i++) {
NotifSection section = mNotifSections.get(i);
if (section.getSectioner().isInSection(entry)) {
@@ -1421,10 +1432,10 @@
mChoreographer.schedule();
}
- private static int countChildren(List<ListEntry> entries) {
+ private static int countChildren(List<PipelineEntry> entries) {
int count = 0;
for (int i = 0; i < entries.size(); i++) {
- final ListEntry entry = entries.get(i);
+ final PipelineEntry entry = entries.get(i);
if (entry instanceof GroupEntry) {
count += ((GroupEntry) entry).getChildren().size();
}
@@ -1432,7 +1443,7 @@
return count;
}
- private void dispatchOnBeforeTransformGroups(List<ListEntry> entries) {
+ private void dispatchOnBeforeTransformGroups(List<PipelineEntry> entries) {
Trace.beginSection("ShadeListBuilder.dispatchOnBeforeTransformGroups");
mOnBeforeTransformGroupsListeners.forEachTraced(listener -> {
listener.onBeforeTransformGroups(entries);
@@ -1440,7 +1451,7 @@
Trace.endSection();
}
- private void dispatchOnBeforeSort(List<ListEntry> entries) {
+ private void dispatchOnBeforeSort(List<PipelineEntry> entries) {
Trace.beginSection("ShadeListBuilder.dispatchOnBeforeSort");
mOnBeforeSortListeners.forEachTraced(listener -> {
listener.onBeforeSort(entries);
@@ -1448,7 +1459,7 @@
Trace.endSection();
}
- private void dispatchOnBeforeFinalizeFilter(List<ListEntry> entries) {
+ private void dispatchOnBeforeFinalizeFilter(List<PipelineEntry> entries) {
Trace.beginSection("ShadeListBuilder.dispatchOnBeforeFinalizeFilter");
mOnBeforeFinalizeFilterListeners.forEachTraced(listener -> {
listener.onBeforeFinalizeFilter(entries);
@@ -1456,7 +1467,7 @@
Trace.endSection();
}
- private void dispatchOnBeforeRenderList(List<ListEntry> entries) {
+ private void dispatchOnBeforeRenderList(List<PipelineEntry> entries) {
Trace.beginSection("ShadeListBuilder.dispatchOnBeforeRenderList");
mOnBeforeRenderListListeners.forEachTraced(listener -> {
listener.onBeforeRenderList(entries);
@@ -1501,13 +1512,13 @@
* @param entries A read-only view into the current notif list. Note that this list is
* backed by the live list and will change in response to new pipeline runs.
*/
- void onRenderList(@NonNull List<ListEntry> entries);
+ void onRenderList(@NonNull List<PipelineEntry> entries);
}
private static final NotifSectioner DEFAULT_SECTIONER = new NotifSectioner("UnknownSection",
NotificationPriorityBucketKt.BUCKET_UNKNOWN) {
@Override
- public boolean isInSection(ListEntry entry) {
+ public boolean isInSection(PipelineEntry entry) {
return true;
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
index 584563b..c942954 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
@@ -19,7 +19,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
/**
- * Stores the suppressed state that [ShadeListBuilder] assigned to this [ListEntry] before the
+ * Stores the suppressed state that [ShadeListBuilder] assigned to this [PipelineEntry] before the
* VisualStabilityManager suppressed group and section changes.
*/
data class SuppressedAttachState private constructor(
@@ -35,7 +35,7 @@
* - Root if suppressing group change to top-level
* - GroupEntry if suppressing group change to a different group
*/
- var parent: GroupEntry?,
+ var parent: PipelineEntry?,
/**
* Whether the ListEntry would have been pruned had its group change not been suppressed.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt
index 244c594..e6d5f41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BundleCoordinator.kt
@@ -20,7 +20,7 @@
import android.app.NotificationChannel.PROMOTIONS_ID
import android.app.NotificationChannel.RECS_ID
import android.app.NotificationChannel.SOCIAL_MEDIA_ID
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
@@ -48,7 +48,7 @@
val newsSectioner =
object : NotifSectioner("News", BUCKET_NEWS) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
return entry.representativeEntry?.channel?.id == NEWS_ID
}
@@ -59,7 +59,7 @@
val socialSectioner =
object : NotifSectioner("Social", BUCKET_SOCIAL) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
return entry.representativeEntry?.channel?.id == SOCIAL_MEDIA_ID
}
@@ -70,7 +70,7 @@
val recsSectioner =
object : NotifSectioner("Recommendations", BUCKET_RECS) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
return entry.representativeEntry?.channel?.id == RECS_ID
}
@@ -81,7 +81,7 @@
val promoSectioner =
object : NotifSectioner("Promotions", BUCKET_PROMO) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
return entry.representativeEntry?.channel?.id == PROMOTIONS_ID
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java
index 9df4bf4..afba85b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java
@@ -25,6 +25,7 @@
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
@@ -96,7 +97,7 @@
private final NotifSectioner mNotifSectioner = new NotifSectioner("ColorizedSectioner",
NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE) {
@Override
- public boolean isInSection(ListEntry entry) {
+ public boolean isInSection(PipelineEntry entry) {
NotificationEntry notificationEntry = entry.getRepresentativeEntry();
if (notificationEntry != null) {
return isRichOngoing(notificationEntry);
@@ -117,7 +118,7 @@
private final NotifComparator mOngoingComparator = new NotifComparator(
"OngoingComparator") {
@Override
- public int compare(@NonNull ListEntry o1, @NonNull ListEntry o2) {
+ public int compare(@NonNull PipelineEntry o1, @NonNull PipelineEntry o2) {
return Integer.compare(
getSortKey(o1.getRepresentativeEntry()),
getSortKey(o2.getRepresentativeEntry())
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index af2c197..248b528 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -16,7 +16,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag
@@ -61,6 +62,7 @@
originalGroup == null -> null
originalGroup == promoted.parent -> null
originalGroup.parent == null -> null
+ originalGroup !is GroupEntry -> summary.key
originalGroup.summary != summary -> null
originalGroup.children.any { it.channel == summary.channel } -> null
else -> summary.key
@@ -74,7 +76,7 @@
override fun shouldPromoteToTopLevel(entry: NotificationEntry): Boolean {
val shouldPromote = entry.channel?.isImportantConversation == true
if (shouldPromote) {
- val summary = entry.parent?.summary
+ val summary = (entry.parent as? GroupEntry)?.summary
if (summary != null && entry.channel == summary.channel) {
promotedEntriesToSummaryOfSameChannel[entry] = summary
}
@@ -85,14 +87,14 @@
val priorityPeopleSectioner =
object : NotifSectioner("Priority People", BUCKET_PRIORITY_PEOPLE) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
return getPeopleType(entry) == TYPE_IMPORTANT_PERSON
}
}
// TODO(b/330193582): Rename to just "People"
val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
if (SortBySectionTimeFlag.isEnabled) {
return highPriorityProvider.isHighPriorityConversation(entry)
|| isConversation(entry)
@@ -111,7 +113,7 @@
val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) {
// Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting.
// All remaining conversations must be silent.
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
SortBySectionTimeFlag.assertInLegacyMode()
return isConversation(entry)
}
@@ -132,17 +134,17 @@
pipeline.addOnBeforeRenderListListener(onBeforeRenderListListener)
}
- private fun isConversation(entry: ListEntry): Boolean =
+ private fun isConversation(entry: PipelineEntry): Boolean =
getPeopleType(entry) != TYPE_NON_PERSON
@PeopleNotificationType
- private fun getPeopleType(entry: ListEntry): Int =
+ private fun getPeopleType(entry: PipelineEntry): Int =
entry.representativeEntry?.let {
peopleNotificationIdentifier.getPeopleNotificationType(it)
} ?: TYPE_NON_PERSON
private val notifComparator: NotifComparator = object : NotifComparator("People") {
- override fun compare(entry1: ListEntry, entry2: ListEntry): Int {
+ override fun compare(entry1: PipelineEntry, entry2: PipelineEntry): Int {
val type1 = getPeopleType(entry1)
val type2 = getPeopleType(entry2)
return type2.compareTo(type1)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
index 034a4fd..e4ec76c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -43,12 +43,12 @@
d.dump("notifLiveDataStoreImpl", notifLiveDataStoreImpl)
}
- private fun onAfterRenderList(entries: List<ListEntry>) {
+ private fun onAfterRenderList(entries: List<PipelineEntry>) {
val flatEntryList = flattenedEntryList(entries)
notifLiveDataStoreImpl.setActiveNotifList(flatEntryList)
}
- private fun flattenedEntryList(entries: List<ListEntry>) =
+ private fun flattenedEntryList(entries: List<PipelineEntry>) =
mutableListOf<NotificationEntry>().also { list ->
entries.forEach { entry ->
when (entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
index 0a9dddc..6bed0cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProviderImpl
@@ -37,7 +37,7 @@
pipeline.addOnBeforeRenderListListener(::onBeforeRenderListListener)
}
- private fun onBeforeRenderListListener(entries: List<ListEntry>) {
+ private fun onBeforeRenderListListener(entries: List<PipelineEntry>) {
val isLocked = !keyguardStateController.isUnlocked
val nonDismissableEntryKeys = mutableSetOf<String>()
markNonDismissibleEntries(nonDismissableEntryKeys, entries, isLocked)
@@ -54,7 +54,7 @@
*/
private fun markNonDismissibleEntries(
markedKeys: MutableSet<String>,
- entries: List<ListEntry>,
+ entries: List<PipelineEntry>,
isLocked: Boolean
): Boolean {
var anyNonDismissableEntries = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
index 02bf3b3..2f0701f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
@@ -18,7 +18,7 @@
import android.util.ArrayMap
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.render.NotifGroupController
@@ -34,7 +34,7 @@
pipeline.addOnAfterRenderGroupListener(::onAfterRenderGroup)
}
- private fun onBeforeFinalizeFilter(entries: List<ListEntry>) {
+ private fun onBeforeFinalizeFilter(entries: List<PipelineEntry>) {
// save untruncated child counts to our internal map
untruncatedChildCounts.clear()
entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
index f253100..d0411b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
@@ -18,7 +18,7 @@
import android.util.ArrayMap
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
@@ -52,7 +52,7 @@
pipeline.addPreRenderInvalidator(invalidator)
}
- private fun onBeforeFinalizeFilterListener(entries: List<ListEntry>) {
+ private fun onBeforeFinalizeFilterListener(entries: List<PipelineEntry>) {
cancelListInvalidation()
notificationGroupTimes.clear()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
index b200136..9045aac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
@@ -18,7 +18,7 @@
import android.util.ArraySet
import com.android.systemui.Dumpable
import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -113,7 +113,7 @@
}
}
- private fun isCurrentlyShowingGuts(entry: ListEntry) =
+ private fun isCurrentlyShowingGuts(entry: PipelineEntry) =
notifsWithOpenGuts.contains(entry.key)
private fun closeGutsAndEndLifetimeExtension(entry: NotificationEntry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index eb5a370..611e0ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -27,7 +27,7 @@
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifCollection
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -103,7 +103,7 @@
mNotifPipeline = pipeline
mHeadsUpManager.addListener(mOnHeadsUpChangedListener)
pipeline.addCollectionListener(mNotifCollectionListener)
- pipeline.addOnBeforeTransformGroupsListener(::onBeforeTransformGroups)
+ pipeline.addOnBeforeTransformGroupsListener { onBeforeTransformGroups() }
pipeline.addOnBeforeFinalizeFilterListener(::onBeforeFinalizeFilter)
pipeline.addPromoter(mNotifPromoter)
pipeline.addNotificationLifetimeExtender(mLifetimeExtender)
@@ -170,7 +170,7 @@
* Once the pipeline starts running, we can look through posted entries and quickly process any
* that don't have groups, and thus will never gave a group heads up edge case.
*/
- fun onBeforeTransformGroups(list: List<ListEntry>) {
+ fun onBeforeTransformGroups() {
mNow = mSystemClock.currentTimeMillis()
if (mPostedEntries.isEmpty()) {
return
@@ -191,7 +191,7 @@
* we know that stability and [NotifPromoter]s have been applied, so we can use the location of
* notifications in this list to determine what kind of group heads up behavior should happen.
*/
- fun onBeforeFinalizeFilter(list: List<ListEntry>) =
+ fun onBeforeFinalizeFilter(list: List<PipelineEntry>) =
mHeadsUpManager.modifyHuns { hunMutator ->
// Nothing to do if there are no other adds/updates
if (mPostedEntries.isEmpty()) {
@@ -410,7 +410,7 @@
)
.firstOrNull()
- private fun getGroupLocationsByKey(list: List<ListEntry>): Map<String, GroupLocation> =
+ private fun getGroupLocationsByKey(list: List<PipelineEntry>): Map<String, GroupLocation> =
mutableMapOf<String, GroupLocation>().also { map ->
list.forEach { topLevelEntry ->
when (topLevelEntry) {
@@ -833,13 +833,13 @@
val sectioner =
object : NotifSectioner("HeadsUp", BUCKET_HEADS_UP) {
- override fun isInSection(entry: ListEntry): Boolean =
+ override fun isInSection(entry: PipelineEntry): Boolean =
// TODO: This check won't notice if a child of the group is going to HUN...
isGoingToShowHunNoRetract(entry)
override fun getComparator(): NotifComparator {
return object : NotifComparator("HeadsUp") {
- override fun compare(o1: ListEntry, o2: ListEntry): Int =
+ override fun compare(o1: PipelineEntry, o2: PipelineEntry): Int =
mHeadsUpManager.compare(o1.representativeEntry, o2.representativeEntry)
}
}
@@ -867,7 +867,7 @@
private fun isSticky(entry: NotificationEntry) = mHeadsUpManager.isSticky(entry.key)
- private fun isEntryBinding(entry: ListEntry): Boolean {
+ private fun isEntryBinding(entry: PipelineEntry): Boolean {
val bindingUntil = mEntriesBindingUntil[entry.key]
return bindingUntil != null && bindingUntil >= mNow
}
@@ -875,12 +875,12 @@
/**
* Whether the notification is already heads up or binding so that it can imminently heads up
*/
- private fun isAttemptingToShowHun(entry: ListEntry) =
+ private fun isAttemptingToShowHun(entry: PipelineEntry) =
mHeadsUpManager.isHeadsUpEntry(entry.key) ||
isEntryBinding(entry) ||
isHeadsUpAnimatingAway(entry)
- private fun isHeadsUpAnimatingAway(entry: ListEntry): Boolean {
+ private fun isHeadsUpAnimatingAway(entry: PipelineEntry): Boolean {
if (!GroupHunAnimationFix.isEnabled) return false
return entry.representativeEntry?.row?.isHeadsUpAnimatingAway ?: false
}
@@ -891,7 +891,7 @@
* returns `true` even if the update would (in isolation of its group) cause the heads up to be
* retracted. This is important for not retracting transferred group heads ups.
*/
- private fun isGoingToShowHunNoRetract(entry: ListEntry) =
+ private fun isGoingToShowHunNoRetract(entry: PipelineEntry) =
mPostedEntries[entry.key]?.calculateShouldBeHeadsUpNoRetract ?: isAttemptingToShowHun(entry)
/**
@@ -900,7 +900,7 @@
* strict because any update which would revoke the heads up supersedes the current heads
* up/binding state.
*/
- private fun isGoingToShowHunStrict(entry: ListEntry) =
+ private fun isGoingToShowHunStrict(entry: PipelineEntry) =
mPostedEntries[entry.key]?.calculateShouldBeHeadsUpStrict ?: isAttemptingToShowHun(entry)
private fun endNotifLifetimeExtensionIfExtended(entry: NotificationEntry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt
index e232849..56deb18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt
@@ -27,7 +27,7 @@
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -176,7 +176,7 @@
}
}
- private fun pickOutTopUnseenNotifs(list: List<ListEntry>) {
+ private fun pickOutTopUnseenNotifs(list: List<PipelineEntry>) {
if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return
if (!minimalismEnabled) return
// Only ever elevate a top unseen notification on keyguard, not even locked shade
@@ -224,7 +224,7 @@
val topOngoingSectioner =
object : NotifSectioner("TopOngoing", BUCKET_TOP_ONGOING) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return false
if (!minimalismEnabled) return false
return entry.anyEntry { notificationEntry ->
@@ -235,7 +235,7 @@
val topUnseenSectioner =
object : NotifSectioner("TopUnseen", BUCKET_TOP_UNSEEN) {
- override fun isInSection(entry: ListEntry): Boolean {
+ override fun isInSection(entry: PipelineEntry): Boolean {
if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return false
if (!minimalismEnabled) return false
return entry.anyEntry { notificationEntry ->
@@ -244,7 +244,7 @@
}
}
- private fun ListEntry.anyEntry(predicate: (NotificationEntry?) -> Boolean) =
+ private fun PipelineEntry.anyEntry(predicate: (NotificationEntry?) -> Boolean) =
when {
predicate(representativeEntry) -> true
this !is GroupEntry -> false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt
index de6f257..660ee40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt
@@ -30,6 +30,7 @@
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.expansionChanges
+import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -313,7 +314,7 @@
unseenNotifications.contains(entry) -> false
// Don't apply the filter to (non-promoted) group summaries
// - summary will be pruned if necessary, depending on if children are filtered
- entry.parent?.summary == entry -> false
+ (entry.parent as? GroupEntry)?.summary == entry -> false
// Check that the entry satisfies certain characteristics that would bypass the
// filter
shouldIgnoreUnseenCheck(entry) -> false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 2ecce1f..20c6736 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -35,7 +35,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
@@ -232,9 +232,10 @@
*/
@Override
public boolean shouldFilterOut(NotificationEntry entry, long now) {
- final GroupEntry parent = requireNonNull(entry.getParent());
- Boolean isMemberOfDelayedGroup = mIsDelayedGroupCache.get(parent);
- if (isMemberOfDelayedGroup == null) {
+ final PipelineEntry pipelineEntryParent = requireNonNull(entry.getParent());
+ Boolean isMemberOfDelayedGroup = mIsDelayedGroupCache.get(pipelineEntryParent);
+ if (isMemberOfDelayedGroup == null && pipelineEntryParent instanceof GroupEntry) {
+ GroupEntry parent = (GroupEntry) pipelineEntryParent;
isMemberOfDelayedGroup = shouldWaitForGroupToInflate(parent, now);
mIsDelayedGroupCache.put(parent, isMemberOfDelayedGroup);
}
@@ -279,7 +280,7 @@
}
};
- private void purgeCaches(Collection<ListEntry> entries) {
+ private void purgeCaches(Collection<PipelineEntry> entries) {
Set<String> wantedPackages = getPackages(entries);
mAppIconProvider.purgeCache(wantedPackages);
mNotificationIconStyleProvider.purgeCache(wantedPackages);
@@ -288,9 +289,9 @@
/**
* Get all app packages present in {@param entries}.
*/
- private static @NonNull Set<String> getPackages(Collection<ListEntry> entries) {
+ private static @NonNull Set<String> getPackages(Collection<PipelineEntry> entries) {
Set<String> packages = new HashSet<>();
- for (ListEntry entry : entries) {
+ for (PipelineEntry entry : entries) {
NotificationEntry notificationEntry = entry.getRepresentativeEntry();
if (notificationEntry == null) {
Log.wtf(TAG, "notification entry " + entry.getKey()
@@ -302,9 +303,9 @@
return packages;
}
- private void inflateAllRequiredViews(List<ListEntry> entries) {
+ private void inflateAllRequiredViews(List<PipelineEntry> entries) {
for (int i = 0, size = entries.size(); i < size; i++) {
- ListEntry entry = entries.get(i);
+ PipelineEntry entry = entries.get(i);
if (entry instanceof GroupEntry) {
GroupEntry groupEntry = (GroupEntry) entry;
inflateRequiredGroupViews(groupEntry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 69b069d..26bc5b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
@@ -97,7 +97,7 @@
private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting",
NotificationPriorityBucketKt.BUCKET_ALERTING) {
@Override
- public boolean isInSection(ListEntry entry) {
+ public boolean isInSection(PipelineEntry entry) {
return mHighPriorityProvider.isHighPriority(entry);
}
@@ -115,7 +115,7 @@
private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent",
NotificationPriorityBucketKt.BUCKET_SILENT) {
@Override
- public boolean isInSection(ListEntry entry) {
+ public boolean isInSection(PipelineEntry entry) {
return !mHighPriorityProvider.isHighPriority(entry)
&& !entry.getRepresentativeEntry().isAmbient();
}
@@ -128,7 +128,7 @@
@Nullable
@Override
- public void onEntriesUpdated(@NonNull List<ListEntry> entries) {
+ public void onEntriesUpdated(@NonNull List<PipelineEntry> entries) {
mHasSilentEntries = false;
for (int i = 0; i < entries.size(); i++) {
if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) {
@@ -144,7 +144,7 @@
private final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized",
NotificationPriorityBucketKt.BUCKET_SILENT) {
@Override
- public boolean isInSection(ListEntry entry) {
+ public boolean isInSection(PipelineEntry entry) {
return !mHighPriorityProvider.isHighPriority(entry)
&& entry.getRepresentativeEntry().isAmbient();
}
@@ -157,7 +157,7 @@
@Nullable
@Override
- public void onEntriesUpdated(@NonNull List<ListEntry> entries) {
+ public void onEntriesUpdated(@NonNull List<PipelineEntry> entries) {
mHasMinimizedEntries = false;
for (int i = 0; i < entries.size(); i++) {
if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt
index 4a7b7ca..930e52a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAlertTimeCoordinator.kt
@@ -17,7 +17,7 @@
import android.util.ArrayMap
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -39,7 +39,7 @@
pipeline.addOnAfterRenderEntryListener(::onAfterRenderEntry)
}
- private fun onBeforeFinalizeFilterListener(entries: List<ListEntry>) {
+ private fun onBeforeFinalizeFilterListener(entries: List<PipelineEntry>) {
latestAlertTimeBySummary.clear()
entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry ->
val summary = checkNotNull(groupEntry.summary)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
index df8e56e..a987c54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
@@ -20,7 +20,7 @@
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.notification.AssistantFeedbackController
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -63,7 +63,7 @@
pipeline.addOnAfterRenderEntryListener(::onAfterRenderEntry)
}
- private fun onBeforeRenderList(list: List<ListEntry>) {
+ private fun onBeforeRenderList(list: List<PipelineEntry>) {
entryToExpand =
list.firstOrNull()?.representativeEntry?.takeIf { entry ->
!mSectionStyleProvider.isMinimizedSection(entry.section!!)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
index 90916d1..db24e7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
@@ -32,7 +32,7 @@
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.DynamicPrivacyController
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
@@ -155,7 +155,7 @@
}
}
- override fun onBeforeRenderList(entries: List<ListEntry>) {
+ override fun onBeforeRenderList(entries: List<PipelineEntry>) {
if (
isKeyguardGoingAway ||
statusBarStateController.state == StatusBarState.KEYGUARD &&
@@ -220,13 +220,15 @@
}
}
-private fun extractAllRepresentativeEntries(entries: List<ListEntry>): Sequence<NotificationEntry> =
+private fun extractAllRepresentativeEntries(entries: List<PipelineEntry>): Sequence<NotificationEntry> =
entries.asSequence().flatMap(::extractAllRepresentativeEntries)
-private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence<NotificationEntry> =
+private fun extractAllRepresentativeEntries(
+ pipelineEntry: PipelineEntry,
+): Sequence<NotificationEntry> =
sequence {
- listEntry.representativeEntry?.let { yield(it) }
- if (listEntry is GroupEntry) {
- yieldAll(extractAllRepresentativeEntries(listEntry.children))
+ pipelineEntry.representativeEntry?.let { yield(it) }
+ if (pipelineEntry is GroupEntry) {
+ yieldAll(extractAllRepresentativeEntries(pipelineEntry.children))
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
index 1c66db7..29a8eb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
@@ -19,7 +19,7 @@
import android.service.notification.NotificationListenerService
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
@@ -67,7 +67,7 @@
mShadeEmptiedCallback = callback
}
- private fun onBeforeRenderList(entries: List<ListEntry>) {
+ private fun onBeforeRenderList(entries: List<PipelineEntry>) {
if (mEntryRemoved && entries.isEmpty()) {
mLogger.logShadeEmptied()
// TODO(b/206023518): This was bad. Do not copy this.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index 1cb2366..53a73f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -19,7 +19,7 @@
import com.android.app.tracing.traceSection
import com.android.server.notification.Flags.screenshareNotificationHiding
import com.android.systemui.Flags.screenshareNotificationHidingBugFix
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl
@@ -50,14 +50,14 @@
groupExpansionManagerImpl.attach(pipeline)
}
- private fun onAfterRenderList(entries: List<ListEntry>) =
+ private fun onAfterRenderList(entries: List<PipelineEntry>) =
traceSection("StackCoordinator.onAfterRenderList") {
val notifStats = calculateNotifStats(entries)
activeNotificationsInteractor.setNotifStats(notifStats)
renderListInteractor.setRenderedList(entries)
}
- private fun calculateNotifStats(entries: List<ListEntry>): NotifStats {
+ private fun calculateNotifStats(entries: List<PipelineEntry>): NotifStats {
var hasNonClearableAlertingNotifs = false
var hasClearableAlertingNotifs = false
var hasNonClearableSilentNotifs = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 49d5029..3e5655a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -39,7 +39,7 @@
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
@@ -253,21 +253,20 @@
return false;
}
- final GroupEntry parent = entry.getParent();
+ final PipelineEntry parent = entry.getParent();
if (parent == null) {
return false;
}
-
return isHeadsUpGroup(parent);
}
- private boolean isHeadsUpGroup(GroupEntry groupEntry) {
- if (StabilizeHeadsUpGroup.isUnexpectedlyInLegacyMode()) {
+ private boolean isHeadsUpGroup(PipelineEntry pipelineEntry) {
+ if (!(pipelineEntry instanceof GroupEntry groupEntry)) {
return false;
}
- if (groupEntry == null) {
+ if (StabilizeHeadsUpGroup.isUnexpectedlyInLegacyMode()) {
return false;
}
@@ -370,7 +369,7 @@
}
@Override
- public boolean isEntryReorderingAllowed(@NonNull ListEntry entry) {
+ public boolean isEntryReorderingAllowed(@NonNull PipelineEntry entry) {
if (StabilizeHeadsUpGroup.isEnabled()) {
if (isEveryChangeAllowed()) {
return true;
@@ -403,7 +402,7 @@
private final OnBeforeRenderListListener mOnBeforeRenderListListener =
new OnBeforeRenderListListener() {
@Override
- public void onBeforeRenderList(List<ListEntry> entries) {
+ public void onBeforeRenderList(List<PipelineEntry> entries) {
if (StabilizeHeadsUpGroup.isUnexpectedlyInLegacyMode()) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
index 465bc28..adcc3ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
@@ -124,7 +124,7 @@
val parent = entry.parent ?: error("Entry must have a parent to determine if minimized")
val isMinimizedSection = sectionStyleProvider.isMinimizedSection(section)
val isTopLevelEntry = parent == GroupEntry.ROOT_ENTRY
- val isGroupSummary = parent.summary == entry
+ val isGroupSummary = (parent as? GroupEntry)?.summary == entry
return isMinimizedSection && (isTopLevelEntry || isGroupSummary)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
index ac450c0..e3ab81c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
@@ -18,7 +18,7 @@
import androidx.annotation.NonNull;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
@@ -31,5 +31,5 @@
* @param entries The current list of top-level entries. Note that this is a live view into the
* current list and will change whenever the pipeline is rerun.
*/
- void onAfterRenderList(@NonNull List<ListEntry> entries);
+ void onAfterRenderList(@NonNull List<PipelineEntry> entries);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java
index 086661e..3c4f422 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
@@ -30,5 +30,5 @@
* @param entries The current list of top-level entries. Note that this is a live view into the
* current list and will change whenever the pipeline is rerun.
*/
- void onBeforeFinalizeFilter(List<ListEntry> entries);
+ void onBeforeFinalizeFilter(List<PipelineEntry> entries);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
index 44a27a4..6ceb7d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
@@ -30,5 +30,5 @@
* @param entries The current list of top-level entries. Note that this is a live view into the
* current list and will change whenever the pipeline is rerun.
*/
- void onBeforeRenderList(List<ListEntry> entries);
+ void onBeforeRenderList(List<PipelineEntry> entries);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
index 56cfe5c..858cec1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
@@ -30,5 +30,5 @@
* @param entries The current list of top-level entries. Note that this is a live view into the
* current list and will change whenever the pipeline is rerun.
*/
- void onBeforeSort(List<ListEntry> entries);
+ void onBeforeSort(List<PipelineEntry> entries);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
index 0dc4df0..eb525c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
@@ -35,5 +35,5 @@
* a live view into the current notif list and will change as the list moves through
* the pipeline.
*/
- void onBeforeTransformGroups(List<ListEntry> list);
+ void onBeforeTransformGroups(List<PipelineEntry> list);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt
index d8f75f6..0d8a64a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderHelper.kt
@@ -16,10 +16,10 @@
package com.android.systemui.statusbar.notification.collection.listbuilder
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
object ShadeListBuilderHelper {
- fun getSectionSubLists(entries: List<ListEntry>): Iterable<List<ListEntry>> =
+ fun getSectionSubLists(entries: List<PipelineEntry>): Iterable<List<PipelineEntry>> =
getContiguousSubLists(entries, minLength = 1) { it.sectionIndex }
inline fun <T : Any, K : Any> getContiguousSubLists(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index a8409d0c..8a9548f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -23,7 +23,7 @@
import com.android.systemui.log.core.LogLevel.WARNING
import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.StateName
import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.getStateName
@@ -152,9 +152,9 @@
fun logEntryAttachStateChanged(
buildId: Int,
- entry: ListEntry,
- prevParent: GroupEntry?,
- newParent: GroupEntry?
+ entry: PipelineEntry,
+ prevParent: PipelineEntry?,
+ newParent: PipelineEntry?
) {
buffer.log(TAG, INFO, {
long1 = buildId.toLong()
@@ -177,7 +177,7 @@
})
}
- fun logParentChanged(buildId: Int, prevParent: GroupEntry?, newParent: GroupEntry?) {
+ fun logParentChanged(buildId: Int, prevParent: PipelineEntry?, newParent: PipelineEntry?) {
buffer.log(TAG, INFO, {
long1 = buildId.toLong()
str1 = prevParent?.logKey
@@ -195,8 +195,8 @@
fun logParentChangeSuppressedStarted(
buildId: Int,
- suppressedParent: GroupEntry?,
- keepingParent: GroupEntry?
+ suppressedParent: PipelineEntry?,
+ keepingParent: PipelineEntry?
) {
buffer.log(TAG, INFO, {
long1 = buildId.toLong()
@@ -209,8 +209,8 @@
fun logParentChangeSuppressedStopped(
buildId: Int,
- previouslySuppressedParent: GroupEntry?,
- previouslyKeptParent: GroupEntry?
+ previouslySuppressedParent: PipelineEntry?,
+ previouslyKeptParent: PipelineEntry?
) {
buffer.log(TAG, INFO, {
long1 = buildId.toLong()
@@ -224,7 +224,7 @@
fun logGroupPruningSuppressed(
buildId: Int,
- keepingParent: GroupEntry?
+ keepingParent: PipelineEntry?
) {
buffer.log(TAG, INFO, {
long1 = buildId.toLong()
@@ -310,7 +310,7 @@
val logRankInFinalList = Compile.IS_DEBUG && notifPipelineFlags.isDevLoggingEnabled()
- fun logFinalList(entries: List<ListEntry>) {
+ fun logFinalList(entries: List<PipelineEntry>) {
if (entries.isEmpty()) {
buffer.log(TAG, DEBUG, {}, { "(empty list)" })
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
index f7bbd28..f7c74c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
@@ -18,7 +18,7 @@
import androidx.annotation.NonNull;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.Comparator;
@@ -29,7 +29,7 @@
*/
public abstract class NotifComparator
extends Pluggable<NotifComparator>
- implements Comparator<ListEntry> {
+ implements Comparator<PipelineEntry> {
protected NotifComparator(String name) {
super(name);
@@ -41,5 +41,5 @@
* @return a negative integer, zero, or a positive integer as the first argument is less than
* equal to, or greater than the second (same as standard Comparator<> interface).
*/
- public abstract int compare(@NonNull ListEntry o1, @NonNull ListEntry o2);
+ public abstract int compare(@NonNull PipelineEntry o1, @NonNull PipelineEntry o2);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
index 8c52c53..4a856a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
@@ -18,7 +18,7 @@
import android.annotation.Nullable;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import com.android.systemui.statusbar.notification.collection.render.NodeController;
import com.android.systemui.statusbar.notification.collection.render.NodeSpec;
@@ -52,11 +52,11 @@
* However, this doesn't necessarily mean that your section will get called on each top-level
* notification. The first section to return true determines the section of the notification.
*/
- public abstract boolean isInSection(ListEntry entry);
+ public abstract boolean isInSection(PipelineEntry entry);
/**
* Returns an optional {@link NotifComparator} to sort entries only in this section.
- * {@link ListEntry} instances passed to this comparator are guaranteed to have this section,
+ * {@link PipelineEntry} instances passed to this comparator are guaranteed to have this section,
* and this ordering will take precedence over any global comparators supplied to {@link
* com.android.systemui.statusbar.notification.collection.NotifPipeline#setComparators(List)}.
*
@@ -80,5 +80,5 @@
* Notify of children of this section being updated
* @param entries of this section that are borrowed (must clone to store)
*/
- public void onEntriesUpdated(List<ListEntry> entries) {}
+ public void onEntriesUpdated(List<PipelineEntry> entries) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt
index 58bbca8..e1e2bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
/**
@@ -75,7 +75,7 @@
* being suppressed. However, if an order change is suppressed, that will be reported to ths
* implementation by calling [onEntryReorderSuppressed] after ordering is complete.
*/
- abstract fun isEntryReorderingAllowed(entry: ListEntry): Boolean
+ abstract fun isEntryReorderingAllowed(entry: PipelineEntry): Boolean
/**
* Called by the pipeline to determine if every call to the other stability methods would
@@ -100,7 +100,7 @@
override fun isGroupChangeAllowed(entry: NotificationEntry): Boolean = true
override fun isGroupPruneAllowed(entry: GroupEntry): Boolean = true
override fun isSectionChangeAllowed(entry: NotificationEntry): Boolean = true
- override fun isEntryReorderingAllowed(entry: ListEntry): Boolean = true
+ override fun isEntryReorderingAllowed(entry: PipelineEntry): Boolean = true
override fun isEveryChangeAllowed(): Boolean = true
override fun onEntryReorderSuppressed() {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index 014ac54..ae2c70a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -27,6 +27,7 @@
import com.android.systemui.log.core.LogLevel.INFO
import com.android.systemui.log.core.LogLevel.WARNING
import com.android.systemui.log.core.LogLevel.WTF
+import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotifCollection
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason
import com.android.systemui.statusbar.notification.collection.NotifCollection.FutureDismissal
@@ -421,6 +422,14 @@
})
}
+ private fun getParentLogKey(childEntry: NotificationEntry): String {
+ return if (childEntry.parent is GroupEntry) {
+ (childEntry.parent as? GroupEntry)?.summary?.logKey ?: "(null)"
+ } else {
+ "(null)"
+ }
+ }
+
fun logDismissAlreadyParentDismissedNotif(
childEntry: NotificationEntry,
childIndex: Int,
@@ -430,7 +439,7 @@
str1 = childEntry.logKey
int1 = childIndex
int2 = childCount
- str2 = childEntry.parent?.summary?.logKey ?: "(null)"
+ str2 = getParentLogKey(childEntry)
}, {
"DISMISS Already Parent-Dismissed $str1 ($int1/$int2) with summary $str2"
})
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index 2e3ab92..051bd3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -23,7 +23,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
@@ -53,7 +53,7 @@
}
/**
- * @return true if the ListEntry is high priority, else false
+ * @return true if the PipelineEntry is high priority, else false
*
* A NotificationEntry is considered high priority if it:
* - has importance greater than or equal to IMPORTANCE_DEFAULT
@@ -67,12 +67,12 @@
* A GroupEntry is considered high priority if its representativeEntry (summary) or any of its
* children are high priority.
*/
- public boolean isHighPriority(@Nullable ListEntry entry) {
+ public boolean isHighPriority(@Nullable PipelineEntry entry) {
return isHighPriority(entry, /* allowImplicit = */ true);
}
/**
- * @return true if the ListEntry is explicitly high priority, else false
+ * @return true if the PipelineEntry is explicitly high priority, else false
*
* A NotificationEntry is considered explicitly high priority if has importance greater than or
* equal to IMPORTANCE_DEFAULT.
@@ -80,11 +80,11 @@
* A GroupEntry is considered explicitly high priority if its representativeEntry (summary) or
* any of its children are explicitly high priority.
*/
- public boolean isExplicitlyHighPriority(@Nullable ListEntry entry) {
+ public boolean isExplicitlyHighPriority(@Nullable PipelineEntry entry) {
return isHighPriority(entry, /* allowImplicit= */ false);
}
- private boolean isHighPriority(@Nullable ListEntry entry, boolean allowImplicit) {
+ private boolean isHighPriority(@Nullable PipelineEntry entry, boolean allowImplicit) {
if (entry == null) {
return false;
}
@@ -100,9 +100,9 @@
}
/**
- * @return true if the ListEntry is high priority conversation, else false
+ * @return true if the PipelineEntry is high priority conversation, else false
*/
- public boolean isHighPriorityConversation(@NonNull ListEntry entry) {
+ public boolean isHighPriorityConversation(@NonNull PipelineEntry entry) {
final NotificationEntry notifEntry = entry.getRepresentativeEntry();
if (notifEntry == null) {
return false;
@@ -119,7 +119,7 @@
return isNotificationEntryWithAtLeastOneImportantChild(entry);
}
- private boolean isNotificationEntryWithAtLeastOneImportantChild(@NonNull ListEntry entry) {
+ private boolean isNotificationEntryWithAtLeastOneImportantChild(@NonNull PipelineEntry entry) {
if (!(entry instanceof GroupEntry)) {
return false;
}
@@ -134,7 +134,7 @@
* Returns whether the given ListEntry has a high priority child or is in a group with a child
* that's high priority
*/
- private boolean hasHighPriorityChild(ListEntry entry, boolean allowImplicit) {
+ private boolean hasHighPriorityChild(PipelineEntry entry, boolean allowImplicit) {
if (NotificationBundleUi.isEnabled()) {
GroupEntry representativeGroupEntry = null;
if (entry instanceof GroupEntry) {
@@ -142,9 +142,10 @@
} else if (entry instanceof NotificationEntry){
final NotificationEntry notificationEntry = entry.getRepresentativeEntry();
if (notificationEntry.getParent() != null
- && notificationEntry.getParent().getSummary() != null
- && notificationEntry.getParent().getSummary() == notificationEntry) {
- representativeGroupEntry = notificationEntry.getParent();
+ && notificationEntry.getParent() instanceof GroupEntry parent
+ && parent.getSummary() != null
+ && parent.getSummary() == notificationEntry) {
+ representativeGroupEntry = parent;
}
}
return representativeGroupEntry != null &&
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
index ea9f295..f418bb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.notification.collection.provider
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
@@ -53,7 +53,7 @@
* Determine if the given entry is minimized.
*/
@JvmOverloads
- fun isMinimized(entry: ListEntry, ifNotInSection: Boolean = true): Boolean {
+ fun isMinimized(entry: PipelineEntry, ifNotInSection: Boolean = true): Boolean {
val section = entry.section ?: return ifNotInSection
return isMinimizedSection(section)
}
@@ -77,7 +77,7 @@
* Determine if the given entry is silent.
*/
@JvmOverloads
- fun isSilent(entry: ListEntry, ifNotInSection: Boolean = true): Boolean {
+ fun isSilent(entry: PipelineEntry, ifNotInSection: Boolean = true): Boolean {
val section = entry.section ?: return ifNotInSection
if (SortBySectionTimeFlag.isEnabled) {
if (entry.section?.bucket == BUCKET_PEOPLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
index 16b98e2..b179a69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
@@ -25,7 +25,7 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.notification.collection.EntryAdapter;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
@@ -81,7 +81,7 @@
}
final Set<NotificationEntry> renderingSummaries = new HashSet<>();
- for (ListEntry entry : entries) {
+ for (PipelineEntry entry : entries) {
if (entry instanceof GroupEntry) {
renderingSummaries.add(entry.getRepresentativeEntry());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
index 69267e5..3edbfaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
@@ -22,6 +22,7 @@
import com.android.systemui.statusbar.notification.collection.EntryAdapter;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import java.util.List;
@@ -78,5 +79,5 @@
* @return list of the children
*/
@Nullable
- List<NotificationEntry> getChildren(@NonNull ListEntry summary);
+ List<NotificationEntry> getChildren(@NonNull PipelineEntry summary);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
index 80a9f8ad..a1a23e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
@@ -24,7 +24,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.EntryAdapter;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
@@ -48,8 +48,13 @@
// The entry is not attached, so it doesn't count.
return false;
}
+ PipelineEntry pipelineEntry = entry.getParent();
+ if (!(pipelineEntry instanceof GroupEntry groupEntry)) {
+ return false;
+ }
+
// If entry is a summary, its parent is a GroupEntry with summary = entry.
- return entry.getParent().getSummary() == entry;
+ return groupEntry.getSummary() == entry;
}
@Override
@@ -65,7 +70,10 @@
if (isTopLevelEntry(entry) || entry.getParent() == null) {
return null;
}
- return entry.getParent().getSummary();
+ if (entry.getParent() instanceof GroupEntry parent) {
+ return parent.getSummary();
+ }
+ return null;
}
@Nullable
@@ -91,8 +99,9 @@
@Nullable
@Override
- public List<NotificationEntry> getChildren(@NonNull ListEntry entry) {
+ public List<NotificationEntry> getChildren(@NonNull PipelineEntry entry) {
NotificationBundleUi.assertInLegacyMode();
+
if (entry instanceof GroupEntry) {
return ((GroupEntry) entry).getChildren();
}
@@ -100,8 +109,7 @@
NotificationEntry representativeEntry = entry.getRepresentativeEntry();
if (representativeEntry != null && isGroupSummary(representativeEntry)) {
// maybe we were actually passed the summary
- GroupEntry parent = representativeEntry.getParent();
- if (parent != null) {
+ if (representativeEntry.getParent() instanceof GroupEntry parent) {
return parent.getChildren();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
index 9fc4e40..e173194 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
@@ -18,12 +18,12 @@
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
import com.android.systemui.util.Compile
import com.android.app.tracing.traceSection
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
/**
* Converts a notif list (the output of the ShadeListBuilder) into a NodeSpec, an abstract
@@ -45,7 +45,7 @@
fun buildNodeSpec(
rootController: NodeController,
- notifList: List<ListEntry>
+ notifList: List<PipelineEntry>
): NodeSpec = traceSection("NodeSpecBuilder.buildNodeSpec") {
val root = NodeSpecImpl(null, rootController)
@@ -100,7 +100,7 @@
return@traceSection root
}
- private fun buildNotifNode(parent: NodeSpec, entry: ListEntry): NodeSpec = when (entry) {
+ private fun buildNotifNode(parent: NodeSpec, entry: PipelineEntry): NodeSpec = when (entry) {
is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireNodeController(entry))
is GroupEntry ->
NodeSpecImpl(parent, viewBarn.requireNodeController(checkNotNull(entry.summary)))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
index fd91d5a..56662f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
@@ -18,18 +18,18 @@
import android.view.textclassifier.Log
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import javax.inject.Inject
/**
- * The ViewBarn is just a map from [ListEntry] to an instance of a [NodeController].
+ * The ViewBarn is just a map from [PipelineEntry] to an instance of a [NodeController].
*/
@SysUISingleton
class NotifViewBarn @Inject constructor() {
private val rowMap = mutableMapOf<String, NotifViewController>()
- fun requireNodeController(entry: ListEntry): NodeController {
+ fun requireNodeController(entry: PipelineEntry): NodeController {
if (DEBUG) {
Log.d(TAG, "requireNodeController: ${entry.key}")
}
@@ -50,14 +50,14 @@
return rowMap[entry.key] ?: error("No view has been registered for entry: ${entry.key}")
}
- fun registerViewForEntry(entry: ListEntry, controller: NotifViewController) {
+ fun registerViewForEntry(entry: PipelineEntry, controller: NotifViewController) {
if (DEBUG) {
Log.d(TAG, "registerViewForEntry: ${entry.key}")
}
rowMap[entry.key] = controller
}
- fun removeViewForEntry(entry: ListEntry) {
+ fun removeViewForEntry(entry: PipelineEntry) {
if (DEBUG) {
Log.d(TAG, "removeViewForEntry: ${entry.key}")
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
index 8284022..396d47e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.notification.collection.render
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
/**
@@ -34,7 +34,7 @@
* also ensure that future calls to [getStackController], [getGroupController], and
* [getRowController] will provide valid results.
*/
- fun onRenderList(notifList: List<ListEntry>)
+ fun onRenderList(notifList: List<PipelineEntry>)
/**
* Provides an interface for the pipeline to update individual groups. This will be called at
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
index 21e6837..93e844d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
@@ -19,7 +19,7 @@
import com.android.app.tracing.traceSection
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.PipelineDumpable
import com.android.systemui.statusbar.notification.collection.PipelineDumper
@@ -46,7 +46,7 @@
listBuilder.setOnRenderListListener(::onRenderList)
}
- private fun onRenderList(notifList: List<ListEntry>) {
+ private fun onRenderList(notifList: List<PipelineEntry>) {
traceSection("RenderStageManager.onRenderList") {
val viewRenderer = viewRenderer ?: return
viewRenderer.onRenderList(notifList)
@@ -85,7 +85,7 @@
dump("onAfterRenderEntryListeners", onAfterRenderEntryListeners)
}
- private fun dispatchOnAfterRenderList(entries: List<ListEntry>) {
+ private fun dispatchOnAfterRenderList(entries: List<PipelineEntry>) {
traceSection("RenderStageManager.dispatchOnAfterRenderList") {
onAfterRenderListListeners.forEach { listener -> listener.onAfterRenderList(entries) }
}
@@ -93,7 +93,7 @@
private fun dispatchOnAfterRenderGroups(
viewRenderer: NotifViewRenderer,
- entries: List<ListEntry>,
+ entries: List<PipelineEntry>,
) {
traceSection("RenderStageManager.dispatchOnAfterRenderGroups") {
if (onAfterRenderGroupListeners.isEmpty()) {
@@ -110,7 +110,7 @@
private fun dispatchOnAfterRenderEntries(
viewRenderer: NotifViewRenderer,
- entries: List<ListEntry>,
+ entries: List<PipelineEntry>,
) {
traceSection("RenderStageManager.dispatchOnAfterRenderEntries") {
if (onAfterRenderEntryListeners.isEmpty()) {
@@ -129,7 +129,7 @@
* Performs a forward, depth-first traversal of the list where the group's summary immediately
* precedes the group's children.
*/
- private inline fun List<ListEntry>.forEachNotificationEntry(
+ private inline fun List<PipelineEntry>.forEachNotificationEntry(
action: (NotificationEntry) -> Unit
) {
forEach { entry ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 72316bf..9532d6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -22,7 +22,7 @@
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.collection.GroupEntry
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.PipelineDumpable
import com.android.systemui.statusbar.notification.collection.PipelineDumper
@@ -76,7 +76,7 @@
private val viewRenderer =
object : NotifViewRenderer {
- override fun onRenderList(notifList: List<ListEntry>) {
+ override fun onRenderList(notifList: List<PipelineEntry>) {
traceSection("ShadeViewManager.onRenderList") {
viewDiffer.applySpec(specBuilder.buildNodeSpec(rootController, notifList))
}
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 bde3c4d..adc049e 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
@@ -29,7 +29,7 @@
import com.android.systemui.dagger.qualifiers.Main
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.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
@@ -57,11 +57,11 @@
/**
* Sets the current list of rendered notification entries as displayed in the notification list.
*/
- fun setRenderedList(entries: List<ListEntry>) {
+ fun setRenderedList(entries: List<PipelineEntry>) {
traceSection("RenderNotificationListInteractor.setRenderedList") {
repository.activeNotifications.update { existingModels ->
buildActiveNotificationsStore(existingModels, sectionStyleProvider, context) {
- entries.forEach(::addListEntry)
+ entries.forEach(::addPipelineEntry)
setRankingsMap(entries)
}
}
@@ -89,11 +89,11 @@
fun build(): ActiveNotificationsStore = builder.build()
/**
- * Convert a [ListEntry] into [ActiveNotificationEntryModel]s, and add them to the
+ * Convert a [PipelineEntry] into [ActiveNotificationEntryModel]s, and add them to the
* [ActiveNotificationsStore]. Special care is taken to avoid re-allocating models if the result
* would be identical to an existing model (at the expense of additional computations).
*/
- fun addListEntry(entry: ListEntry) {
+ fun addPipelineEntry(entry: PipelineEntry) {
when (entry) {
is GroupEntry -> {
entry.summary?.let { summary ->
@@ -116,11 +116,11 @@
}
}
- fun setRankingsMap(entries: List<ListEntry>) {
+ fun setRankingsMap(entries: List<PipelineEntry>) {
builder.setRankingsMap(flatMapToRankingsMap(entries))
}
- fun flatMapToRankingsMap(entries: List<ListEntry>): Map<String, Int> {
+ fun flatMapToRankingsMap(entries: List<PipelineEntry>): Map<String, Int> {
val result = ArrayMap<String, Int>()
for (entry in entries) {
if (entry is NotificationEntry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/AvalancheController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/AvalancheController.kt
index ccc2dff..867db8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/AvalancheController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/AvalancheController.kt
@@ -49,7 +49,7 @@
) : Dumpable {
private val tag = "AvalancheController"
- private val debug = Compile.IS_DEBUG && Log.isLoggable(tag, Log.DEBUG)
+ private val debug = false // Compile.IS_DEBUG && Log.isLoggable(tag, Log.DEBUG)
var baseEntryMapStr: () -> String = { "baseEntryMapStr not initialized" }
var enableAtRuntime = true
@@ -163,6 +163,7 @@
if (entry in nextMap) nextMap.remove(entry)
if (entry in nextList) nextList.remove(entry)
+ outcome = "add next"
addToNext(entry, runnable)
// Shorten headsUpEntryShowing display time
@@ -174,7 +175,7 @@
headsUpEntryShowing!!.updateEntry(
/* updatePostTime= */ false,
/* updateEarliestRemovalTime= */ false,
- /* reason= */ "avalanche duration update",
+ /* reason= */ "shorten duration of previously-last HUN",
)
}
}
@@ -269,8 +270,10 @@
}
nextList.sort()
val entryList = showingList + nextList
+ val thisKey = getKey(entry)
if (entryList.isEmpty()) {
- log { "No avalanche HUNs, use default ms: $autoDismissMs" }
+ headsUpManagerLogger.logAvalancheDuration(
+ thisKey, autoDismissMs, "No avalanche HUNs, use default", nextKey = "")
return autoDismissMs
}
// entryList.indexOf(entry) returns -1 even when the entry is in entryList
@@ -281,27 +284,29 @@
}
}
if (thisEntryIndex == -1) {
- log { "Untracked entry, use default ms: $autoDismissMs" }
+ headsUpManagerLogger.logAvalancheDuration(
+ thisKey, autoDismissMs, "Untracked entry, use default", nextKey = "")
return autoDismissMs
}
val nextEntryIndex = thisEntryIndex + 1
-
- // If last entry, use default duration
if (nextEntryIndex >= entryList.size) {
- log { "Last entry, use default ms: $autoDismissMs" }
+ headsUpManagerLogger.logAvalancheDuration(
+ thisKey, autoDismissMs, "Last entry, use default", nextKey = "")
return autoDismissMs
}
val nextEntry = entryList[nextEntryIndex]
+ val nextKey = getKey(nextEntry)
if (nextEntry.compareNonTimeFields(entry) == -1) {
- // Next entry is higher priority
- log { "Next entry is higher priority: 500ms" }
+ headsUpManagerLogger.logAvalancheDuration(
+ thisKey, 500, "LOWER priority than next: ", nextKey)
return 500
} else if (nextEntry.compareNonTimeFields(entry) == 0) {
- // Next entry is same priority
- log { "Next entry is same priority: 1000ms" }
+ headsUpManagerLogger.logAvalancheDuration(
+ thisKey, 1000, "SAME priority as next: ", nextKey)
return 1000
} else {
- log { "Next entry is lower priority, use default ms: $autoDismissMs" }
+ headsUpManagerLogger.logAvalancheDuration(
+ thisKey, autoDismissMs, "HIGHER priority than next: ", nextKey)
return autoDismissMs
}
}
@@ -355,25 +360,28 @@
}
private fun showNow(entry: HeadsUpEntry, runnableList: MutableList<Runnable>) {
- log { "SHOW: " + getKey(entry) }
-
+ headsUpManagerLogger.logAvalancheStage("show", getKey(entry))
uiEventLogger.log(ThrottleEvent.AVALANCHE_THROTTLING_HUN_SHOWN)
headsUpEntryShowing = entry
- runnableList.forEach {
- if (it in debugRunnableLabelMap) {
- log { "RUNNABLE: ${debugRunnableLabelMap[it]}" }
+ runnableList.forEach { runnable ->
+ if (debug) {
+ debugRunnableLabelMap[runnable]?.let { label ->
+ headsUpManagerLogger.logAvalancheStage("run", label)
+ // Remove label after logging to avoid memory leak
+ debugRunnableLabelMap.remove(runnable)
+ }
}
- it.run()
+ runnable.run()
}
}
private fun showNext() {
- log { "SHOW NEXT" }
+ headsUpManagerLogger.logAvalancheStage("show next", key = "")
headsUpEntryShowing = null
if (nextList.isEmpty()) {
- log { "NO MORE TO SHOW" }
+ headsUpManagerLogger.logAvalancheStage("no more", key = "")
previousHunKey = ""
return
}
@@ -395,11 +403,7 @@
debugRunnableLabelMap.remove(r)
}
}
- val queue = ArrayList<String>()
- for (entry in listToDrop) {
- queue.add("[${getKey(entry)}]")
- }
- val dropList = java.lang.String.join("\n", queue)
+ val dropList = listToDrop.joinToString("\n ") { getKey(it) }
headsUpManagerLogger.logDroppedHuns(dropList)
}
clearNext()
@@ -424,38 +428,24 @@
// Methods below are for logging only ==========================================================
- private inline fun log(s: () -> String) {
- if (debug) {
- Log.d(tag, s())
- }
- }
-
private fun getStateStr(): String {
- return "\navalanche state:" +
- "\n\tshowing: [${getKey(headsUpEntryShowing)}]" +
- "\n\tprevious: [$previousHunKey]" +
- "\n\tnext list: $nextListStr" +
- "\n\tnext map: $nextMapStr" +
- "\nBHUM.mHeadsUpEntryMap: " +
- baseEntryMapStr()
+ return "\n[AC state]" +
+ "\nshow: ${getKey(headsUpEntryShowing)}" +
+ "\nprevious: $previousHunKey" +
+ "\n$nextStr" +
+ "\n[HeadsUpManagerImpl.mHeadsUpEntryMap] " + baseEntryMapStr() + "\n"
}
- private val nextListStr: String
+ private val nextStr: String
get() {
- val queue = ArrayList<String>()
- for (entry in nextList) {
- queue.add("[${getKey(entry)}]")
+ val nextListStr = nextList.joinToString("\n ") { getKey(it) }
+ if (nextList.toSet() == nextMap.keys.toSet()) {
+ return "next (${nextList.size}):\n $nextListStr"
}
- return java.lang.String.join("\n", queue)
- }
-
- private val nextMapStr: String
- get() {
- val queue = ArrayList<String>()
- for (entry in nextMap.keys) {
- queue.add("[${getKey(entry)}]")
- }
- return java.lang.String.join("\n", queue)
+ // This should never happen
+ val nextMapStr = nextMap.keys.joinToString("\n ") { getKey(it) }
+ return "next list (${nextList.size}):\n $nextListStr" +
+ "\nnext map (${nextMap.size}):\n $nextMapStr"
}
fun getKey(entry: HeadsUpEntry?): String {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
index 7d74a49..87b9bf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
@@ -856,11 +856,11 @@
private String getEntryMapStr() {
if (mHeadsUpEntryMap.isEmpty()) {
- return "EMPTY";
+ return "";
}
StringBuilder entryMapStr = new StringBuilder();
for (HeadsUpEntry entry: mHeadsUpEntryMap.values()) {
- entryMapStr.append("\n\t").append(
+ entryMapStr.append("\n ").append(
entry.mEntry == null ? "null" : entry.mEntry.getKey());
}
return entryMapStr.toString();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt
index 65fb9ca..388d357 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt
@@ -71,7 +71,7 @@
str3 = outcome
bool1 = isEnabled
},
- { "$str1\n\t=> AC[isEnabled:$bool1] update: $str2\n\t=> $str3" },
+ { "$str1\n=> AC[enabled:$bool1] update: $str2\n=> $str3" },
)
}
@@ -90,7 +90,33 @@
str3 = outcome
bool1 = isEnabled
},
- { "$str1\n\t=> AC[isEnabled:$bool1] delete: $str2\n\t=> $str3" },
+ { "$str1\n=> AC[enabled:$bool1] delete: $str2\n=> $str3" },
+ )
+ }
+
+ fun logAvalancheStage(stage: String, key: String) {
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = stage
+ str2 = key
+ },
+ { "[AC] $str1 $str2" },
+ )
+ }
+
+ fun logAvalancheDuration(thisKey: String, duration: Int, reason: String, nextKey: String) {
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = thisKey
+ int1 = duration
+ str2 = reason
+ str3 = nextKey
+ },
+ { "[AC] $str1 | $int1 ms | $str2 $str3" },
)
}
@@ -325,7 +351,7 @@
}
fun logDroppedHuns(entryList: String) {
- buffer.log(TAG, VERBOSE, { str1 = entryList }, { "[AC] Drop HUNs: $str1" })
+ buffer.log(TAG, VERBOSE, { str1 = entryList }, { "[AC] dropped:\n $str1" })
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
index c7548aa..5096894 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
@@ -19,7 +19,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -198,7 +198,7 @@
else -> false
}
- private fun shouldHideIfEntrySilent(entry: ListEntry): Boolean =
+ private fun shouldHideIfEntrySilent(entry: PipelineEntry): Boolean =
when {
// Show if explicitly high priority (not hidden)
highPriorityProvider.isExplicitlyHighPriority(entry) -> false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
index f755dbb..002230e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -20,6 +20,7 @@
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
@@ -117,8 +118,8 @@
if (!entry.sbn.notification.isGroupSummary) {
return TYPE_NON_PERSON;
}
-
- return getPeopleTypeForChildList(entry.parent?.children)
+ val parent = entry.parent as? GroupEntry ?: return TYPE_NON_PERSON
+ return getPeopleTypeForChildList(parent.children)
} else {
if (!groupManager.isGroupSummary(entry)) {
return TYPE_NON_PERSON
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
index 893570b..7959e99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.promoted
import android.app.Flags
+import android.app.Flags.notificationsRedesignTemplates
import android.app.Notification
import android.graphics.PorterDuff
import android.view.LayoutInflater
@@ -166,7 +167,10 @@
private val closeButton: View? = root.findViewById(R.id.close_button)
private val conversationIconBadge: View? = root.findViewById(R.id.conversation_icon_badge)
private val conversationIcon: CachingIconView? = root.findViewById(R.id.conversation_icon)
- private val conversationText: TextView? = root.findViewById(R.id.conversation_text)
+ private val conversationText: TextView? =
+ root.findViewById(
+ if (notificationsRedesignTemplates()) R.id.title else R.id.conversation_text
+ )
private val expandButton: NotificationExpandButton? = root.findViewById(R.id.expand_button)
private val headerText: TextView? = root.findViewById(R.id.header_text)
private val headerTextDivider: View? = root.findViewById(R.id.header_text_divider)
@@ -386,24 +390,21 @@
setTextViewColor(time, SecondaryText)
setTextViewColor(chronometer, SecondaryText)
- val timeValue = content.time
-
- if (timeValue == null) {
- time?.visibility = GONE
- chronometer?.visibility = GONE
- } else if (timeValue.mode == When.Mode.BasicTime) {
- time?.visibility = VISIBLE
- time?.setTime(timeValue.time)
- chronometer?.visibility = GONE
- } else {
- inflateChronometer()
-
- time?.visibility = GONE
- chronometer?.visibility = VISIBLE
- chronometer?.base = timeValue.time
- chronometer?.isCountDown = (timeValue.mode == When.Mode.CountDown)
- chronometer?.setStarted(true)
+ if (content.time is When.Time) {
+ time?.setTime(content.time.currentTimeMillis)
}
+
+ if (content.time is When.Chronometer) {
+ inflateChronometer()
+ chronometer?.base = content.time.elapsedRealtimeMillis
+ chronometer?.isCountDown = content.time.isCountDown
+ chronometer?.setStarted(true)
+ } else {
+ chronometer?.stop()
+ }
+
+ time?.isVisible = (content.time is When.Time)
+ chronometer?.isVisible = (content.time is When.Chronometer)
}
private fun updateSmallIcon(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
index 39c7df0..2aafe8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
@@ -48,6 +48,7 @@
import com.android.systemui.statusbar.notification.row.shared.ImageModelProvider.ImageSizeClass.MediumSquare
import com.android.systemui.statusbar.notification.row.shared.ImageModelProvider.ImageSizeClass.SmallSquare
import com.android.systemui.statusbar.notification.row.shared.SkeletonImageTransform
+import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
interface PromotedNotificationContentExtractor {
@@ -64,6 +65,7 @@
constructor(
@ShadeDisplayAware private val context: Context,
private val skeletonImageTransform: SkeletonImageTransform,
+ private val systemClock: SystemClock,
private val logger: PromotedNotificationLogger,
) : PromotedNotificationContentExtractor {
override fun extractContent(
@@ -168,15 +170,17 @@
extras?.getBoolean(EXTRA_PROGRESS_INDETERMINATE)
private fun Notification.extractWhen(): When? {
- val time = `when`
- val showsTime = showsTime()
- val showsChronometer = showsChronometer()
- val countDown = chronometerCountDown()
-
return when {
- showsTime -> When(time, When.Mode.BasicTime)
- showsChronometer ->
- When(time, if (countDown) When.Mode.CountDown else When.Mode.CountUp)
+ showsChronometer() -> {
+ When.Chronometer(
+ elapsedRealtimeMillis =
+ `when` + systemClock.elapsedRealtime() - systemClock.currentTimeMillis(),
+ isCountDown = chronometerCountDown(),
+ )
+ }
+
+ showsTime() -> When.Time(currentTimeMillis = `when`)
+
else -> null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
index 38d41e3..0c2859f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
@@ -16,7 +16,9 @@
package com.android.systemui.statusbar.notification.promoted.shared.model
+import android.annotation.CurrentTimeMillisLong
import android.annotation.DrawableRes
+import android.annotation.ElapsedRealtimeLong
import android.app.Notification
import android.app.Notification.FLAG_PROMOTED_ONGOING
import androidx.annotation.ColorInt
@@ -120,16 +122,18 @@
data class Identity(val key: String, val style: Style)
/** The timestamp associated with a notification, along with the mode used to display it. */
- data class When(val time: Long, val mode: Mode) {
- /** The mode used to display a notification's `when` value. */
- enum class Mode {
- /** No custom mode requested by the notification. */
- BasicTime,
- /** Show the notification's time as a chronometer that counts down to [time]. */
- CountDown,
- /** Show the notification's time as a chronometer that counts up from [time]. */
- CountUp,
- }
+ sealed class When {
+ /** Show the notification's time as a timestamp. */
+ data class Time(@CurrentTimeMillisLong val currentTimeMillis: Long) : When()
+
+ /**
+ * Show the notification's time as a chronometer that counts up or down (based on
+ * [isCountDown]) to [elapsedRealtimeMillis].
+ */
+ data class Chronometer(
+ @ElapsedRealtimeLong val elapsedRealtimeMillis: Long,
+ val isCountDown: Boolean,
+ ) : When()
}
/** The colors used to display the notification. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index b4092cd..b077327 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.Flags.notificationBackgroundTintOptimization;
+import static com.android.systemui.Flags.notificationRowTransparency;
import static com.android.systemui.statusbar.notification.row.ExpandableView.ClipSide.BOTTOM;
import static com.android.systemui.statusbar.notification.row.ExpandableView.ClipSide.TOP;
@@ -38,6 +39,7 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.jank.InteractionJankMonitor.Configuration;
import com.android.systemui.Gefingerpoken;
+import com.android.systemui.common.shared.colors.SurfaceEffectColors;
import com.android.systemui.res.R;
import com.android.systemui.shade.TouchLogger;
import com.android.systemui.statusbar.NotificationShelf;
@@ -122,8 +124,12 @@
}
private void updateColors() {
- mNormalColor = mContext.getColor(
- com.android.internal.R.color.materialColorSurfaceContainerHigh);
+ if (notificationRowTransparency()) {
+ mNormalColor = SurfaceEffectColors.surfaceEffect1(getResources());
+ } else {
+ mNormalColor = mContext.getColor(
+ com.android.internal.R.color.materialColorSurfaceContainerHigh);
+ }
mTintedRippleColor = mContext.getColor(
R.color.notification_ripple_tinted_color);
mNormalRippleColor = mContext.getColor(
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 d383bee..d2800d7 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
@@ -21,7 +21,9 @@
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static com.android.systemui.Flags.notificationsPinnedHunInShade;
+import static com.android.systemui.Flags.notificationRowTransparency;
import static com.android.systemui.flags.Flags.ENABLE_NOTIFICATIONS_SIMULATE_SLOW_MEASURE;
+import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
import static com.android.systemui.statusbar.policy.RemoteInputView.FOCUS_ANIMATION_MIN_SCALE;
@@ -44,6 +46,7 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
@@ -115,7 +118,6 @@
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiForceExpanded;
-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;
@@ -167,6 +169,7 @@
private static final long RECENTLY_ALERTED_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(30);
private static final SourceType BASE_VALUE = SourceType.from("BaseValue");
private static final SourceType FROM_PARENT = SourceType.from("FromParent(ENR)");
+ private static final long INITIALIZATION_DELAY = 400;
// We don't correctly track dark mode until the content views are inflated, so always update
// the background on first content update just in case it happens to be during a theme change.
@@ -265,7 +268,6 @@
private NotificationContentView mPublicLayout;
private NotificationContentView mPrivateLayout;
private NotificationContentView[] mLayouts;
- private int mNotificationColor;
private ExpandableNotificationRowLogger mLogger;
private String mLoggingKey;
private NotificationGuts mGuts;
@@ -350,6 +352,10 @@
*/
private boolean mSaveSpaceOnLockscreen;
+ // indicates when this view was first attached to a window
+ // this value will reset when the view is completely removed from the shade (ie: filtered out)
+ private long initializationTime = -1;
+
/**
* It is added for unit testing purpose.
* Please do not use it for other purposes.
@@ -525,6 +531,10 @@
return mPublicLayout;
}
+ public String getLoggingKey() {
+ return mLoggingKey;
+ }
+
/**
* Sets animations running in the layouts of this row, including public, private, and children.
*
@@ -619,26 +629,11 @@
}
/**
- * Marks a content view as freeable, setting it so that future inflations do not reinflate
- * and ensuring that the view is freed when it is safe to remove.
- *
- * @param inflationFlag flag corresponding to the content view to be freed
- * @deprecated By default, {@link NotificationRowContentBinder#unbindContent} will tell the
- * view hierarchy to only free when the view is safe to remove so this method is no longer
- * needed. Will remove when all uses are gone.
- */
- @Deprecated
- public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) {
- RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry);
- params.markContentViewsFreeable(inflationFlag);
- mRowContentBindStage.requestRebind(mEntry, null /* callback */);
- }
-
- /**
* Returns whether this row is considered non-blockable (i.e. it's a non-blockable system notif
* or is in an allowList).
*/
public boolean getIsNonblockable() {
+ NotificationBundleUi.assertInLegacyMode();
if (mEntry == null) {
return true;
}
@@ -660,9 +655,8 @@
l.onNotificationUpdated(mEntry);
}
mShowingPublicInitialized = false;
- updateNotificationColor();
if (mMenuRow != null) {
- mMenuRow.onNotificationUpdated(mEntry.getSbn());
+ mMenuRow.onNotificationUpdated();
mMenuRow.setAppName(mAppName);
}
if (mIsSummaryWithChildren) {
@@ -721,15 +715,6 @@
}
/**
- * Called when the notification's ranking was changed (but nothing else changed).
- */
- public void onNotificationRankingUpdated() {
- if (mMenuRow != null) {
- mMenuRow.onNotificationUpdated(mEntry.getSbn());
- }
- }
-
- /**
* Call when bubble state has changed and the button on the notification should be updated.
*/
public void updateBubbleButton() {
@@ -740,7 +725,7 @@
@VisibleForTesting
void updateShelfIconColor() {
- StatusBarIconView expandedIcon = mEntry.getIcons().getShelfIcon();
+ StatusBarIconView expandedIcon = getShelfIcon();
boolean isPreL = Boolean.TRUE.equals(expandedIcon.getTag(R.id.icon_is_pre_L));
boolean colorize = !isPreL || NotificationUtils.isGrayscale(expandedIcon,
ContrastColorUtil.getInstance(mContext));
@@ -761,8 +746,13 @@
if (color != Notification.COLOR_INVALID) {
return color;
} else {
- return mEntry.getContrastedColor(mContext, mIsMinimized && !isExpanded(),
- getBackgroundColorWithoutTint());
+ if (NotificationBundleUi.isEnabled()) {
+ return mEntryAdapter.getContrastedColor(mContext, mIsMinimized && !isExpanded(),
+ getBackgroundColorWithoutTint());
+ } else {
+ return mEntry.getContrastedColor(mContext, mIsMinimized && !isExpanded(),
+ getBackgroundColorWithoutTint());
+ }
}
}
@@ -864,15 +854,29 @@
boolean customView = contractedView != null
&& contractedView.getId()
!= com.android.internal.R.id.status_bar_latest_event_content;
- boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
- boolean beforeP = mEntry.targetSdk < Build.VERSION_CODES.P;
- boolean beforeS = mEntry.targetSdk < Build.VERSION_CODES.S;
+ int targetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT;
+ if (NotificationBundleUi.isEnabled()) {
+ targetSdk = mEntryAdapter.getTargetSdk();
+ } else {
+ targetSdk = mEntry.targetSdk;
+ }
+
+ boolean beforeN = targetSdk < Build.VERSION_CODES.N;
+ boolean beforeP = targetSdk < Build.VERSION_CODES.P;
+ boolean beforeS = targetSdk < Build.VERSION_CODES.S;
int smallHeight;
boolean isCallLayout = contractedView instanceof CallLayout;
boolean isMessagingLayout = contractedView instanceof MessagingLayout
|| contractedView instanceof ConversationLayout;
+ String summarization = null;
+ if (NotificationBundleUi.isEnabled()) {
+ summarization = mEntryAdapter.getSummarization();
+ } else {
+ summarization = mEntry.getRanking().getSummarization();
+ }
+
if (customView && beforeS && !mIsSummaryWithChildren) {
if (beforeN) {
smallHeight = mMaxSmallHeightBeforeN;
@@ -885,7 +889,7 @@
smallHeight = maxExpandedHeight;
} else if (NmSummarizationUiFlag.isEnabled()
&& isMessagingLayout
- && !TextUtils.isEmpty(mEntry.getRanking().getSummarization())) {
+ && !TextUtils.isEmpty(summarization)) {
smallHeight = mMaxSmallHeightWithSummarization;
} else {
smallHeight = mMaxSmallHeight;
@@ -1518,7 +1522,22 @@
@Override
public boolean hasFinishedInitialization() {
- return getEntry().hasFinishedInitialization();
+ if (NotificationBundleUi.isEnabled()) {
+ return initializationTime != -1
+ && SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
+ } else {
+ return getEntry().hasFinishedInitialization();
+ }
+ }
+
+ public void resetInitializationTime() {
+ initializationTime = -1;
+ }
+
+ public void setInitializationTime(long time) {
+ if (initializationTime == -1) {
+ initializationTime = time;
+ }
}
/**
@@ -1533,7 +1552,7 @@
return null;
}
if (mMenuRow.getMenuView() == null) {
- mMenuRow.createMenu(this, mEntry.getSbn());
+ mMenuRow.createMenu(this);
mMenuRow.setAppName(mAppName);
FrameLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
@@ -1575,7 +1594,7 @@
if (oldMenu != null) {
int menuIndex = indexOfChild(oldMenu);
removeView(oldMenu);
- mMenuRow.createMenu(ExpandableNotificationRow.this, mEntry.getSbn());
+ mMenuRow.createMenu(ExpandableNotificationRow.this);
mMenuRow.setAppName(mAppName);
addView(mMenuRow.getMenuView(), menuIndex);
}
@@ -1583,12 +1602,17 @@
l.reinflate();
l.reInflateViews();
}
- mEntry.getSbn().clearPackageContext();
+ if (NotificationBundleUi.isEnabled()) {
+ mEntryAdapter.prepareForInflation();
+ } else {
+ mEntry.getSbn().clearPackageContext();
+ }
// TODO: Move content inflation logic out of this call
RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry);
params.setNeedsReinflation(true);
- var rebindEndCallback = mRebindingTracker.trackRebinding(mEntry.getKey());
+ var rebindEndCallback = mRebindingTracker.trackRebinding(NotificationBundleUi.isEnabled()
+ ? mEntryAdapter.getKey() : mEntry.getKey());
mRowContentBindStage.requestRebind(mEntry, (e) -> rebindEndCallback.onFinished());
Trace.endSection();
}
@@ -1631,6 +1655,12 @@
if (view != null) {
view.setBackgroundTintColor(color);
}
+ if (notificationRowTransparency()
+ && (mBackgroundNormal != null)
+ && (mEntry != null)) {
+ mBackgroundNormal.setBgIsColorized(
+ mEntry.getSbn().getNotification().isColorized());
+ }
}
public void closeRemoteInput() {
@@ -1646,20 +1676,6 @@
mPrivateLayout.setSingleLineWidthIndention(indention);
}
- public int getNotificationColor() {
- return mNotificationColor;
- }
-
- public void updateNotificationColor() {
- Configuration currentConfig = getResources().getConfiguration();
- boolean nightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
-
- mNotificationColor = ContrastColorUtil.resolveContrastColor(mContext,
- mEntry.getSbn().getNotification().color,
- getBackgroundColorWithoutTint(), nightMode);
- }
-
public HybridNotificationView getSingleLineView() {
return mPrivateLayout.getSingleLineView();
}
@@ -1917,15 +1933,15 @@
* Called when a notification which was previously kept in its parent for the
* dismiss animation is finally detached from its parent.
*/
- void logKeepInParentChildDetached(NotificationEntry child, NotificationEntry oldParent);
+ void logKeepInParentChildDetached(String child, String oldParent);
/**
* Called when we want to attach a notification to a new parent,
* but it still has the keepInParent flag set, so we skip it.
*/
void logSkipAttachingKeepInParentChild(
- NotificationEntry child,
- NotificationEntry newParent
+ String child,
+ String newParent
);
/**
@@ -1933,8 +1949,8 @@
* NotificationChildrenContainer
*/
void logRemoveTransientFromContainer(
- NotificationEntry childEntry,
- NotificationEntry containerEntry
+ String childEntry,
+ String containerEntry
);
/**
@@ -1942,7 +1958,7 @@
* NotificationStackScrollLayout
*/
void logRemoveTransientFromNssl(
- NotificationEntry childEntry
+ String childEntry
);
/**
@@ -1950,7 +1966,7 @@
* is not NotificationChildrenContainer or NotificationStackScrollLayout
*/
void logRemoveTransientFromViewGroup(
- NotificationEntry childEntry,
+ String childEntry,
ViewGroup containerView
);
@@ -1959,8 +1975,8 @@
* ExpandableNotificationRow
*/
void logAddTransientRow(
- NotificationEntry childEntry,
- NotificationEntry containerEntry,
+ String childEntry,
+ String containerEntry,
int index
);
@@ -1969,39 +1985,39 @@
* ExpandableNotificationRow
*/
void logRemoveTransientRow(
- NotificationEntry childEntry,
- NotificationEntry containerEntry
+ String childEntry,
+ String containerEntry
);
/**
* Called when resetting the alpha value for content views
*/
void logResetAllContentAlphas(
- NotificationEntry entry
+ String entry
);
/**
* Called when resetting the alpha value for content views is skipped
*/
void logSkipResetAllContentAlphas(
- NotificationEntry entry
+ String entry
);
/** Called when we start an appear animation. */
- void logStartAppearAnimation(NotificationEntry entry, boolean isAppear);
+ void logStartAppearAnimation(String entry, boolean isAppear);
/** Called when we cancel the running appear animation. */
- void logCancelAppearDrawing(NotificationEntry entry, boolean wasDrawing);
+ void logCancelAppearDrawing(String entry, boolean wasDrawing);
/** Called when the animator of the appear animation is started. */
- void logAppearAnimationStarted(NotificationEntry entry, boolean isAppear);
+ void logAppearAnimationStarted(String entry, boolean isAppear);
/** Called when we prepared an appear animation, but the animator was never started. */
- void logAppearAnimationSkipped(NotificationEntry entry, boolean isAppear);
+ void logAppearAnimationSkipped(String entry, boolean isAppear);
/** Called when the animator of the appear animation is finished. */
void logAppearAnimationFinished(
- NotificationEntry entry,
+ String entry,
boolean isAppear,
boolean cancelled
);
@@ -2080,7 +2096,7 @@
NotificationEntry entry,
RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
String appName,
- String notificationKey,
+ @NonNull String notificationKey,
ExpandableNotificationRowLogger logger,
KeyguardBypassController bypassController,
GroupMembershipManager groupMembershipManager,
@@ -2120,7 +2136,7 @@
mMenuRow.setAppName(mAppName);
}
mLogger = logger;
- mLoggingKey = notificationKey;
+ mLoggingKey = logKey(notificationKey);
mBypassController = bypassController;
mGroupMembershipManager = groupMembershipManager;
mGroupExpansionManager = groupExpansionManager;
@@ -2166,7 +2182,7 @@
R.dimen.notification_min_height);
}
mMaxSmallHeightWithSummarization = NotificationUtils.getFontScaledHeight(mContext,
- com.android.internal.R.dimen.notification_collapsed_height_with_summarization);
+ com.android.internal.R.dimen.notification_min_height);
mMaxExpandedHeight = NotificationUtils.getFontScaledHeight(mContext,
R.dimen.notification_max_height);
mMaxExpandedHeightForPromotedOngoing = NotificationUtils.getFontScaledHeight(mContext,
@@ -2248,6 +2264,11 @@
mEntry = entry;
}
+ @VisibleForTesting
+ protected void setEntryAdapter(EntryAdapter entry) {
+ mEntryAdapter = entry;
+ }
+
private final Runnable mExpireRecentlyAlertedFlag = () -> applyAudiblyAlertedRecently(false);
private void applyAudiblyAlertedRecently(boolean audiblyAlertedRecently) {
@@ -2485,7 +2506,7 @@
mTranslateableViews.get(i).setTranslationX(0);
}
invalidateOutline();
- getEntry().getIcons().getShelfIcon().setScrollX(0);
+ getShelfIcon().setScrollX(0);
}
if (mMenuRow != null) {
@@ -2604,7 +2625,7 @@
// In order to keep the shelf in sync with this swiping, we're simply translating
// it's icon by the same amount. The translation is already being used for the normal
// positioning, so we can use the scrollX instead.
- getEntry().getIcons().getShelfIcon().setScrollX((int) -translationX);
+ getShelfIcon().setScrollX((int) -translationX);
}
if (mMenuRow != null && mMenuRow.getMenuView() != null) {
@@ -2745,7 +2766,7 @@
top = params.getTop();
}
int actualHeight = params.getBottom() - top;
- setActualHeight(actualHeight);
+ setFinalActualHeight(actualHeight);
int notificationStackTop = params.getNotificationParentTop();
top -= notificationStackTop;
@@ -2831,7 +2852,11 @@
@Override
public @NonNull StatusBarIconView getShelfIcon() {
- return getEntry().getIcons().getShelfIcon();
+ if (NotificationBundleUi.isEnabled()) {
+ return getEntryAdapter().getIcons().getShelfIcon();
+ } else {
+ return mEntry.getIcons().getShelfIcon();
+ }
}
@Override
@@ -3060,8 +3085,11 @@
* except for legacy use cases.
*/
public boolean canShowHeadsUp() {
+ boolean canEntryHun = NotificationBundleUi.isEnabled()
+ ? mEntryAdapter.canPeek()
+ : mEntry.isStickyAndNotDemoted();
if (mOnKeyguard && !isDozing() && !isBypassEnabled() &&
- (!mEntry.isStickyAndNotDemoted()
+ (!canEntryHun
|| (!mIgnoreLockscreenConstraints && mSaveSpaceOnLockscreen))) {
return false;
}
@@ -3100,7 +3128,11 @@
}
if (!mIsSummaryWithChildren && wasSummary) {
// Reset the 'when' once the row stops being a summary
- mPublicLayout.setNotificationWhen(mEntry.getSbn().getNotification().getWhen());
+ if (NotificationBundleUi.isEnabled()) {
+ mPublicLayout.setNotificationWhen(mEntryAdapter.getWhen());
+ } else {
+ mPublicLayout.setNotificationWhen(mEntry.getSbn().getNotification().getWhen());
+ }
}
getShowingLayout().updateBackgroundColor(false /* animate */);
mPrivateLayout.updateExpandButtons(isExpandable());
@@ -3304,7 +3336,7 @@
}
resetAllContentAlphas();
} else {
- mLogger.logSkipResetAllContentAlphas(getEntry());
+ mLogger.logSkipResetAllContentAlphas(mLoggingKey);
}
mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
updateChildrenVisibility();
@@ -3369,7 +3401,7 @@
*/
@Override
public boolean canExpandableViewBeDismissed() {
- if (areGutsExposed() || !mEntry.hasFinishedInitialization()) {
+ if (areGutsExposed() || !hasFinishedInitialization()) {
return false;
}
return canViewBeDismissed();
@@ -3393,7 +3425,12 @@
* clearability see {@link NotificationEntry#isClearable()}.
*/
public boolean canViewBeCleared() {
- return mEntry.isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
+ if (NotificationBundleUi.isEnabled()) {
+ return mEntryAdapter.isClearable()
+ && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
+ } else {
+ return mEntry.isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
+ }
}
private boolean shouldShowPublic() {
@@ -3458,7 +3495,7 @@
@Override
public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear,
Runnable onFinishRunnable) {
- mLogger.logStartAppearAnimation(getEntry(), /* isAppear = */ true);
+ mLogger.logStartAppearAnimation(mLoggingKey, /* isAppear = */ true);
super.performAddAnimation(delay, duration, isHeadsUpAppear, onFinishRunnable);
}
@@ -3471,7 +3508,7 @@
Runnable onStartedRunnable,
Runnable onFinishedRunnable,
AnimatorListenerAdapter animationListener, ClipSide clipSide) {
- mLogger.logStartAppearAnimation(getEntry(), /* isAppear = */ false);
+ mLogger.logStartAppearAnimation(mLoggingKey, /* isAppear = */ false);
if (mMenuRow != null && mMenuRow.isMenuVisible()) {
Animator anim = getTranslateViewAnimator(0f, null /* listener */);
if (anim != null) {
@@ -3501,20 +3538,20 @@
@Override
protected void onAppearAnimationStarted(boolean isAppear) {
- mLogger.logAppearAnimationStarted(getEntry(), /* isAppear = */ isAppear);
+ mLogger.logAppearAnimationStarted(mLoggingKey, /* isAppear = */ isAppear);
super.onAppearAnimationStarted(isAppear);
}
@Override
protected void onAppearAnimationSkipped(boolean isAppear) {
- mLogger.logAppearAnimationSkipped(getEntry(), /* isAppear = */ isAppear);
+ mLogger.logAppearAnimationSkipped(mLoggingKey, /* isAppear = */ isAppear);
super.onAppearAnimationSkipped(isAppear);
}
@Override
protected void onAppearAnimationFinished(boolean wasAppearing, boolean cancelled) {
mLogger.logAppearAnimationFinished(
- /* entry = */ getEntry(),
+ /* entry = */ mLoggingKey,
/* isAppear = */ wasAppearing,
/* cancelled = */ cancelled
);
@@ -3535,13 +3572,13 @@
@Override
public void cancelAppearDrawing() {
- mLogger.logCancelAppearDrawing(getEntry(), isDrawingAppearAnimation());
+ mLogger.logCancelAppearDrawing(mLoggingKey, isDrawingAppearAnimation());
super.cancelAppearDrawing();
}
@Override
public void resetAllContentAlphas() {
- mLogger.logResetAllContentAlphas(getEntry());
+ mLogger.logResetAllContentAlphas(mLoggingKey);
mPrivateLayout.setAlpha(1f);
mPrivateLayout.setLayerType(LAYER_TYPE_NONE, null);
mPublicLayout.setAlpha(1f);
@@ -4070,6 +4107,7 @@
}
public boolean isMediaRow() {
+ NotificationBundleUi.assertInLegacyMode();
return mEntry.getSbn().getNotification().isMediaNotification();
}
@@ -4192,7 +4230,11 @@
public void dump(PrintWriter pwOriginal, String[] args) {
IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
// Skip super call; dump viewState ourselves
- pw.println("Notification: " + mEntry.getKey());
+ if (NotificationBundleUi.isEnabled()) {
+ pw.println("Notification: " + mEntryAdapter.getKey());
+ } else {
+ pw.println("Notification: " + mEntry.getKey());
+ }
DumpUtilsKt.withIncreasedIndent(pw, () -> {
pw.println(this);
pw.print("visibility: " + getVisibility());
@@ -4223,6 +4265,7 @@
pw.print(", isPinned: " + isPinned());
pw.print(", expandedWhenPinned: " + mExpandedWhenPinned);
pw.print(", isMinimized: " + mIsMinimized);
+ pw.print(", isAboveShelf: " + isAboveShelf());
pw.println();
if (NotificationContentView.INCLUDE_HEIGHTS_TO_DUMP) {
@@ -4313,13 +4356,13 @@
private void logKeepInParentChildDetached(ExpandableNotificationRow child) {
if (mLogger != null) {
- mLogger.logKeepInParentChildDetached(child.getEntry(), getEntry());
+ mLogger.logKeepInParentChildDetached(child.getLoggingKey(), mLoggingKey);
}
}
private void logSkipAttachingKeepInParentChild(ExpandableNotificationRow child) {
if (mLogger != null) {
- mLogger.logSkipAttachingKeepInParentChild(child.getEntry(), getEntry());
+ mLogger.logSkipAttachingKeepInParentChild(child.getLoggingKey(), mLoggingKey);
}
}
@@ -4375,17 +4418,17 @@
}
if (transientContainer instanceof NotificationChildrenContainer) {
mLogger.logRemoveTransientFromContainer(
- /* childEntry = */ getEntry(),
+ /* childEntry = */ mLoggingKey,
/* containerEntry = */ ((NotificationChildrenContainer) transientContainer)
- .getContainingNotification().getEntry()
+ .getContainingNotification().getLoggingKey()
);
} else if (transientContainer instanceof NotificationStackScrollLayout) {
mLogger.logRemoveTransientFromNssl(
- /* childEntry = */ getEntry()
+ /* childEntry = */ mLoggingKey
);
} else {
mLogger.logRemoveTransientFromViewGroup(
- /* childEntry = */ getEntry(),
+ /* childEntry = */ mLoggingKey,
/* containerView = */ transientContainer
);
}
@@ -4403,7 +4446,7 @@
if (mLogger == null) {
return;
}
- mLogger.logAddTransientRow(row.getEntry(), getEntry(), index);
+ mLogger.logAddTransientRow(row.getLoggingKey(), mLoggingKey, index);
}
@Override
@@ -4418,6 +4461,6 @@
if (mLogger == null) {
return;
}
- mLogger.logRemoveTransientRow(row.getEntry(), getEntry());
+ mLogger.logRemoveTransientRow(row.getLoggingKey(), mLoggingKey);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 6262303..07711b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -56,6 +56,7 @@
import com.android.systemui.statusbar.notification.row.dagger.AppName;
import com.android.systemui.statusbar.notification.row.dagger.NotificationKey;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
+import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationRowStatsLogger;
@@ -145,38 +146,38 @@
@Override
public void logKeepInParentChildDetached(
- NotificationEntry child,
- NotificationEntry oldParent
+ String child,
+ String oldParent
) {
mLogBufferLogger.logKeepInParentChildDetached(child, oldParent);
}
@Override
public void logSkipAttachingKeepInParentChild(
- NotificationEntry child,
- NotificationEntry newParent
+ String child,
+ String newParent
) {
mLogBufferLogger.logSkipAttachingKeepInParentChild(child, newParent);
}
@Override
public void logRemoveTransientFromContainer(
- NotificationEntry childEntry,
- NotificationEntry containerEntry
+ String childEntry,
+ String containerEntry
) {
mLogBufferLogger.logRemoveTransientFromContainer(childEntry, containerEntry);
}
@Override
public void logRemoveTransientFromNssl(
- NotificationEntry childEntry
+ String childEntry
) {
mLogBufferLogger.logRemoveTransientFromNssl(childEntry);
}
@Override
public void logRemoveTransientFromViewGroup(
- NotificationEntry childEntry,
+ String childEntry,
ViewGroup containerView
) {
mLogBufferLogger.logRemoveTransientFromViewGroup(childEntry, containerView);
@@ -184,8 +185,8 @@
@Override
public void logAddTransientRow(
- NotificationEntry childEntry,
- NotificationEntry containerEntry,
+ String childEntry,
+ String containerEntry,
int index
) {
mLogBufferLogger.logAddTransientRow(childEntry, containerEntry, index);
@@ -193,48 +194,48 @@
@Override
public void logRemoveTransientRow(
- NotificationEntry childEntry,
- NotificationEntry containerEntry
+ String childEntry,
+ String containerEntry
) {
mLogBufferLogger.logRemoveTransientRow(childEntry, containerEntry);
}
@Override
public void logResetAllContentAlphas(
- NotificationEntry entry
+ String entry
) {
mLogBufferLogger.logResetAllContentAlphas(entry);
}
@Override
public void logSkipResetAllContentAlphas(
- NotificationEntry entry
+ String entry
) {
mLogBufferLogger.logSkipResetAllContentAlphas(entry);
}
@Override
- public void logStartAppearAnimation(NotificationEntry entry, boolean isAppear) {
+ public void logStartAppearAnimation(String entry, boolean isAppear) {
mLogBufferLogger.logStartAppearAnimation(entry, isAppear);
}
@Override
- public void logCancelAppearDrawing(NotificationEntry entry, boolean wasDrawing) {
+ public void logCancelAppearDrawing(String entry, boolean wasDrawing) {
mLogBufferLogger.logCancelAppearDrawing(entry, wasDrawing);
}
@Override
- public void logAppearAnimationStarted(NotificationEntry entry, boolean isAppear) {
+ public void logAppearAnimationStarted(String entry, boolean isAppear) {
mLogBufferLogger.logAppearAnimationStarted(entry, isAppear);
}
@Override
- public void logAppearAnimationSkipped(NotificationEntry entry, boolean isAppear) {
+ public void logAppearAnimationSkipped(String entry, boolean isAppear) {
mLogBufferLogger.logAppearAnimationSkipped(entry, isAppear);
}
@Override
- public void logAppearAnimationFinished(NotificationEntry entry, boolean isAppear,
+ public void logAppearAnimationFinished(String entry, boolean isAppear,
boolean cancelled) {
mLogBufferLogger.logAppearAnimationFinished(entry, isAppear, cancelled);
}
@@ -373,7 +374,11 @@
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
- mView.getEntry().setInitializationTime(mClock.elapsedRealtime());
+ if (NotificationBundleUi.isEnabled()) {
+ mView.setInitializationTime(mClock.elapsedRealtime());
+ } else {
+ mView.getEntry().setInitializationTime(mClock.elapsedRealtime());
+ }
mPluginManager.addPluginListener(mView,
NotificationMenuRowPlugin.class, false /* Allow multiple */);
if (!SceneContainerFlag.isEnabled()) {
@@ -405,7 +410,7 @@
@Override
@NonNull
public String getNodeLabel() {
- return logKey(mView.getEntry());
+ return NotificationBundleUi.isEnabled() ? mView.getLoggingKey() : logKey(mView.getEntry());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 2bc4874..da664f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.Flags.notificationColorUpdateLogger;
+import static com.android.systemui.Flags.physicalNotificationMovement;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
@@ -24,6 +25,7 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.FloatProperty;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.view.View;
@@ -41,6 +43,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.PhysicsProperty;
import com.android.systemui.statusbar.notification.Roundable;
import com.android.systemui.statusbar.notification.RoundableState;
import com.android.systemui.statusbar.notification.headsup.PinnedStatus;
@@ -58,6 +61,20 @@
* An abstract view for expandable views.
*/
public abstract class ExpandableView extends FrameLayout implements Dumpable, Roundable {
+ public static final int TAG_ANIMATOR_HEIGHT = R.id.height_animator_tag;
+ public static final PhysicsProperty HEIGHT_PROPERTY = new PhysicsProperty(TAG_ANIMATOR_HEIGHT,
+ new FloatProperty<>("ActualHeight") {
+
+ @Override
+ public Float get(View view) {
+ return (float) ((ExpandableView) view).getActualHeight();
+ }
+
+ @Override
+ public void setValue(@NonNull View view, float value) {
+ ((ExpandableView) view).setActualHeight((int) value);
+ }
+ });
private static final String TAG = "ExpandableView";
/** whether the dump() for this class should include verbose details */
protected static final boolean DUMP_VERBOSE = Compile.IS_DEBUG
@@ -84,7 +101,8 @@
protected float mContentTransformationAmount;
protected boolean mIsLastChild;
protected int mContentShift;
- @NonNull private final ExpandableViewState mViewState;
+ @NonNull
+ private final ExpandableViewState mViewState;
private float mContentTranslation;
protected boolean mLastInSection;
protected boolean mFirstInSection;
@@ -205,7 +223,7 @@
MeasureSpec.EXACTLY);
}
child.measure(getChildMeasureSpec(
- widthMeasureSpec, viewHorizontalPadding, layoutParams.width),
+ widthMeasureSpec, viewHorizontalPadding, layoutParams.width),
childHeightSpec);
int childHeight = child.getMeasuredHeight();
maxChildHeight = Math.max(maxChildHeight, childHeight);
@@ -223,7 +241,7 @@
// Now that we know our own height, measure the children that are MATCH_PARENT
for (View child : mMatchParentViews) {
child.measure(getChildMeasureSpec(
- widthMeasureSpec, viewHorizontalPadding, child.getLayoutParams().width),
+ widthMeasureSpec, viewHorizontalPadding, child.getLayoutParams().width),
exactlyOwnHeightSpec);
}
mMatchParentViews.clear();
@@ -269,12 +287,29 @@
}
/**
+ * Sets the final value of the actual height, which is to be applied immediately without
+ * animation. This may be different than the current value if we're animating away an offset.
+ */
+ public void setFinalActualHeight(int childHeight) {
+ if (physicalNotificationMovement()) {
+ HEIGHT_PROPERTY.setFinalValue(this, childHeight);
+ } else {
+ setActualHeight(childHeight);
+ }
+ }
+
+ /**
+ * Once the physical notification movement flag is enabled, don't use
+ * this directly as a public method since it may not update the property values and misbehave
+ * during animations. Use #setFinalActualHeight instead.
+ *
* Sets the actual height of this notification. This is different than the laid out
* {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
*
- * @param actualHeight The height of this notification.
+ * @param actualHeight The height of this notification.
* @param notifyListeners Whether the listener should be informed about the change.
*/
+ @Deprecated
public void setActualHeight(int actualHeight, boolean notifyListeners) {
if (mActualHeight != actualHeight) {
mActualHeight = actualHeight;
@@ -285,7 +320,7 @@
}
}
- public void setActualHeight(int actualHeight) {
+ protected void setActualHeight(int actualHeight) {
setActualHeight(actualHeight, true /* notifyListeners */);
}
@@ -748,7 +783,8 @@
*
* @return the ExpandableView's view state.
*/
- @NonNull public ExpandableViewState getViewState() {
+ @NonNull
+ public ExpandableViewState getViewState() {
return mViewState;
}
@@ -840,9 +876,10 @@
* Set how much this notification is transformed into the shelf.
*
* @param contentTransformationAmount A value from 0 to 1 indicating how much we are transformed
- * to the content away
- * @param isLastChild is this the last child in the list. If true, then the transformation is
- * different since its content fades out.
+ * to the content away
+ * @param isLastChild is this the last child in the list. If true, then the
+ * transformation is
+ * different since its content fades out.
*/
public void setContentTransformationAmount(float contentTransformationAmount,
boolean isLastChild) {
@@ -971,8 +1008,9 @@
public interface OnHeightChangedListener {
/**
- * @param view the view for which the height changed, or {@code null} if just the top
- * padding or the padding between the elements changed
+ * @param view the view for which the height changed, or {@code null} if just the
+ * top
+ * padding or the padding between the elements changed
* @param needsAnimation whether the view height needs to be animated
*/
void onHeightChanged(ExpandableView view, boolean needsAnimation);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index dd3a9c9..33c36d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row;
+import static com.android.systemui.Flags.notificationRowTransparency;
import static com.android.systemui.util.ColorUtilKt.hexColorString;
import android.content.Context;
@@ -23,6 +24,7 @@
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
@@ -34,8 +36,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.Dumpable;
+import com.android.systemui.common.shared.colors.SurfaceEffectColors;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.shared.NotificationAddXOnHoverToDismiss;
import com.android.systemui.util.DrawableDumpKt;
@@ -69,6 +73,7 @@
private final ColorStateList mLightColoredStatefulColors;
private final ColorStateList mDarkColoredStatefulColors;
private final int mNormalColor;
+ private boolean mBgIsColorized = false;
private final int convexR = 9;
private final int concaveR = 22;
@@ -82,8 +87,12 @@
R.color.notification_state_color_light);
mDarkColoredStatefulColors = getResources().getColorStateList(
R.color.notification_state_color_dark);
- mNormalColor = mContext.getColor(
- com.android.internal.R.color.materialColorSurfaceContainerHigh);
+ if (notificationRowTransparency()) {
+ mNormalColor = SurfaceEffectColors.surfaceEffect1(getResources());
+ } else {
+ mNormalColor = mContext.getColor(
+ com.android.internal.R.color.materialColorSurfaceContainerHigh);
+ }
mFocusOverlayStroke = getResources().getDimension(R.dimen.notification_focus_stroke_width);
}
@@ -132,6 +141,21 @@
}
}
+ /**
+ * A way to tell whether the background has been colorized.
+ */
+ public boolean isColorized() {
+ return mBgIsColorized;
+ }
+
+ /**
+ * A way to inform this class whether the background has been colorized.
+ * We need to know this, in order to *not* override that color.
+ */
+ public void setBgIsColorized(boolean b) {
+ mBgIsColorized = b;
+ }
+
private Path calculateDismissButtonCutoutPath(Rect backgroundBounds) {
// TODO(b/365585705): Adapt to RTL after the UX design is finalized.
@@ -280,7 +304,7 @@
setCustomBackground(d);
}
- private Drawable getBaseBackgroundLayer() {
+ public Drawable getBaseBackgroundLayer() {
return ((LayerDrawable) mBackground).getDrawable(0);
}
@@ -288,11 +312,27 @@
return ((LayerDrawable) mBackground).getDrawable(1);
}
+ private void updateBaseLayerColor() {
+ // BG base layer being a drawable, there isn't a method like setColor() to color it.
+ // Instead, we set a color filter that essentially replaces every pixel of the drawable.
+ // For non-colorized notifications, this function specifies a new color token.
+ // For colorized notifications, this uses a color that matches the tint color at 90% alpha.
+ getBaseBackgroundLayer().setColorFilter(
+ new PorterDuffColorFilter(
+ isColorized()
+ ? ColorUtils.setAlphaComponent(mTintColor, (int) (255 * 0.9f))
+ : SurfaceEffectColors.surfaceEffect1(getResources()),
+ PorterDuff.Mode.SRC)); // SRC operator discards the drawable's color+alpha
+ }
+
public void setTint(int tintColor) {
Drawable baseLayer = getBaseBackgroundLayer();
baseLayer.mutate().setTintMode(PorterDuff.Mode.SRC_ATOP);
baseLayer.setTint(tintColor);
mTintColor = tintColor;
+ if (notificationRowTransparency()) {
+ updateBaseLayerColor();
+ }
setStatefulColors();
invalidate();
}
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 0c1dd2e..c31f4ad 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
@@ -247,7 +247,7 @@
entry.getRanking().getSummarization());
} else {
result.mPublicInflatedSingleLineViewModel =
- SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+ SingleLineViewInflater.inflatePublicSingleLineViewModel(
row.getContext(),
isConversation
);
@@ -509,7 +509,7 @@
new Notification.Builder(packageContext, original.getChannelId());
redacted.setContentTitle(original.extras.getCharSequence(Notification.EXTRA_TITLE));
CharSequence redactedMessage = systemUiContext.getString(
- R.string.redacted_notification_single_line_text
+ R.string.redacted_otp_notification_single_line_text
);
redacted.setWhen(original.getWhen());
@@ -1362,7 +1362,7 @@
);
} else {
result.mPublicInflatedSingleLineViewModel =
- SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+ SingleLineViewInflater.inflatePublicSingleLineViewModel(
mContext,
isConversation
);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 6e638f5..9a75253 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -73,6 +73,7 @@
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.row.icon.AppIconProvider;
import com.android.systemui.statusbar.notification.row.icon.NotificationIconStyleProvider;
+import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -436,7 +437,9 @@
onNasFeedbackClick,
mUiEventLogger,
mDeviceProvisionedController.isDeviceProvisioned(),
- row.getIsNonblockable(),
+ NotificationBundleUi.isEnabled()
+ ? !row.getEntry().isBlockable()
+ : row.getIsNonblockable(),
mHighPriorityProvider.isHighPriority(row.getEntry()),
mAssistantFeedbackController,
mMetricsLogger,
@@ -480,7 +483,9 @@
row.getEntry(),
onSettingsClick,
mDeviceProvisionedController.isDeviceProvisioned(),
- row.getIsNonblockable());
+ NotificationBundleUi.isEnabled()
+ ? !row.getEntry().isBlockable()
+ : row.getIsNonblockable());
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index b96b224a..ab382df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -186,7 +186,7 @@
}
@Override
- public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
+ public void createMenu(ViewGroup parent) {
mParent = (ExpandableNotificationRow) parent;
createMenuViews(true /* resetState */);
}
@@ -227,7 +227,7 @@
}
@Override
- public void onNotificationUpdated(StatusBarNotification sbn) {
+ public void onNotificationUpdated() {
if (mMenuContainer == null) {
// Menu hasn't been created yet, no need to do anything.
return;
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 761d3fe..b9a3594 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
@@ -754,7 +754,7 @@
summarization = null,
)
} else {
- SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+ SingleLineViewInflater.inflatePublicSingleLineViewModel(
systemUiContext,
entry.ranking.isConversation,
)
@@ -792,7 +792,7 @@
val redacted = Notification.Builder(packageContext, original.channelId)
redacted.setContentTitle(original.extras.getCharSequence(Notification.EXTRA_TITLE))
val redactedMessage =
- sysUiContext.getString(R.string.redacted_notification_single_line_text)
+ sysUiContext.getString(R.string.redacted_otp_notification_single_line_text)
if (originalStyle is MessagingStyle) {
val newStyle = MessagingStyle(originalStyle.user)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
index 9e1c974..dad57a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
@@ -22,8 +22,6 @@
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.NotificationLog
import com.android.systemui.log.dagger.NotificationRenderLog
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.statusbar.notification.stack.MagneticNotificationRowManagerImpl
import javax.inject.Inject
@@ -33,60 +31,60 @@
@NotificationLog private val buffer: LogBuffer,
@NotificationRenderLog private val notificationRenderBuffer: LogBuffer,
) {
- fun logKeepInParentChildDetached(child: NotificationEntry, oldParent: NotificationEntry?) {
+ fun logKeepInParentChildDetached(child: String, oldParent: String?) {
buffer.log(
TAG,
LogLevel.DEBUG,
{
- str1 = child.logKey
- str2 = oldParent.logKey
+ str1 = child
+ str2 = oldParent
},
{ "Detach child $str1 kept in parent $str2" },
)
}
- fun logSkipAttachingKeepInParentChild(child: NotificationEntry, newParent: NotificationEntry?) {
+ fun logSkipAttachingKeepInParentChild(child: String, newParent: String?) {
buffer.log(
TAG,
LogLevel.WARNING,
{
- str1 = child.logKey
- str2 = newParent.logKey
+ str1 = child
+ str2 = newParent
},
{ "Skipping to attach $str1 to $str2, because it still flagged to keep in parent" },
)
}
fun logRemoveTransientFromContainer(
- childEntry: NotificationEntry,
- containerEntry: NotificationEntry,
+ childEntry: String,
+ containerEntry: String,
) {
notificationRenderBuffer.log(
TAG,
LogLevel.INFO,
{
- str1 = childEntry.logKey
- str2 = containerEntry.logKey
+ str1 = childEntry
+ str2 = containerEntry
},
{ "RemoveTransientRow from ChildrenContainer: childKey: $str1 -- containerKey: $str2" },
)
}
- fun logRemoveTransientFromNssl(childEntry: NotificationEntry) {
+ fun logRemoveTransientFromNssl(childEntry: String) {
notificationRenderBuffer.log(
TAG,
LogLevel.INFO,
- { str1 = childEntry.logKey },
+ { str1 = childEntry },
{ "RemoveTransientRow from Nssl: childKey: $str1" },
)
}
- fun logRemoveTransientFromViewGroup(childEntry: NotificationEntry, containerView: ViewGroup) {
+ fun logRemoveTransientFromViewGroup(childEntry: String, containerView: ViewGroup) {
notificationRenderBuffer.log(
TAG,
LogLevel.WARNING,
{
- str1 = childEntry.logKey
+ str1 = childEntry
str2 = containerView.toString()
},
{ "RemoveTransientRow from other ViewGroup: childKey: $str1 -- ViewGroup: $str2" },
@@ -94,94 +92,94 @@
}
fun logAddTransientRow(
- childEntry: NotificationEntry,
- containerEntry: NotificationEntry,
+ childEntry: String,
+ containerEntry: String,
index: Int,
) {
notificationRenderBuffer.log(
TAG,
LogLevel.ERROR,
{
- str1 = childEntry.logKey
- str2 = containerEntry.logKey
+ str1 = childEntry
+ str2 = containerEntry
int1 = index
},
{ "addTransientRow to row: childKey: $str1 -- containerKey: $str2 -- index: $int1" },
)
}
- fun logRemoveTransientRow(childEntry: NotificationEntry, containerEntry: NotificationEntry) {
+ fun logRemoveTransientRow(childEntry: String, containerEntry: String) {
notificationRenderBuffer.log(
TAG,
LogLevel.ERROR,
{
- str1 = childEntry.logKey
- str2 = containerEntry.logKey
+ str1 = childEntry
+ str2 = containerEntry
},
{ "removeTransientRow from row: childKey: $str1 -- containerKey: $str2" },
)
}
- fun logResetAllContentAlphas(entry: NotificationEntry) {
+ fun logResetAllContentAlphas(entry: String) {
notificationRenderBuffer.log(
TAG,
LogLevel.INFO,
- { str1 = entry.logKey },
+ { str1 = entry },
{ "resetAllContentAlphas: $str1" },
)
}
- fun logSkipResetAllContentAlphas(entry: NotificationEntry) {
+ fun logSkipResetAllContentAlphas(entry: String) {
notificationRenderBuffer.log(
TAG,
LogLevel.INFO,
- { str1 = entry.logKey },
+ { str1 = entry },
{ "Skip resetAllContentAlphas: $str1" },
)
}
- fun logStartAppearAnimation(entry: NotificationEntry, isAppear: Boolean) {
+ fun logStartAppearAnimation(entry: String, isAppear: Boolean) {
notificationRenderBuffer.log(
TAG,
LogLevel.DEBUG,
{
- str1 = entry.logKey
+ str1 = entry
bool1 = isAppear
},
{ "startAppearAnimation childKey: $str1 isAppear:$bool1" },
)
}
- fun logCancelAppearDrawing(entry: NotificationEntry, wasDrawing: Boolean) {
+ fun logCancelAppearDrawing(entry: String, wasDrawing: Boolean) {
notificationRenderBuffer.log(
TAG,
LogLevel.WARNING,
{
- str1 = entry.logKey
+ str1 = entry
bool1 = wasDrawing
},
{ "cancelAppearDrawing childKey: $str1 wasDrawing:$bool1" },
)
}
- fun logAppearAnimationStarted(entry: NotificationEntry, isAppear: Boolean) {
+ fun logAppearAnimationStarted(entry: String, isAppear: Boolean) {
notificationRenderBuffer.log(
TAG,
LogLevel.DEBUG,
{
- str1 = entry.logKey
+ str1 = entry
bool1 = isAppear
},
{ "onAppearAnimationStarted childKey: $str1 isAppear:$bool1" },
)
}
- fun logAppearAnimationSkipped(entry: NotificationEntry, isAppear: Boolean) {
+ fun logAppearAnimationSkipped(entry: String, isAppear: Boolean) {
notificationRenderBuffer.log(
TAG,
LogLevel.WARNING,
{
- str1 = entry.logKey
+ str1 = entry
bool1 = isAppear
},
{ "Skipped an appear animation childKey: $str1 isAppear:$bool1" },
@@ -189,7 +187,7 @@
}
fun logAppearAnimationFinished(
- entry: NotificationEntry,
+ entry: String,
isAppear: Boolean,
cancelled: Boolean,
) {
@@ -197,7 +195,7 @@
TAG,
LogLevel.DEBUG,
{
- str1 = entry.logKey
+ str1 = entry
bool1 = isAppear
bool2 = cancelled
},
@@ -207,13 +205,13 @@
fun logMagneticAndRoundableTargetsNotSet(
state: MagneticNotificationRowManagerImpl.State,
- entry: NotificationEntry,
+ entry: String,
) {
buffer.log(
TAG,
LogLevel.ERROR,
{
- str1 = entry.logKey
+ str1 = entry
str2 = state.name
},
{ "Failed to set magnetic and roundable targets for $str1 on state $str2." },
@@ -222,13 +220,13 @@
fun logMagneticRowTranslationNotSet(
state: MagneticNotificationRowManagerImpl.State,
- entry: NotificationEntry,
+ entry: String,
) {
buffer.log(
TAG,
LogLevel.ERROR,
{
- str1 = entry.logKey
+ str1 = entry
str2 = state.name
},
{ "Failed to set magnetic row translation for $str1 on state $str2." },
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 b3c8f22..ea73b4b 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
@@ -71,7 +71,7 @@
var contentText =
if (redactText) {
systemUiContext.getString(
- com.android.systemui.res.R.string.redacted_notification_single_line_text
+ com.android.systemui.res.R.string.redacted_otp_notification_single_line_text
)
} else {
HybridGroupManager.resolveText(notification)
@@ -120,7 +120,7 @@
}
@JvmStatic
- fun inflateRedactedSingleLineViewModel(
+ fun inflatePublicSingleLineViewModel(
context: Context,
isConversation: Boolean = false,
): SingleLineViewModel {
@@ -144,7 +144,7 @@
com.android.systemui.res.R.string.redacted_notification_single_line_title
),
context.getString(
- com.android.systemui.res.R.string.redacted_notification_single_line_text
+ com.android.systemui.res.R.string.public_notification_single_line_text
),
conversationData,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
index 2d94694..e887e25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row.wrapper
+import android.app.Flags.notificationsRedesignTemplates
import android.content.Context
import android.view.View
import com.android.internal.widget.CachingIconView
@@ -25,17 +26,13 @@
import com.android.systemui.statusbar.notification.NotificationUtils
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
-/**
- * Wraps a notification containing a call template
- */
-class NotificationCallTemplateViewWrapper constructor(
- ctx: Context,
- view: View,
- row: ExpandableNotificationRow
-) : NotificationTemplateViewWrapper(ctx, view, row) {
+/** Wraps a notification containing a call template */
+class NotificationCallTemplateViewWrapper
+constructor(ctx: Context, view: View, row: ExpandableNotificationRow) :
+ NotificationTemplateViewWrapper(ctx, view, row) {
private val minHeightWithActions: Int =
- NotificationUtils.getFontScaledHeight(ctx, R.dimen.notification_max_height)
+ NotificationUtils.getFontScaledHeight(ctx, R.dimen.notification_max_height)
private val callLayout: CallLayout = view as CallLayout
private lateinit var conversationIconContainer: View
@@ -48,13 +45,17 @@
private fun resolveViews() {
with(callLayout) {
conversationIconContainer =
- requireViewById(com.android.internal.R.id.conversation_icon_container)
+ requireViewById(com.android.internal.R.id.conversation_icon_container)
conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon)
conversationBadgeBg =
- requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
+ requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
expandBtn = requireViewById(com.android.internal.R.id.expand_button)
appName = requireViewById(com.android.internal.R.id.app_name_text)
- conversationTitleView = requireViewById(com.android.internal.R.id.conversation_text)
+ conversationTitleView =
+ requireViewById(
+ if (notificationsRedesignTemplates()) com.android.internal.R.id.title
+ else com.android.internal.R.id.conversation_text
+ )
}
}
@@ -68,20 +69,12 @@
override fun updateTransformedTypes() {
// This also clears the existing types
super.updateTransformedTypes()
- addTransformedViews(
- appName,
- conversationTitleView
- )
- addViewsTransformingToSimilar(
- conversationIconView,
- conversationBadgeBg,
- expandBtn
- )
+ addTransformedViews(appName, conversationTitleView)
+ addViewsTransformingToSimilar(conversationIconView, conversationBadgeBg, expandBtn)
}
override fun disallowSingleClick(x: Float, y: Float): Boolean {
- val isOnExpandButton = expandBtn.visibility == View.VISIBLE &&
- isOnView(expandBtn, x, y)
+ val isOnExpandButton = expandBtn.visibility == View.VISIBLE && isOnView(expandBtn, x, y)
return isOnExpandButton || super.disallowSingleClick(x, y)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
index 9d13ab5..6a96fba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
@@ -17,10 +17,12 @@
package com.android.systemui.statusbar.notification.row.wrapper
import android.app.Flags
+import android.app.Flags.notificationsRedesignTemplates
import android.content.Context
import android.graphics.drawable.AnimatedImageDrawable
import android.view.View
import android.view.ViewGroup
+import androidx.core.view.isVisible
import com.android.internal.widget.CachingIconView
import com.android.internal.widget.ConversationLayout
import com.android.internal.widget.MessagingGroup
@@ -53,8 +55,8 @@
private lateinit var badgeIconView: NotificationRowIconView
private lateinit var conversationBadgeBg: View
private lateinit var expandBtn: View
- private lateinit var expandBtnContainer: View
- private lateinit var imageMessageContainer: ViewGroup
+ private var expandBtnContainer: View? = null
+ private var imageMessageContainer: ViewGroup? = null
private lateinit var messageContainers: ArrayList<MessagingGroup>
private lateinit var messagingLinearLayout: MessagingLinearLayout
private lateinit var conversationTitleView: View
@@ -78,10 +80,14 @@
conversationBadgeBg =
requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
expandBtn = requireViewById(com.android.internal.R.id.expand_button)
- expandBtnContainer = requireViewById(com.android.internal.R.id.expand_button_container)
+ expandBtnContainer = findViewById(com.android.internal.R.id.expand_button_container)
importanceRing = requireViewById(com.android.internal.R.id.conversation_icon_badge_ring)
appName = requireViewById(com.android.internal.R.id.app_name_text)
- conversationTitleView = requireViewById(com.android.internal.R.id.conversation_text)
+ conversationTitleView =
+ requireViewById(
+ if (notificationsRedesignTemplates()) com.android.internal.R.id.title
+ else com.android.internal.R.id.conversation_text
+ )
facePileTop = findViewById(com.android.internal.R.id.conversation_face_pile_top)
facePileBottom = findViewById(com.android.internal.R.id.conversation_face_pile_bottom)
facePileBottomBg =
@@ -133,11 +139,21 @@
expandable: Boolean,
onClickListener: View.OnClickListener,
requestLayout: Boolean,
- ) = conversationLayout.updateExpandability(expandable, onClickListener)
+ ) {
+ if (notificationsRedesignTemplates()) {
+ super.updateExpandability(expandable, onClickListener, requestLayout)
+ } else {
+ conversationLayout.updateExpandability(expandable, onClickListener)
+ }
+ }
override fun disallowSingleClick(x: Float, y: Float): Boolean {
val isOnExpandButton =
- expandBtnContainer.visibility == View.VISIBLE && isOnView(expandBtnContainer, x, y)
+ if (notificationsRedesignTemplates()) {
+ expandBtn.isVisible && isOnView(expandBtn, x, y)
+ } else {
+ expandBtnContainer?.visibility == View.VISIBLE && isOnView(expandBtnContainer, x, y)
+ }
return isOnExpandButton || super.disallowSingleClick(x, y)
}
@@ -158,7 +174,8 @@
// and the top level image message container.
val containers =
messageContainers.asSequence().map { it.messageContainer } +
- sequenceOf(imageMessageContainer)
+ if (notificationsRedesignTemplates()) emptySequence()
+ else sequenceOf(imageMessageContainer!!)
val drawables =
containers
.flatMap { it.children }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
index 00b9aa4..3d60092 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
@@ -23,6 +23,8 @@
import android.view.View;
import android.view.animation.Interpolator;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+
import java.util.function.Consumer;
/**
@@ -77,6 +79,34 @@
}
/**
+ * @return a listener that will be added for a given property during its animation. Similar to
+ * the finish listener but used for Dynamic / SpringAnimations
+ */
+ public DynamicAnimation.OnAnimationEndListener getAnimationEndListener(Property property) {
+ if (mAnimationEndAction == null && mAnimationCancelAction == null) {
+ return null;
+ }
+ Consumer<Property> cancelAction = mAnimationCancelAction;
+ Consumer<Property> endAction = mAnimationEndAction;
+ return (animation, canceled, value, velocity) -> {
+ if (canceled && cancelAction != null) {
+ cancelAction.accept(property);
+ } else if (!canceled && endAction != null) {
+ endAction.accept(property);
+ }
+ };
+ }
+
+ /**
+ * @return a listener that is invoked when a property animation starts, used for dynamic
+ * animations. For classical, interpolator based animations used the listeneradapter instead,
+ * this is only for Dynamic Animations
+ */
+ public Consumer<DynamicAnimation> getAnimationStartListener(Property property) {
+ return null;
+ }
+
+ /**
* Add a callback for animation cancellation.
*/
public AnimationProperties setAnimationCancelAction(Consumer<Property> listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
index 69c9a4b..8cf9dd3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
@@ -16,23 +16,31 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.systemui.Flags.physicalNotificationMovement;
+import static com.android.systemui.statusbar.notification.row.ExpandableView.HEIGHT_PROPERTY;
+import static com.android.systemui.statusbar.notification.row.ExpandableView.TAG_ANIMATOR_HEIGHT;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
+import android.util.FloatProperty;
import android.view.View;
+import androidx.annotation.NonNull;
+
import com.android.app.animation.Interpolators;
import com.android.systemui.res.R;
+import com.android.systemui.statusbar.notification.PhysicsProperty;
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
/**
-* A state of an expandable view
-*/
+ * A state of an expandable view
+ */
public class ExpandableViewState extends ViewState {
- private static final int TAG_ANIMATOR_HEIGHT = R.id.height_animator_tag;
private static final int TAG_ANIMATOR_TOP_INSET = R.id.top_inset_animator_tag;
private static final int TAG_ANIMATOR_BOTTOM_INSET = R.id.bottom_inset_animator_tag;
private static final int TAG_END_HEIGHT = R.id.height_animator_end_value_tag;
@@ -149,7 +157,7 @@
// apply height
if (height != newHeight) {
- expandableView.setActualHeight(newHeight, false /* notifyListeners */);
+ expandableView.setFinalActualHeight(newHeight);
}
// apply hiding sensitive
@@ -186,8 +194,24 @@
// start height animation
if (this.height != expandableView.getActualHeight()) {
- startHeightAnimation(expandableView, properties);
- } else {
+ if (mUsePhysicsForMovement) {
+ boolean animateHeight = properties.getAnimationFilter().animateHeight;
+ if (animateHeight) {
+ expandableView.setActualHeightAnimating(true);
+ }
+ PhysicsPropertyAnimator.setProperty(child, HEIGHT_PROPERTY, this.height, properties,
+ animateHeight,
+ (animation, canceled, value, velocity) -> {
+ expandableView.setActualHeightAnimating(false);
+ if (!canceled && child instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) child).setGroupExpansionChanging(
+ false /* isExpansionChanging */);
+ }
+ });
+ } else {
+ startHeightAnimationInterpolator(expandableView, properties);
+ }
+ } else {
abortAnimation(child, TAG_ANIMATOR_HEIGHT);
}
@@ -224,7 +248,8 @@
}
}
- private void startHeightAnimation(final ExpandableView child, AnimationProperties properties) {
+ private void startHeightAnimationInterpolator(final ExpandableView child,
+ AnimationProperties properties) {
Integer previousStartValue = getChildTag(child, TAG_START_HEIGHT);
Integer previousEndValue = getChildTag(child, TAG_END_HEIGHT);
int newEndValue = this.height;
@@ -374,38 +399,16 @@
}
});
startAnimator(animator, listener);
- child.setTag(clipTop ? TAG_ANIMATOR_TOP_INSET:TAG_ANIMATOR_BOTTOM_INSET, animator);
- child.setTag(clipTop ? TAG_START_TOP_INSET: TAG_START_BOTTOM_INSET,
+ child.setTag(clipTop ? TAG_ANIMATOR_TOP_INSET : TAG_ANIMATOR_BOTTOM_INSET, animator);
+ child.setTag(clipTop ? TAG_START_TOP_INSET : TAG_START_BOTTOM_INSET,
clipTop ? child.getClipTopAmount() : child.getClipBottomAmount());
- child.setTag(clipTop ? TAG_END_TOP_INSET: TAG_END_BOTTOM_INSET, newEndValue);
- }
-
- /**
- * Get the end value of the height animation running on a view or the actualHeight
- * if no animation is running.
- */
- public static int getFinalActualHeight(ExpandableView view) {
- if (view == null) {
- return 0;
- }
- ValueAnimator heightAnimator = getChildTag(view, TAG_ANIMATOR_HEIGHT);
- if (heightAnimator == null) {
- return view.getActualHeight();
- } else {
- return getChildTag(view, TAG_END_HEIGHT);
- }
+ child.setTag(clipTop ? TAG_END_TOP_INSET : TAG_END_BOTTOM_INSET, newEndValue);
}
@Override
public void cancelAnimations(View view) {
super.cancelAnimations(view);
- Animator animator = getChildTag(view, TAG_ANIMATOR_HEIGHT);
- if (animator != null) {
- animator.cancel();
- }
- animator = getChildTag(view, TAG_ANIMATOR_TOP_INSET);
- if (animator != null) {
- animator.cancel();
- }
+ abortAnimation(view, TAG_ANIMATOR_HEIGHT);
+ abortAnimation(view, TAG_ANIMATOR_TOP_INSET);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
index a507c4c..de4af37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
@@ -73,7 +73,7 @@
updateMagneticAndRoundableTargets(swipingRow, stackScrollLayout, sectionsManager)
currentState = State.TARGETS_SET
} else {
- logger.logMagneticAndRoundableTargetsNotSet(currentState, swipingRow.entry)
+ logger.logMagneticAndRoundableTargetsNotSet(currentState, swipingRow.loggingKey)
}
}
@@ -95,12 +95,15 @@
notificationTargetsHelper.findMagneticTargets(
expandableNotificationRow,
stackScrollLayout,
+ sectionsManager,
MAGNETIC_TRANSLATION_MULTIPLIERS.size,
)
- currentMagneticListeners.swipedListener()?.cancelTranslationAnimations()
newListeners.forEach {
if (currentMagneticListeners.contains(it)) {
it?.cancelMagneticAnimations()
+ if (it == currentMagneticListeners.swipedListener()) {
+ it?.cancelTranslationAnimations()
+ }
}
}
currentMagneticListeners = newListeners
@@ -116,7 +119,7 @@
currentMagneticListeners.swipedListener()?.canRowBeDismissed() ?: false
when (currentState) {
State.IDLE -> {
- logger.logMagneticRowTranslationNotSet(currentState, row.entry)
+ logger.logMagneticRowTranslationNotSet(currentState, row.getLoggingKey())
return false
}
State.TARGETS_SET -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index ee57d45..1d18535 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -1352,10 +1352,11 @@
if (i < maxAllowedVisibleChildren) {
float singleLineHeight = child.getShowingLayout().getMinHeight(
false /* likeGroupExpanded */);
- child.setActualHeight((int) NotificationUtils.interpolate(singleLineHeight,
- childHeight, fraction), false);
+ childHeight = NotificationUtils.interpolate(singleLineHeight,
+ childHeight, fraction);
+ child.setFinalActualHeight((int) childHeight);
} else {
- child.setActualHeight((int) childHeight, false);
+ child.setFinalActualHeight((int) childHeight);
}
}
}
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 c694a19..3ff18ef 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
@@ -26,6 +26,7 @@
import static com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_CLEAR_ALL;
import static com.android.systemui.Flags.magneticNotificationSwipes;
import static com.android.systemui.Flags.notificationOverExpansionClippingFix;
+import static com.android.systemui.Flags.physicalNotificationMovement;
import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
import static com.android.systemui.statusbar.notification.stack.shared.model.AccessibilityScrollEvent.SCROLL_DOWN;
@@ -109,6 +110,7 @@
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationTransitionAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -5761,7 +5763,12 @@
+ view.getActualHeight() - mShelf.getIntrinsicHeight();
}
} else if (!firstVisibleView) {
- view.setTranslationY(wakeUplocation);
+ if (physicalNotificationMovement()) {
+ PhysicsPropertyAnimator.setProperty(view, PhysicsPropertyAnimator.Y_TRANSLATION,
+ wakeUplocation);
+ } else {
+ view.setTranslationY(wakeUplocation);
+ }
}
}
}
@@ -6679,7 +6686,7 @@
static boolean canChildBeCleared(View v) {
if (v instanceof ExpandableNotificationRow row) {
- if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
+ if (row.areGutsExposed() || !row.hasFinishedInitialization()) {
return false;
}
return row.canViewBeCleared();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index b69b936..8d7b2209 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -5,7 +5,6 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.notification.Roundable
-import com.android.systemui.statusbar.notification.footer.ui.view.FooterView
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import javax.inject.Inject
@@ -88,6 +87,7 @@
*
* @param[viewSwiped] The [ExpandableNotificationRow] that is swiped.
* @param[stackScrollLayout] [NotificationStackScrollLayout] container.
+ * @param[sectionsManager] The [NotificationSectionsManager]
* @param[totalMagneticTargets] The total number of magnetic listeners in the resulting list.
* This includes the listener of the view swiped.
* @return The list of [MagneticRowListener]s above and below the swiped
@@ -96,6 +96,7 @@
fun findMagneticTargets(
viewSwiped: ExpandableNotificationRow,
stackScrollLayout: NotificationStackScrollLayout,
+ sectionsManager: NotificationSectionsManager,
totalMagneticTargets: Int,
): List<MagneticRowListener?> {
val notificationParent = viewSwiped.notificationParent
@@ -126,26 +127,34 @@
var canMoveRight = true
for (distance in 1..totalMagneticTargets / 2) {
if (canMoveLeft) {
- val leftElement = container.getOrNull(index = centerIndex - distance)
+ val leftElement =
+ container.getOrNull(index = centerIndex - distance)?.takeIf {
+ it.isValidMagneticBoundary() ||
+ !sectionsManager.beginsSection(view = viewSwiped, previous = it)
+ }
if (leftElement is ExpandableNotificationRow) {
magneticTargets[leftIndex] = leftElement.magneticRowListener
leftIndex--
} else {
if (leftElement.isValidMagneticBoundary()) {
- // Add the boundary and then stop the iterating
+ // Add the boundary and then stop iterating
magneticTargets[leftIndex] = leftElement?.magneticRowListener
}
canMoveLeft = false
}
}
if (canMoveRight) {
- val rightElement = container.getOrNull(index = centerIndex + distance)
+ val rightElement =
+ container.getOrNull(index = centerIndex + distance)?.takeIf {
+ it.isValidMagneticBoundary() ||
+ !sectionsManager.beginsSection(view = it, previous = viewSwiped)
+ }
if (rightElement is ExpandableNotificationRow) {
magneticTargets[rightIndex] = rightElement.magneticRowListener
rightIndex++
} else {
if (rightElement.isValidMagneticBoundary()) {
- // Add the boundary and then stop the iterating
+ // Add the boundary and then stop iterating
magneticTargets[rightIndex] = rightElement?.magneticRowListener
}
canMoveRight = false
@@ -157,7 +166,6 @@
private fun ExpandableView?.isValidMagneticBoundary(): Boolean =
when (this) {
- is FooterView,
is NotificationShelf,
is SectionHeaderView -> true
else -> false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 06b989a..08692be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -1227,13 +1227,17 @@
float baseZ = ambientState.getBaseZHeight();
if (SceneContainerFlag.isEnabled()) {
- // SceneContainer flags off this logic, and just sets the baseZ because:
+ // SceneContainer simplifies this logic, because:
// - there are no overlapping HUNs anymore, no need for multiplying their shadows
// - shadows for HUNs overlapping with the stack are now set from updateHeadsUpStates
- // - shadows for HUNs overlapping with the shelf are NOT set anymore, because it only
- // happens on AOD/Pulsing, where they're displayed on a black background so a shadow
- // wouldn't be visible.
- childViewState.setZTranslation(baseZ);
+ if (child.isPinned() || ambientState.getTrackedHeadsUpRow() == child) {
+ // set a default elevation on the HUN, which would be overridden
+ // from updateHeadsUpStates if it is displayed in the shade
+ childViewState.setZTranslation(baseZ + mPinnedZTranslationExtra);
+ } else {
+ // set baseZ for every notification
+ childViewState.setZTranslation(baseZ);
+ }
} else {
if (child.mustStayOnScreen() && !childViewState.headsUpIsVisible
&& !ambientState.isDozingAndNotPulsing(child)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index c783250..5e0d57e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.systemui.Flags.physicalNotificationMovement;
+import static com.android.systemui.statusbar.notification.row.ExpandableView.HEIGHT_PROPERTY;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_HEADS_UP_CYCLING_IN;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_HEADS_UP_CYCLING_OUT;
@@ -29,11 +31,14 @@
import android.util.Property;
import android.view.View;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+
import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.res.R;
import com.android.systemui.shared.clocks.AnimatableClockView;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
@@ -41,6 +46,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Stack;
+import java.util.function.Consumer;
/**
* An stack state animator which handles animations to new StackScrollStates
@@ -68,8 +74,10 @@
public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
private static final int MAX_STAGGER_COUNT = 5;
- @VisibleForTesting int mGoToFullShadeAppearingTranslation;
- @VisibleForTesting float mHeadsUpAppearStartAboveScreen;
+ @VisibleForTesting
+ int mGoToFullShadeAppearingTranslation;
+ @VisibleForTesting
+ float mHeadsUpAppearStartAboveScreen;
// Padding between the old and new heads up notifications for the hun cycling animation
private float mHeadsUpCyclingPadding;
private final ExpandableViewState mTmpState = new ExpandableViewState();
@@ -80,8 +88,9 @@
private ArrayList<View> mNewAddChildren = new ArrayList<>();
private HashSet<View> mHeadsUpAppearChildren = new HashSet<>();
private HashSet<View> mHeadsUpDisappearChildren = new HashSet<>();
- private HashSet<Animator> mAnimatorSet = new HashSet<>();
+ private HashSet<Object> mAnimatorSet = new HashSet<>();
private Stack<AnimatorListenerAdapter> mAnimationListenerPool = new Stack<>();
+ private Stack<DynamicAnimation.OnAnimationEndListener> mAnimationEndPool = new Stack<>();
private AnimationFilter mAnimationFilter = new AnimationFilter();
private long mCurrentLength;
private long mCurrentAdditionalDelay;
@@ -99,6 +108,9 @@
mHostLayout = hostLayout;
initView(context);
mAnimationProperties = new AnimationProperties() {
+
+ private final Consumer<DynamicAnimation> mDynamicAnimationConsumer = mAnimatorSet::add;
+
@Override
public AnimationFilter getAnimationFilter() {
return mAnimationFilter;
@@ -110,6 +122,17 @@
}
@Override
+ public DynamicAnimation.OnAnimationEndListener getAnimationEndListener(
+ Property property) {
+ return getGlobalAnimationEndListener();
+ }
+
+ @Override
+ public Consumer<DynamicAnimation> getAnimationStartListener(Property property) {
+ return mDynamicAnimationConsumer;
+ }
+
+ @Override
public boolean wasAdded(View view) {
return mNewAddChildren.contains(view);
}
@@ -187,11 +210,11 @@
adaptDurationWhenGoingToFullShade(child, viewState, wasAdded, animationStaggerCount);
mAnimationProperties.delay = 0;
if (wasAdded || mAnimationFilter.hasDelays
- && (viewState.getYTranslation() != child.getTranslationY()
- || viewState.getZTranslation() != child.getTranslationZ()
- || viewState.getAlpha() != child.getAlpha()
- || viewState.height != child.getActualHeight()
- || viewState.clipTopAmount != child.getClipTopAmount())) {
+ && (viewState.getYTranslation() != child.getTranslationY()
+ || viewState.getZTranslation() != child.getTranslationZ()
+ || viewState.getAlpha() != child.getAlpha()
+ || viewState.height != child.getActualHeight()
+ || viewState.clipTopAmount != child.getClipTopAmount())) {
mAnimationProperties.delay = mCurrentAdditionalDelay
+ calculateChildAnimationDelay(viewState, animationStaggerCount);
}
@@ -209,7 +232,13 @@
mAnimationProperties.duration = ANIMATION_DURATION_APPEAR_DISAPPEAR + 50
+ (long) (100 * longerDurationFactor);
}
- child.setTranslationY(viewState.getYTranslation() + startOffset);
+ float newTranslationY = viewState.getYTranslation() + startOffset;
+ if (physicalNotificationMovement()) {
+ PhysicsPropertyAnimator.setProperty(child, PhysicsPropertyAnimator.Y_TRANSLATION,
+ newTranslationY);
+ } else {
+ child.setTranslationY(newTranslationY);
+ }
}
}
@@ -312,7 +341,7 @@
/**
* @return an adapter which ensures that onAnimationFinished is called once no animation is
- * running anymore
+ * running anymore
*/
private AnimatorListenerAdapter getGlobalAnimationFinishedListener() {
if (!mAnimationListenerPool.empty()) {
@@ -345,6 +374,27 @@
};
}
+ /**
+ * @return an adapter which ensures that onAnimationFinished is called once no animation is
+ * running anymore
+ */
+ private DynamicAnimation.OnAnimationEndListener getGlobalAnimationEndListener() {
+ if (!mAnimationEndPool.empty()) {
+ return mAnimationEndPool.pop();
+ }
+ return new DynamicAnimation.OnAnimationEndListener() {
+ @Override
+ public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
+ float velocity) {
+ mAnimatorSet.remove(animation);
+ if (mAnimatorSet.isEmpty() && !canceled) {
+ onAnimationFinished();
+ }
+ mAnimationEndPool.push(this);
+ }
+ };
+ }
+
private void onAnimationFinished() {
mHostLayout.onChildAnimationFinished();
@@ -358,7 +408,7 @@
* Process the animationEvents for a new animation. Here is the place to do something custom,
* like to modify the ViewState or to create a custom animation for an event.
*
- * @param animationEvents the animation events for the animation to perform
+ * @param animationEvents the animation events for the animation to perform
* @return true if any custom animation was created
*/
private boolean processAnimationEvents(
@@ -428,7 +478,7 @@
translationDirection = ((viewState.getYTranslation()
- (ownPosition + actualHeight / 2.0f)) * 2 /
actualHeight);
- translationDirection = Math.max(Math.min(translationDirection, 1.0f),-1.0f);
+ translationDirection = Math.max(Math.min(translationDirection, 1.0f), -1.0f);
}
Runnable postAnimation;
@@ -446,7 +496,7 @@
changingView.removeFromTransientContainer();
};
} else {
- startAnimation = ()-> {
+ startAnimation = () -> {
changingView.setInRemovalAnimation(true);
};
postAnimation = () -> {
@@ -460,7 +510,7 @@
ExpandableView.ClipSide.BOTTOM);
needsCustomAnimation = true;
} else if (event.animationType ==
- NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT) {
+ NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT) {
boolean isFullySwipedOut = mHostLayout.isFullySwipedOut(changingView);
if (loggable) {
mLogger.processAnimationEventsRemoveSwipeOut(key, isFullySwipedOut, isHeadsUp);
@@ -699,8 +749,8 @@
/**
* @param headsUpFromBottom Whether we are showing the HUNs at the bottom of the screen
- * @param oldHunHeight Height of the old HUN
- * @param newHunHeight Height of the new HUN
+ * @param oldHunHeight Height of the old HUN
+ * @param newHunHeight Height of the new HUN
* @return The y translation target value of the HUN cycling out animation
*/
private float getHeadsUpCyclingOutYTranslation(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index b2ffa4a..2ef6f36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -16,6 +16,10 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.systemui.Flags.physicalNotificationMovement;
+import static com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.TAG_ANIMATOR_TRANSLATION_Y;
+import static com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Y_TRANSLATION;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -26,14 +30,20 @@
import android.view.View;
import android.view.animation.Interpolator;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringAnimation;
+
import com.android.app.animation.Interpolators;
import com.android.systemui.Dumpable;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.NotificationFadeAware.FadeOptimizedNotification;
+import com.android.systemui.statusbar.notification.PhysicsProperty;
+import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator;
import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.PropertyData;
import com.android.systemui.statusbar.notification.headsup.HeadsUpUtil;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
import java.io.PrintWriter;
import java.lang.reflect.Field;
@@ -46,6 +56,14 @@
*/
public class ViewState implements Dumpable {
+ public ViewState() {
+ this(physicalNotificationMovement());
+ }
+
+ public ViewState(boolean usePhysicsForMovement) {
+ setUsePhysicsForMovement(usePhysicsForMovement);
+ }
+
/**
* Some animation properties that can be used to update running animations but not creating
* any new ones.
@@ -59,7 +77,6 @@
}
};
private static final int TAG_ANIMATOR_TRANSLATION_X = R.id.translation_x_animator_tag;
- private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
private static final int TAG_ANIMATOR_TRANSLATION_Z = R.id.translation_z_animator_tag;
private static final int TAG_ANIMATOR_ALPHA = R.id.alpha_animator_tag;
private static final int TAG_END_TRANSLATION_X = R.id.translation_x_animator_end_value_tag;
@@ -72,8 +89,7 @@
private static final int TAG_START_ALPHA = R.id.alpha_animator_start_value_tag;
private static final String LOG_TAG = "StackViewState";
- private static final AnimatableProperty SCALE_X_PROPERTY
- = new AnimatableProperty() {
+ private static final AnimatableProperty SCALE_X_PROPERTY = new AnimatableProperty() {
@Override
public int getAnimationStartTag() {
@@ -96,8 +112,7 @@
}
};
- private static final AnimatableProperty SCALE_Y_PROPERTY
- = new AnimatableProperty() {
+ private static final AnimatableProperty SCALE_Y_PROPERTY = new AnimatableProperty() {
@Override
public int getAnimationStartTag() {
@@ -129,11 +144,16 @@
private float mZTranslation;
private float mScaleX = 1.0f;
private float mScaleY = 1.0f;
+ protected boolean mUsePhysicsForMovement = false;
public float getAlpha() {
return mAlpha;
}
+ public void setUsePhysicsForMovement(boolean usePhysicsForMovement) {
+ this.mUsePhysicsForMovement = usePhysicsForMovement;
+ }
+
/**
* @param alpha View transparency.
*/
@@ -230,6 +250,7 @@
hidden = viewState.hidden;
mScaleX = viewState.mScaleX;
mScaleY = viewState.mScaleY;
+ mUsePhysicsForMovement = viewState.mUsePhysicsForMovement;
}
public void initFrom(View view) {
@@ -261,11 +282,15 @@
}
// apply yTranslation
- boolean animatingY = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y);
- if (animatingY) {
- updateAnimationY(view);
- } else if (view.getTranslationY() != this.mYTranslation) {
- view.setTranslationY(this.mYTranslation);
+ if (mUsePhysicsForMovement) {
+ PhysicsPropertyAnimator.setProperty(view, Y_TRANSLATION, this.mYTranslation);
+ } else {
+ boolean animatingY = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y);
+ if (animatingY) {
+ updateAnimationY(view);
+ } else if (view.getTranslationY() != this.mYTranslation) {
+ view.setTranslationY(this.mYTranslation);
+ }
}
// apply zTranslation
@@ -293,8 +318,8 @@
}
int oldVisibility = view.getVisibility();
- boolean becomesInvisible = this.mAlpha == 0.0f
- || (this.hidden && (!isAnimating(view) || oldVisibility != View.VISIBLE));
+ boolean becomesInvisible = this.mAlpha == 0.0f || (this.hidden && (!isAnimating(view)
+ || oldVisibility != View.VISIBLE));
boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
if (animatingAlpha) {
updateAlphaAnimation(view);
@@ -315,9 +340,8 @@
} else {
boolean newLayerTypeIsHardware = becomesFaded && view.hasOverlappingRendering();
int layerType = view.getLayerType();
- int newLayerType = newLayerTypeIsHardware
- ? View.LAYER_TYPE_HARDWARE
- : View.LAYER_TYPE_NONE;
+ int newLayerType =
+ newLayerTypeIsHardware ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
if (layerType != newLayerType) {
view.setLayerType(newLayerType, null);
}
@@ -360,11 +384,19 @@
}
private static boolean isAnimating(View view, int tag) {
- return getChildTag(view, tag) != null;
+ Object childTag = getChildTag(view, tag);
+ if (childTag instanceof PropertyData propertyData) {
+ return propertyData.getAnimator() != null;
+ }
+ return childTag != null;
}
public static boolean isAnimating(View view, AnimatableProperty property) {
- return getChildTag(view, property.getAnimatorTag()) != null;
+ Object childTag = getChildTag(view, property.getAnimatorTag());
+ if (childTag instanceof PropertyData propertyData) {
+ return propertyData.getAnimator() != null;
+ }
+ return childTag != null;
}
/**
@@ -376,8 +408,7 @@
public void animateTo(View child, AnimationProperties animationProperties) {
boolean wasVisible = child.getVisibility() == View.VISIBLE;
final float alpha = this.mAlpha;
- if (!wasVisible && (alpha != 0 || child.getAlpha() != 0)
- && !this.gone && !this.hidden) {
+ if (!wasVisible && (alpha != 0 || child.getAlpha() != 0) && !this.gone && !this.hidden) {
child.setVisibility(View.VISIBLE);
}
float childAlpha = child.getAlpha();
@@ -465,8 +496,8 @@
}
}
- ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.ALPHA,
- child.getAlpha(), newEndValue);
+ ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.ALPHA, child.getAlpha(),
+ newEndValue);
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
// Handle layer type
child.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -516,8 +547,7 @@
startZTranslationAnimation(view, NO_NEW_ANIMATIONS);
}
- private void updateAnimation(View view, AnimatableProperty property,
- float endValue) {
+ private void updateAnimation(View view, AnimatableProperty property, float endValue) {
PropertyAnimator.startAnimation(view, property, endValue, NO_NEW_ANIMATIONS);
}
@@ -615,8 +645,8 @@
child.getTranslationX(), newEndValue);
Interpolator customInterpolator = properties.getCustomInterpolator(child,
View.TRANSLATION_X);
- Interpolator interpolator = customInterpolator != null ? customInterpolator
- : Interpolators.FAST_OUT_SLOW_IN;
+ Interpolator interpolator =
+ customInterpolator != null ? customInterpolator : Interpolators.FAST_OUT_SLOW_IN;
animator.setInterpolator(interpolator);
long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
animator.setDuration(newDuration);
@@ -649,6 +679,24 @@
}
private void startYTranslationAnimation(final View child, AnimationProperties properties) {
+ if (mUsePhysicsForMovement) {
+ // Y Translation does some extra calls when it ends, so lets add a listener
+ DynamicAnimation.OnAnimationEndListener endListener =
+ (animation, canceled, value, velocity) -> {
+ if (!canceled) {
+ HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(child, false);
+ onYTranslationAnimationFinished(child);
+ }
+ };
+ PhysicsPropertyAnimator.setProperty(child, Y_TRANSLATION, this.mYTranslation,
+ properties, properties.getAnimationFilter().animateY, endListener);
+ } else {
+ startYTranslationInterpolatorAnimation(child, properties);
+ }
+ }
+
+ private void startYTranslationInterpolatorAnimation(View child,
+ AnimationProperties properties) {
Float previousStartValue = getChildTag(child, TAG_START_TRANSLATION_Y);
Float previousEndValue = getChildTag(child, TAG_END_TRANSLATION_Y);
float newEndValue = this.mYTranslation;
@@ -681,8 +729,8 @@
child.getTranslationY(), newEndValue);
Interpolator customInterpolator = properties.getCustomInterpolator(child,
View.TRANSLATION_Y);
- Interpolator interpolator = customInterpolator != null ? customInterpolator
- : Interpolators.FAST_OUT_SLOW_IN;
+ Interpolator interpolator =
+ customInterpolator != null ? customInterpolator : Interpolators.FAST_OUT_SLOW_IN;
animator.setInterpolator(interpolator);
long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
animator.setDuration(newDuration);
@@ -731,9 +779,19 @@
}
protected void abortAnimation(View child, int animatorTag) {
- Animator previousAnimator = getChildTag(child, animatorTag);
- if (previousAnimator != null) {
- previousAnimator.cancel();
+ Object storedTag = getChildTag(child, animatorTag);
+ if (storedTag != null) {
+ if (storedTag instanceof Animator animator) {
+ animator.cancel();
+ } else if (storedTag instanceof PropertyData propertyData) {
+ // Physics based animation!
+ Runnable delayRunnable = propertyData.getDelayRunnable();
+ child.removeCallbacks(delayRunnable);
+ SpringAnimation animator = propertyData.getAnimator();
+ if (animator != null) {
+ animator.cancel();
+ }
+ }
}
}
@@ -750,46 +808,15 @@
if (previousAnimator != null) {
// We take either the desired length of the new animation or the remaining time of
// the previous animator, whichever is longer.
- newDuration = Math.max(previousAnimator.getDuration()
- - previousAnimator.getCurrentPlayTime(), newDuration);
+ newDuration = Math.max(
+ previousAnimator.getDuration() - previousAnimator.getCurrentPlayTime(),
+ newDuration);
previousAnimator.cancel();
}
return newDuration;
}
/**
- * Get the end value of the xTranslation animation running on a view or the xTranslation
- * if no animation is running.
- */
- public static float getFinalTranslationX(View view) {
- if (view == null) {
- return 0;
- }
- ValueAnimator xAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
- if (xAnimator == null) {
- return view.getTranslationX();
- } else {
- return getChildTag(view, TAG_END_TRANSLATION_X);
- }
- }
-
- /**
- * Get the end value of the yTranslation animation running on a view or the yTranslation
- * if no animation is running.
- */
- public static float getFinalTranslationY(View view) {
- if (view == null) {
- return 0;
- }
- ValueAnimator yAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
- if (yAnimator == null) {
- return view.getTranslationY();
- } else {
- return getChildTag(view, TAG_END_TRANSLATION_Y);
- }
- }
-
- /**
* Get the end value of the zTranslation animation running on a view or the zTranslation
* if no animation is running.
*/
@@ -806,26 +833,14 @@
}
public static boolean isAnimatingY(View child) {
- return getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y) != null;
+ return isAnimating(child, TAG_ANIMATOR_TRANSLATION_Y);
}
public void cancelAnimations(View view) {
- Animator animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
- if (animator != null) {
- animator.cancel();
- }
- animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
- if (animator != null) {
- animator.cancel();
- }
- animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
- if (animator != null) {
- animator.cancel();
- }
- animator = getChildTag(view, TAG_ANIMATOR_ALPHA);
- if (animator != null) {
- animator.cancel();
- }
+ abortAnimation(view, TAG_ANIMATOR_TRANSLATION_X);
+ abortAnimation(view, TAG_ANIMATOR_TRANSLATION_Y);
+ abortAnimation(view, TAG_ANIMATOR_TRANSLATION_Z);
+ abortAnimation(view, TAG_ANIMATOR_ALPHA);
}
@Override
@@ -840,8 +855,8 @@
// Print field names paired with their values
for (Field field : fields) {
int modifiers = field.getModifiers();
- if (Modifier.isStatic(modifiers) || field.isSynthetic()
- || Modifier.isTransient(modifiers)) {
+ if (Modifier.isStatic(modifiers) || field.isSynthetic() || Modifier.isTransient(
+ modifiers)) {
continue;
}
if (!first) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 54efa4a..34b6560 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -20,6 +20,7 @@
import android.content.Context
import androidx.annotation.VisibleForTesting
import com.android.app.tracing.coroutines.flow.flowName
+import com.android.systemui.Flags.glanceableHubV2
import com.android.systemui.common.shared.model.NotificationContainerBounds
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
@@ -44,15 +45,18 @@
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
+import com.android.systemui.keyguard.ui.viewmodel.AodToGlanceableHubTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToPrimaryBouncerTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.DozingToDreamingTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.DozingToGlanceableHubTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.DozingToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.DozingToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.DozingToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GoneToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GoneToDozingTransitionViewModel
@@ -84,7 +88,9 @@
import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
+import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
+import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import com.android.systemui.util.kotlin.FlowDumperImpl
import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
import com.android.systemui.util.kotlin.sample
@@ -135,7 +141,9 @@
private val aodToGoneTransitionViewModel: AodToGoneTransitionViewModel,
private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
private val aodToOccludedTransitionViewModel: AodToOccludedTransitionViewModel,
+ private val aodToGlanceableHubTransitionViewModel: AodToGlanceableHubTransitionViewModel,
private val aodToPrimaryBouncerTransitionViewModel: AodToPrimaryBouncerTransitionViewModel,
+ private val dozingToDreamingTransitionViewModel: DozingToDreamingTransitionViewModel,
dozingToGlanceableHubTransitionViewModel: DozingToGlanceableHubTransitionViewModel,
private val dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
private val dozingToOccludedTransitionViewModel: DozingToOccludedTransitionViewModel,
@@ -144,6 +152,7 @@
private val dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
private val glanceableHubToLockscreenTransitionViewModel:
GlanceableHubToLockscreenTransitionViewModel,
+ private val glanceableHubToAodTransitionViewModel: GlanceableHubToAodTransitionViewModel,
private val goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
private val goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel,
private val goneToDreamingTransitionViewModel: GoneToDreamingTransitionViewModel,
@@ -293,20 +302,40 @@
.distinctUntilChanged()
.dumpWhileCollecting("configurationBasedDimensions")
+ private val isOnAnyBouncer: Flow<Boolean> =
+ anyOf(
+ keyguardTransitionInteractor.transitionValue(ALTERNATE_BOUNCER).map { it > 0f },
+ keyguardTransitionInteractor
+ .transitionValue(
+ scene = Scenes.Bouncer,
+ stateWithoutSceneContainer = PRIMARY_BOUNCER,
+ )
+ .map { it > 0f },
+ )
+
/** If the user is visually on one of the unoccluded lockscreen states. */
val isOnLockscreen: Flow<Boolean> =
- anyOf(
- keyguardTransitionInteractor.transitionValue(AOD).map { it > 0f },
- keyguardTransitionInteractor.transitionValue(DOZING).map { it > 0f },
- keyguardTransitionInteractor.transitionValue(ALTERNATE_BOUNCER).map { it > 0f },
- keyguardTransitionInteractor
- .transitionValue(
- scene = Scenes.Bouncer,
- stateWithoutSceneContainer = PRIMARY_BOUNCER,
- )
- .map { it > 0f },
- keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f },
- )
+ if (glanceableHubV2()) {
+ anyOf(
+ keyguardTransitionInteractor.transitionValue(AOD).map { it > 0f },
+ keyguardTransitionInteractor.transitionValue(DOZING).map { it > 0f },
+ keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f },
+ allOf(
+ // Exclude bouncer showing over communal hub, as this should not be
+ // considered
+ // "lockscreen"
+ not(communalSceneInteractor.isCommunalVisible),
+ isOnAnyBouncer,
+ ),
+ )
+ } else {
+ anyOf(
+ keyguardTransitionInteractor.transitionValue(AOD).map { it > 0f },
+ keyguardTransitionInteractor.transitionValue(DOZING).map { it > 0f },
+ keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f },
+ isOnAnyBouncer,
+ )
+ }
.flowName("isOnLockscreen")
.stateIn(
scope = applicationScope,
@@ -571,7 +600,9 @@
aodToGoneTransitionViewModel.notificationAlpha(viewState),
aodToLockscreenTransitionViewModel.notificationAlpha,
aodToOccludedTransitionViewModel.lockscreenAlpha(viewState),
+ aodToGlanceableHubTransitionViewModel.lockscreenAlpha(viewState),
aodToPrimaryBouncerTransitionViewModel.notificationAlpha,
+ dozingToDreamingTransitionViewModel.notificationAlpha,
dozingToLockscreenTransitionViewModel.lockscreenAlpha,
dozingToOccludedTransitionViewModel.lockscreenAlpha(viewState),
dozingToPrimaryBouncerTransitionViewModel.notificationAlpha,
@@ -591,6 +622,7 @@
offToLockscreenTransitionViewModel.lockscreenAlpha,
primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha(viewState),
glanceableHubToLockscreenTransitionViewModel.keyguardAlpha,
+ glanceableHubToAodTransitionViewModel.lockscreenAlpha,
lockscreenToGlanceableHubTransitionViewModel.keyguardAlpha,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index de72154..36193bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -441,6 +441,7 @@
mAnimationScheduler.addCallback(mAnimationCallback);
mUserInfoController.addCallback(mOnUserInfoChangedListener);
mStatusBarStateController.addCallback(mStatusBarStateListener);
+ mStatusBarState = mStatusBarStateController.getState();
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mDisableStateTracker.startTracking(mCommandQueue, mView.getDisplay().getDisplayId());
if (mTintedIconManager == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 4825a10..15d73d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -735,6 +735,7 @@
private final Consumer<Property> mCannedAnimationEndListener;
public IconState(View child) {
+ super(false /* usePhysicsForMovement */);
mView = child;
mCannedAnimationEndListener = (property) -> {
// If we finished animating out of the shelf
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 6c8e182..ba41fd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -65,6 +65,7 @@
import com.android.systemui.shade.ShadeDisplayAware;
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationClickNotifier;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -116,6 +117,7 @@
private final static String TAG = "StatusBarNotificationActivityStarter";
private final Context mContext;
+ private final ShadeDialogContextInteractor mContextInteractor;
private final Handler mMainThreadHandler;
private final Executor mUiBgExecutor;
@@ -156,6 +158,7 @@
@Inject
StatusBarNotificationActivityStarter(
@ShadeDisplayAware Context context,
+ ShadeDialogContextInteractor contextInteractor,
@Main Handler mainThreadHandler,
@Background Executor uiBgExecutor,
NotificationVisibilityProvider visibilityProvider,
@@ -188,6 +191,7 @@
PowerInteractor powerInteractor,
UserTracker userTracker) {
mContext = context;
+ mContextInteractor = contextInteractor;
mMainThreadHandler = mainThreadHandler;
mUiBgExecutor = uiBgExecutor;
mVisibilityProvider = visibilityProvider;
@@ -491,7 +495,7 @@
boolean animate,
boolean isActivityIntent) {
mLogger.logStartNotificationIntent(entry);
- final int displayId = mContext.getDisplayId();
+ final int displayId = mContextInteractor.getContext().getDisplayId();
try {
ActivityTransitionAnimator.Controller animationController =
new StatusBarTransitionAnimatorController(
@@ -532,7 +536,7 @@
public void startNotificationGutsIntent(@NonNull final Intent intent, final int appUid,
@NonNull ExpandableNotificationRow row) {
boolean animate = mActivityStarter.shouldAnimateLaunch(true /* isActivityIntent */);
- final int displayId = mContext.getDisplayId();
+ final int displayId = mContextInteractor.getContext().getDisplayId();
ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
@Override
public boolean onDismiss() {
@@ -571,7 +575,7 @@
@Override
public void startHistoryIntent(View view, boolean showHistory) {
ModesEmptyShadeFix.assertInLegacyMode();
- final int displayId = mContext.getDisplayId();
+ final int displayId = mContextInteractor.getContext().getDisplayId();
boolean animate = mActivityStarter.shouldAnimateLaunch(true /* isActivityIntent */);
ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
@Override
@@ -621,7 +625,7 @@
@Override
public void startSettingsIntent(@NonNull View view, @NonNull SettingsIntent intentInfo) {
- final int displayId = mContext.getDisplayId();
+ final int displayId = mContextInteractor.getContext().getDisplayId();
boolean animate = mActivityStarter.shouldAnimateLaunch(true /* isActivityIntent */);
ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 144939d..38c0d28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -443,6 +443,11 @@
}
public static class StatusIconState extends ViewState {
+
+ public StatusIconState() {
+ super(false /* usePhysicsForMovement */);
+ }
+
/// StatusBarIconView.STATE_*
public int visibleState = STATE_ICON;
public boolean justAdded = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt
index 9f8b455..b77e8f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/StatusBarChipsModernization.kt
@@ -23,6 +23,10 @@
@Suppress("NOTHING_TO_INLINE")
object StatusBarChipsModernization {
/** The aconfig flag name */
+ @Deprecated(
+ "For tests, use @EnableChipsModernization or @DisableChipsModernization " +
+ "annotations instead"
+ )
const val FLAG_NAME = Flags.FLAG_STATUS_BAR_CHIPS_MODERNIZATION
/** A token used for dependency declaration */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
index 2fd7d82..d6ca656 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
@@ -150,7 +150,14 @@
return when {
isVisible -> {
logger.d({ "Call app is visible: uid=$int1" }) { int1 = model.uid }
- OngoingCallModel.InCallWithVisibleApp
+ OngoingCallModel.InCallWithVisibleApp(
+ startTimeMs = model.whenTime,
+ notificationIconView = model.statusBarChipIconView,
+ intent = model.contentIntent,
+ notificationKey = model.key,
+ appName = model.appName,
+ promotedContent = model.promotedContent,
+ )
}
else -> {
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 6507b72..62f0ba0 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
@@ -28,8 +28,21 @@
/**
* There is an ongoing call but the call app is currently visible, so we don't need to show the
* chip.
+ *
+ * @property startTimeMs see [InCall.startTimeMs].
+ * @property notificationIconView see [InCall.notificationIconView].
+ * @property intent see [InCall.intent].
+ * @property appName see [InCall.appName].
+ * @property promotedContent see [InCall.promotedContent].
*/
- data object InCallWithVisibleApp : OngoingCallModel
+ data class InCallWithVisibleApp(
+ val startTimeMs: Long,
+ val notificationIconView: StatusBarIconView?,
+ val intent: PendingIntent?,
+ val notificationKey: String,
+ val appName: String,
+ val promotedContent: PromotedNotificationContentModel?,
+ ) : OngoingCallModel
/**
* There *is* an ongoing call.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index d336903..2efc057 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -20,6 +20,7 @@
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
+import android.content.pm.PackageManager
import android.telephony.CarrierConfigManager
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
@@ -192,6 +193,19 @@
serviceStateChangedEvent
.mapLatest {
val modems = telephonyManager.activeModemCount
+
+ // Assume false for automotive devices which don't have the calling feature.
+ // TODO: b/398045526 to revisit the below.
+ val isAutomotive: Boolean =
+ context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ val hasFeatureCalling: Boolean =
+ context.packageManager.hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING
+ )
+ if (isAutomotive && !hasFeatureCalling) {
+ return@mapLatest false
+ }
+
// Check the service state for every modem. If any state reports emergency calling
// capable, then consider the device to have emergency call capabilities
(0..<modems)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index a1f7a81..0eabb4ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -37,10 +37,8 @@
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
@@ -255,12 +253,7 @@
}
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
- override val isNonTerrestrial: StateFlow<Boolean> =
- if (Flags.carrierEnabledSatelliteFlag()) {
- connectionRepository.isNonTerrestrial
- } else {
- MutableStateFlow(false).asStateFlow()
- }
+ override val isNonTerrestrial: StateFlow<Boolean> = connectionRepository.isNonTerrestrial
override val isRoaming: StateFlow<Boolean> =
combine(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
index c52536d..10821df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
@@ -21,7 +21,6 @@
import android.telephony.SubscriptionManager
import android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING
import com.android.settingslib.SignalIcon.MobileIconGroup
-import com.android.settingslib.flags.Flags
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -29,11 +28,13 @@
import com.android.systemui.flags.Flags.FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.core.NewStatusBarIcons
import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository
@@ -85,6 +86,12 @@
/** Whether the mobile icons can be stacked vertically. */
val isStackable: StateFlow<Boolean>
+ /**
+ * Observable for the subscriptionId of the current mobile data connection. Null if we don't
+ * have a valid subscription id
+ */
+ val activeMobileDataSubscriptionId: StateFlow<Int?>
+
/** True if the active mobile data subscription has data enabled */
val activeDataConnectionHasDataEnabled: StateFlow<Boolean>
@@ -168,6 +175,9 @@
)
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
+ override val activeMobileDataSubscriptionId: StateFlow<Int?> =
+ mobileConnectionsRepo.activeMobileDataSubscriptionId
+
override val activeDataConnectionHasDataEnabled: StateFlow<Boolean> =
mobileConnectionsRepo.activeMobileDataRepository
.flatMapLatest { it?.dataEnabled ?: flowOf(false) }
@@ -298,10 +308,16 @@
.stateIn(scope, SharingStarted.WhileSubscribed(), emptyList())
override val isStackable =
- if (Flags.newStatusBarIcons() && StatusBarRootModernization.isEnabled) {
+ if (NewStatusBarIcons.isEnabled && StatusBarRootModernization.isEnabled) {
icons.flatMapLatest { icons ->
- combine(icons.map { it.isNonTerrestrial }) {
- it.size == 2 && it.none { isNonTerrestrial -> isNonTerrestrial }
+ combine(icons.map { it.signalLevelIcon }) { signalLevelIcons ->
+ // These are only stackable if:
+ // - They are cellular
+ // - There's exactly two
+ // - They have the same number of levels
+ signalLevelIcons.filterIsInstance<SignalIconModel.Cellular>().let {
+ it.size == 2 && it[0].numberOfLevels == it[1].numberOfLevels
+ }
}
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
index 6176a3e..288e49e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
@@ -63,6 +63,8 @@
@VisibleForTesting
val reuseCache = ConcurrentHashMap<Int, Pair<MobileIconViewModel, CoroutineScope>>()
+ val activeMobileDataSubscriptionId: StateFlow<Int?> = interactor.activeMobileDataSubscriptionId
+
val subscriptionIdsFlow: StateFlow<List<Int>> =
interactor.filteredSubscriptions
.mapLatest { subscriptions ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModel.kt
index a2c2a3c..2c85a51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModel.kt
@@ -25,7 +25,7 @@
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -43,8 +43,14 @@
initialValue = false,
)
- private val iconViewModelFlow: StateFlow<List<MobileIconViewModelCommon>> =
- mobileIconsViewModel.mobileSubViewModels
+ private val iconViewModelFlow: Flow<List<MobileIconViewModelCommon>> =
+ combine(
+ mobileIconsViewModel.mobileSubViewModels,
+ mobileIconsViewModel.activeMobileDataSubscriptionId,
+ ) { viewModels, activeSubId ->
+ // Sort to get the active subscription first, if it's set
+ viewModels.sortedByDescending { it.subscriptionId == activeSubId }
+ }
val dualSim: DualSim? by
hydrator.hydratedStateOf(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
index cd320a1..d734889 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
@@ -31,6 +31,8 @@
import com.android.systemui.statusbar.chips.mediaprojection.domain.model.MediaProjectionStopDialogModel
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.chips.ui.binder.OngoingActivityChipBinder
+import com.android.systemui.statusbar.chips.ui.binder.OngoingActivityChipViewBinding
+import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModelLegacy
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.core.StatusBarRootModernization
@@ -149,6 +151,7 @@
if (!StatusBarNotifChips.isEnabled && !StatusBarChipsModernization.isEnabled) {
val primaryChipViewBinding =
OngoingActivityChipBinder.createBinding(primaryChipView)
+
launch {
viewModel.primaryOngoingActivityChip.collect { primaryChipModel ->
OngoingActivityChipBinder.bind(
@@ -156,18 +159,14 @@
primaryChipViewBinding,
iconViewStore,
)
- if (StatusBarRootModernization.isEnabled) {
- when (primaryChipModel) {
- is OngoingActivityChipModel.Active ->
- primaryChipViewBinding.rootView.show(
- shouldAnimateChange = true
- )
- is OngoingActivityChipModel.Inactive ->
- primaryChipViewBinding.rootView.hide(
- state = View.GONE,
- shouldAnimateChange = primaryChipModel.shouldAnimate,
- )
+ if (StatusBarRootModernization.isEnabled) {
+ launch {
+ bindLegacyPrimaryOngoingActivityChipWithVisibility(
+ viewModel,
+ primaryChipModel,
+ primaryChipViewBinding,
+ )
}
} else {
when (primaryChipModel) {
@@ -213,12 +212,14 @@
)
if (StatusBarRootModernization.isEnabled) {
- primaryChipViewBinding.rootView.adjustVisibility(
- chips.primary.toVisibilityModel()
- )
- secondaryChipViewBinding.rootView.adjustVisibility(
- chips.secondary.toVisibilityModel()
- )
+ launch {
+ bindOngoingActivityChipsWithVisibility(
+ viewModel,
+ chips,
+ primaryChipViewBinding,
+ secondaryChipViewBinding,
+ )
+ }
} else {
listener?.onOngoingActivityStatusChanged(
hasPrimaryOngoingActivity =
@@ -312,6 +313,52 @@
}
}
+ /** Bind the (legacy) single primary ongoing activity chip with the status bar visibility */
+ private suspend fun bindLegacyPrimaryOngoingActivityChipWithVisibility(
+ viewModel: HomeStatusBarViewModel,
+ primaryChipModel: OngoingActivityChipModel,
+ primaryChipViewBinding: OngoingActivityChipViewBinding,
+ ) {
+ viewModel.canShowOngoingActivityChips.collectLatest { visible ->
+ if (!visible) {
+ primaryChipViewBinding.rootView.hide(shouldAnimateChange = false)
+ } else {
+ when (primaryChipModel) {
+ is OngoingActivityChipModel.Active -> {
+ primaryChipViewBinding.rootView.show(shouldAnimateChange = true)
+ }
+
+ is OngoingActivityChipModel.Inactive -> {
+ primaryChipViewBinding.rootView.hide(
+ state = View.GONE,
+ shouldAnimateChange = primaryChipModel.shouldAnimate,
+ )
+ }
+ }
+ }
+ }
+ }
+
+ /** Bind the primary/secondary chips along with the home status bar's visibility */
+ private suspend fun bindOngoingActivityChipsWithVisibility(
+ viewModel: HomeStatusBarViewModel,
+ chips: MultipleOngoingActivityChipsModelLegacy,
+ primaryChipViewBinding: OngoingActivityChipViewBinding,
+ secondaryChipViewBinding: OngoingActivityChipViewBinding,
+ ) {
+ viewModel.canShowOngoingActivityChips.collectLatest { canShow ->
+ if (!canShow) {
+ primaryChipViewBinding.rootView.hide(shouldAnimateChange = false)
+ secondaryChipViewBinding.rootView.hide(shouldAnimateChange = false)
+ } else {
+ primaryChipViewBinding.rootView.adjustVisibility(chips.primary.toVisibilityModel())
+ secondaryChipViewBinding.rootView.adjustVisibility(
+ chips.secondary.toVisibilityModel()
+ )
+ }
+ }
+ }
+
private fun SystemEventAnimationState.isAnimatingChip() =
when (this) {
AnimatingIn,
@@ -374,43 +421,42 @@
if (visibility == View.INVISIBLE || visibility == View.GONE) {
return
}
+ alpha = 0f
visibility = state
}
// See CollapsedStatusBarFragment#hide.
private fun View.hide(state: Int = View.INVISIBLE, shouldAnimateChange: Boolean) {
+ animate().cancel()
if (visibility == View.INVISIBLE || visibility == View.GONE) {
return
}
- val v = this
- v.animate().cancel()
if (!shouldAnimateChange) {
- v.alpha = 0f
- v.visibility = state
+ alpha = 0f
+ visibility = state
return
}
- v.animate()
+ animate()
.alpha(0f)
.setDuration(CollapsedStatusBarFragment.FADE_OUT_DURATION.toLong())
.setStartDelay(0)
.setInterpolator(Interpolators.ALPHA_OUT)
- .withEndAction { v.visibility = state }
+ .withEndAction { visibility = state }
}
// See CollapsedStatusBarFragment#show.
private fun View.show(shouldAnimateChange: Boolean) {
- if (visibility == View.VISIBLE) {
+ animate().cancel()
+ if (visibility == View.VISIBLE && alpha >= 1f) {
return
}
- val v = this
- v.animate().cancel()
- v.visibility = View.VISIBLE
+ visibility = View.VISIBLE
if (!shouldAnimateChange) {
- v.alpha = 1f
+ alpha = 1f
return
}
- v.animate()
+ animate()
.alpha(1f)
.setDuration(CollapsedStatusBarFragment.FADE_IN_DURATION.toLong())
.setInterpolator(Interpolators.ALPHA_IN)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StackedMobileIcon.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StackedMobileIcon.kt
index 465a43f..a51da0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StackedMobileIcon.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StackedMobileIcon.kt
@@ -17,9 +17,12 @@
package com.android.systemui.statusbar.pipeline.shared.ui.composable
import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -27,23 +30,28 @@
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.TextUnit
-import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import com.android.compose.modifiers.height
-import com.android.compose.modifiers.width
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.StackedMobileIconViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.BarBaseHeightFiveBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.BarBaseHeightFourBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.BarsLevelIncrementSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.BarsVerticalPaddingSp
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.ExclamationCutoutRadiusSp
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.ExclamationDiameterSp
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.ExclamationHeightSp
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.ExclamationHorizontalOffset
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.ExclamationVerticalSpacing
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.HorizontalPaddingFiveBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.HorizontalPaddingFourBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.IconHeightSp
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.IconPaddingSp
+import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.IconSpacingSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.IconWidthFiveBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.IconWidthFourBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.SecondaryBarHeightSp
@@ -58,15 +66,16 @@
val dualSim = viewModel.dualSim ?: return
val contentColor = LocalContentColor.current
+ val padding = with(LocalDensity.current) { IconPaddingSp.toDp() }
+ val horizontalArrangement = with(LocalDensity.current) { spacedBy(IconSpacingSp.toDp()) }
- Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) {
+ Row(
+ horizontalArrangement = horizontalArrangement,
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = modifier.padding(horizontal = padding),
+ ) {
viewModel.networkTypeIcon?.let {
- Icon(
- it,
- tint = contentColor,
- modifier =
- Modifier.height { IconHeightSp.roundToPx() }.padding(start = 1.dp, end = 2.dp),
- )
+ Icon(it, tint = contentColor, modifier = Modifier.fillMaxHeight())
}
StackedMobileIcon(dualSim, contentColor)
@@ -79,23 +88,23 @@
color: Color,
modifier: Modifier = Modifier,
) {
- val maxNumberOfLevels =
- max(viewModel.primary.numberOfLevels, viewModel.secondary.numberOfLevels)
- val dimensions = if (maxNumberOfLevels == 6) FiveBarsDimensions else FourBarsDimensions
+ // Removing 1 to get the real number of bars
+ val numberOfBars = max(viewModel.primary.numberOfLevels, viewModel.secondary.numberOfLevels) - 1
+ val dimensions = if (numberOfBars == 5) FiveBarsDimensions else FourBarsDimensions
val iconSize =
with(LocalDensity.current) { dimensions.totalWidth.toDp() to IconHeightSp.toDp() }
- Canvas(modifier.size(width = iconSize.first, height = iconSize.second)) {
+ Canvas(modifier.width(iconSize.first).height(iconSize.second)) {
val verticalPaddingPx = BarsVerticalPaddingSp.roundToPx()
val horizontalPaddingPx = dimensions.barsHorizontalPadding.roundToPx()
- val totalPaddingWidthPx = horizontalPaddingPx * (maxNumberOfLevels - 1)
+ val totalPaddingWidthPx = horizontalPaddingPx * (numberOfBars - 1)
- val barWidthPx = (size.width - totalPaddingWidthPx) / maxNumberOfLevels
+ val barWidthPx = (size.width - totalPaddingWidthPx) / numberOfBars
val dotHeightPx = SecondaryBarHeightSp.toPx()
val baseBarHeightPx = dimensions.barBaseHeight.toPx()
var xOffsetPx = 0f
- for (bar in 1..maxNumberOfLevels) {
+ for (bar in 1..numberOfBars) {
// Bottom dots representing secondary sim
val dotYOffsetPx = size.height - dotHeightPx
if (bar <= viewModel.secondary.numberOfLevels) {
@@ -123,6 +132,10 @@
xOffsetPx += barWidthPx + horizontalPaddingPx
}
+
+ if (viewModel.primary.showExclamationMark) {
+ drawExclamationCutout(color)
+ }
}
}
@@ -143,6 +156,39 @@
)
}
+private fun DrawScope.drawExclamationCutout(color: Color) {
+ // Exclamation mark is bottom aligned with the canvas
+ val exclamationDiameterPx = ExclamationDiameterSp.toPx()
+ val exclamationRadiusPx = ExclamationDiameterSp.toPx() / 2
+ val exclamationTotalHeight =
+ ExclamationHeightSp.toPx() + ExclamationVerticalSpacing.toPx() + exclamationDiameterPx
+ val exclamationDotCenter =
+ Offset(size.width - ExclamationHorizontalOffset.toPx(), size.height - exclamationRadiusPx)
+ val exclamationMarkTopLeft =
+ Offset(exclamationDotCenter.x - exclamationRadiusPx, size.height - exclamationTotalHeight)
+ val exclamationCornerRadius = CornerRadius(exclamationRadiusPx)
+ val cutoutCenter = Offset(exclamationDotCenter.x, size.height - (exclamationTotalHeight / 2))
+
+ // Transparent cutout
+ drawCircle(
+ color = Color.Transparent,
+ radius = ExclamationCutoutRadiusSp.toPx(),
+ center = cutoutCenter,
+ blendMode = BlendMode.SrcIn,
+ )
+
+ // Top bar for the exclamation mark
+ drawRoundRect(
+ color = color,
+ topLeft = exclamationMarkTopLeft,
+ size = Size(exclamationDiameterPx, ExclamationHeightSp.toPx()),
+ cornerRadius = exclamationCornerRadius,
+ )
+
+ // Bottom circle for the exclamation mark
+ drawCircle(color = color, center = exclamationDotCenter, radius = exclamationRadiusPx)
+}
+
private abstract class BarsDependentDimensions(
val totalWidth: TextUnit,
val barsHorizontalPadding: TextUnit,
@@ -166,10 +212,19 @@
private object StackedMobileIconDimensions {
// Common dimensions
val IconHeightSp = 12.sp
+ val IconPaddingSp = 4.sp
+ val IconSpacingSp = 2.sp
val BarsVerticalPaddingSp = 1.5.sp
val BarsLevelIncrementSp = 1.sp
val SecondaryBarHeightSp = 3.sp
+ // Exclamation cutout dimensions
+ val ExclamationCutoutRadiusSp = 5.sp
+ val ExclamationDiameterSp = 1.5.sp
+ val ExclamationHeightSp = 4.5.sp
+ val ExclamationVerticalSpacing = 1.sp
+ val ExclamationHorizontalOffset = 1.sp
+
// Dimensions dependant on the number of total bars
val IconWidthFiveBarsSp = 18.5.sp
val IconWidthFourBarsSp = 16.sp
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt
index d3e3711..2433d11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt
@@ -27,6 +27,7 @@
import com.android.systemui.common.shared.model.Text.Companion.loadText
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon
/** Model describing the state that the QS Internet tile should be in. */
sealed interface InternetTileModel {
@@ -49,11 +50,14 @@
state.contentDescription = contentDescription.loadContentDescription(context)
// To support both SignalDrawable and other icons, give priority to icons over IDs
- if (icon != null) {
- state.icon = icon
- } else if (iconId != null) {
- state.icon = QSTileImpl.maybeLoadResourceIcon(iconId!!, context)
- }
+ state.icon =
+ when {
+ icon is ResourceIcon ->
+ QSTileImpl.maybeLoadResourceIcon((icon as ResourceIcon).resId, context)
+ icon != null -> icon
+ iconId != null -> QSTileImpl.maybeLoadResourceIcon(iconId!!, context)
+ else -> null
+ }
state.state =
if (this is Active) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
index 9ae2cb2..807e905 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
@@ -149,6 +149,9 @@
*/
val isHomeStatusBarAllowedByScene: StateFlow<Boolean>
+ /** True if the home status bar is showing, and there is no HUN happening */
+ val canShowOngoingActivityChips: Flow<Boolean>
+
/** True if the operator name view is not hidden due to HUN or other visibility state */
val shouldShowOperatorNameView: Flow<Boolean>
val isClockVisible: Flow<VisibilityModel>
@@ -412,6 +415,15 @@
)
.flowOn(bgDispatcher)
+ override val canShowOngoingActivityChips: Flow<Boolean> =
+ combine(
+ isHomeStatusBarAllowed,
+ keyguardInteractor.isSecureCameraActive,
+ headsUpNotificationInteractor.statusBarHeadsUpStatus,
+ ) { isHomeStatusBarAllowed, isSecureCameraActive, headsUpState ->
+ isHomeStatusBarAllowed && !isSecureCameraActive && !headsUpState.isPinned
+ }
+
override val isClockVisible: Flow<VisibilityModel> =
combine(
shouldHomeStatusBarBeVisible,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
index 88cf46a..b13e01b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
@@ -29,7 +29,6 @@
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
@@ -43,7 +42,6 @@
* Handles reading and writing of rotation lock settings per device state, as well as setting the
* rotation lock when device state changes.
*/
-@SysUISingleton
public final class DeviceStateRotationLockSettingController
implements Listenable, RotationLockController.RotationLockControllerCallback, Dumpable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
index 797aa1f..3ee7f33e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
@@ -27,8 +27,10 @@
import com.android.internal.view.RotationPolicy.RotationPolicyListener;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.rotationlock.DeviceStateAutoRotateModule.BoundsDeviceStateAutoRotateModule;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
+import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.inject.Inject;
@@ -50,21 +52,25 @@
};
private final RotationPolicyWrapper mRotationPolicy;
- private final DeviceStateRotationLockSettingController
+ private final Optional<DeviceStateRotationLockSettingController>
mDeviceStateRotationLockSettingController;
private final boolean mIsPerDeviceStateRotationLockEnabled;
@Inject
public RotationLockControllerImpl(
RotationPolicyWrapper rotationPolicyWrapper,
- DeviceStateRotationLockSettingController deviceStateRotationLockSettingController,
+ Optional<DeviceStateRotationLockSettingController>
+ deviceStateRotationLockSettingController,
@Named(DEVICE_STATE_ROTATION_LOCK_DEFAULTS) String[] deviceStateRotationLockDefaults
) {
mRotationPolicy = rotationPolicyWrapper;
- mDeviceStateRotationLockSettingController = deviceStateRotationLockSettingController;
mIsPerDeviceStateRotationLockEnabled = deviceStateRotationLockDefaults.length > 0;
- if (mIsPerDeviceStateRotationLockEnabled) {
- mCallbacks.add(mDeviceStateRotationLockSettingController);
+ mDeviceStateRotationLockSettingController =
+ deviceStateRotationLockSettingController;
+
+ if (mIsPerDeviceStateRotationLockEnabled
+ && mDeviceStateRotationLockSettingController.isPresent()) {
+ mCallbacks.add(mDeviceStateRotationLockSettingController.get());
}
setListening(true);
@@ -113,8 +119,9 @@
} else {
mRotationPolicy.unregisterRotationPolicyListener(mRotationPolicyListener);
}
- if (mIsPerDeviceStateRotationLockEnabled) {
- mDeviceStateRotationLockSettingController.setListening(listening);
+ if (mIsPerDeviceStateRotationLockEnabled
+ && mDeviceStateRotationLockSettingController.isPresent()) {
+ mDeviceStateRotationLockSettingController.get().setListening(listening);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
index 9ab8175..36513f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
@@ -24,6 +24,9 @@
import android.annotation.MainThread;
import android.app.IActivityManager;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ExecutorContentObserver;
@@ -51,6 +54,8 @@
import com.android.systemui.util.ListenerSet;
import com.android.systemui.util.settings.GlobalSettings;
+import java.util.List;
+import java.util.Objects;
import java.util.Random;
import java.util.concurrent.Executor;
@@ -63,12 +68,14 @@
private static final String LOG_TAG = "SNPC";
private final SensitiveNotificationProtectionControllerLogger mLogger;
private final PackageManager mPackageManager;
+ private final RoleManager mRoleManager;
// Packages exempt from projection session protections (if they start a projection session)
private final ArraySet<String> mSessionProtectionExemptPackages = new ArraySet<>();
// Packages exempt from individual notification protections (if they post a notification)
private final ArraySet<String> mNotificationProtectionExemptPackages = new ArraySet<>();
private final ListenerSet<Runnable> mListeners = new ListenerSet<>();
private volatile MediaProjectionInfo mProjection;
+ private ArraySet<RoleHolder> mNotificationProtectionExemptByRolePackages = new ArraySet<>();
private SensitiveNotificatioMediaProjectionSession mActiveMediaProjectionSession;
boolean mDisableScreenShareProtections = false;
@@ -128,6 +135,27 @@
}
};
+ @VisibleForTesting
+ final OnRoleHoldersChangedListener mRoleHoldersChangedListener =
+ new OnRoleHoldersChangedListener() {
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName,
+ @NonNull UserHandle user) {
+ if (!roleName.equals(AssociationRequest.DEVICE_PROFILE_APP_STREAMING)) {
+ return;
+ }
+
+ List<String> appStreamingRoleHolders = mRoleManager.getRoleHoldersAsUser(
+ roleName, user);
+ ArraySet<RoleHolder> roleHolders = new ArraySet<>();
+ for (String appStreamingRoleHolder : appStreamingRoleHolders) {
+ RoleHolder roleHolder = new RoleHolder(appStreamingRoleHolder, user);
+ roleHolders.add(roleHolder);
+ }
+ mNotificationProtectionExemptByRolePackages = roleHolders;
+ }
+ };
+
private void logSensitiveContentProtectionSessionStart(
long sessionId, int projectionAppUid, boolean exempt) {
mActiveMediaProjectionSession =
@@ -166,11 +194,13 @@
IActivityManager activityManager,
PackageManager packageManager,
TelephonyManager telephonyManager,
+ RoleManager roleManager,
@Main Handler mainHandler,
@Background Executor bgExecutor,
SensitiveNotificationProtectionControllerLogger logger) {
mLogger = logger;
mPackageManager = packageManager;
+ mRoleManager = roleManager;
if (!screenshareNotificationHiding()) {
return;
@@ -215,6 +245,8 @@
});
mediaProjectionManager.addCallback(mMediaProjectionCallback, mainHandler);
+ roleManager.addOnRoleHoldersChangedListenerAsUser(bgExecutor, mRoleHoldersChangedListener,
+ UserHandle.ALL);
}
@NonNull
@@ -314,6 +346,10 @@
Log.w(LOG_TAG, "Screen share protections exempt for package " + info.getPackageName()
+ " via permission");
return null;
+ } else if (info != null && isAppStreamingRoleHolder(info)) {
+ Log.w(LOG_TAG, "Screen share protections exempt for package " + info.getPackageName()
+ + " via role(s) held");
+ return null;
} else if (info != null && info.getLaunchCookie() != null) {
// Only enable sensitive content protection if sharing full screen
// Launch cookie only set (non-null) if sharing single app/task
@@ -323,11 +359,16 @@
return info;
}
+ private boolean isAppStreamingRoleHolder(@NonNull MediaProjectionInfo info) {
+ return mNotificationProtectionExemptByRolePackages.contains(
+ new RoleHolder(info.getPackageName(), info.getUserHandle()));
+ }
+
private boolean canRecordSensitiveContent(@NonNull String packageName) {
// RECORD_SENSITIVE_CONTENT is flagged api on sensitiveNotificationAppProtection
if (sensitiveNotificationAppProtection()) {
return mPackageManager.checkPermission(
- android.Manifest.permission.RECORD_SENSITIVE_CONTENT, packageName)
+ android.Manifest.permission.RECORD_SENSITIVE_CONTENT, packageName)
== PackageManager.PERMISSION_GRANTED;
}
return false;
@@ -382,4 +423,26 @@
boolean userForcesRedaction = entry.isChannelVisibilityPrivate();
return notificationRequestsRedaction || userForcesRedaction;
}
+
+ private static final class RoleHolder {
+ private final String mPackageName;
+ private final UserHandle mUserHandle;
+
+ RoleHolder(String packageName, UserHandle userHandle) {
+ mPackageName = packageName;
+ mUserHandle = userHandle;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RoleHolder that)) return false;
+ return Objects.equals(mPackageName, that.mPackageName) && Objects.equals(
+ mUserHandle, that.mUserHandle);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPackageName, mUserHandle);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt
index 33ed419..5dbe9b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt
@@ -21,29 +21,25 @@
import com.android.systemui.qs.QSModesEvent
import javax.inject.Inject
-class ModesDialogEventLogger
-@Inject
-constructor(
- private val uiEventLogger: UiEventLogger,
-) {
+class ModesDialogEventLogger @Inject constructor(private val uiEventLogger: UiEventLogger) {
fun logModeOn(mode: ZenMode) {
val id =
if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_ON else QSModesEvent.QS_MODES_MODE_ON
- uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName)
+ uiEventLogger.log(id, /* uid= */ 0, mode.ownerPackage)
}
fun logModeOff(mode: ZenMode) {
val id =
if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_OFF else QSModesEvent.QS_MODES_MODE_OFF
- uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName)
+ uiEventLogger.log(id, /* uid= */ 0, mode.ownerPackage)
}
fun logModeSettings(mode: ZenMode) {
val id =
if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_SETTINGS
else QSModesEvent.QS_MODES_MODE_SETTINGS
- uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName)
+ uiEventLogger.log(id, /* uid= */ 0, mode.ownerPackage)
}
fun logOpenDurationDialog(mode: ZenMode) {
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 07f1c34..dc07202 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
@@ -71,10 +71,10 @@
mode.id in prevIds -> true
// Mode is enabled -> show if active (so user can toggle off), or if it
// can be manually toggled on
- mode.rule.isEnabled -> mode.isActive || mode.rule.isManualInvocationAllowed
+ mode.isEnabled -> mode.isActive || mode.isManualInvocationAllowed
// Mode was created as disabled, or disabled by the app that owns it ->
// will be shown with a "Not set" text
- !mode.rule.isEnabled -> mode.status == ZenMode.Status.DISABLED_BY_OTHER
+ !mode.isEnabled -> mode.status == ZenMode.Status.DISABLED_BY_OTHER
else -> false
}
}
@@ -97,13 +97,13 @@
if (mode.isActive) R.string.zen_mode_on else R.string.zen_mode_off
),
onClick = {
- if (!mode.rule.isEnabled) {
+ if (!mode.isEnabled) {
openSettings(mode)
} else if (mode.isActive) {
dialogEventLogger.logModeOff(mode)
zenModeInteractor.deactivateMode(mode)
} else {
- if (mode.rule.isManualInvocationAllowed) {
+ if (mode.isManualInvocationAllowed) {
if (zenModeInteractor.shouldAskForZenDuration(mode)) {
dialogEventLogger.logOpenDurationDialog(mode)
// NOTE: The dialog handles turning on the mode itself.
@@ -144,10 +144,10 @@
* readers, and for the tile subtext will be augmented with the current status of the mode.
*/
private fun getModeDescription(mode: ZenMode, forAccessibility: Boolean): String? {
- if (!mode.rule.isEnabled) {
+ if (!mode.isEnabled) {
return context.resources.getString(R.string.zen_mode_set_up)
}
- if (!mode.rule.isManualInvocationAllowed && !mode.isActive) {
+ if (!mode.isManualInvocationAllowed && !mode.isActive) {
return context.resources.getString(R.string.zen_mode_no_manual_invocation)
}
return if (forAccessibility)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt
index a2125c8..d8a9527 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt
@@ -130,22 +130,32 @@
val easterEggGestureViewModel: EasterEggGestureViewModel,
) : TouchpadTutorialScreensProvider {
@Composable
- override fun BackGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
+ override fun BackGesture(
+ onDoneButtonClicked: () -> Unit,
+ onBack: () -> Unit,
+ isAutoProceed: Boolean,
+ ) {
BackGestureTutorialScreen(
backGestureScreenViewModel,
easterEggGestureViewModel,
onDoneButtonClicked,
onBack,
+ isAutoProceed,
)
}
@Composable
- override fun HomeGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
+ override fun HomeGesture(
+ onDoneButtonClicked: () -> Unit,
+ onBack: () -> Unit,
+ isAutoProceed: Boolean,
+ ) {
HomeGestureTutorialScreen(
homeGestureScreenViewModel,
easterEggGestureViewModel,
onDoneButtonClicked,
onBack,
+ isAutoProceed,
)
}
}
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 bce55cb..c28483c 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
@@ -33,6 +33,7 @@
easterEggGestureViewModel: EasterEggGestureViewModel,
onDoneButtonClicked: () -> Unit,
onBack: () -> Unit,
+ isAutoProceed: Boolean = false,
) {
val screenConfig =
TutorialScreenConfig(
@@ -47,6 +48,7 @@
bodyErrorResId = R.string.touchpad_back_gesture_error_body,
),
animations = TutorialScreenConfig.Animations(educationResId = R.raw.trackpad_back_edu),
+ hasNextButton = isAutoProceed,
)
GestureTutorialScreen(
screenConfig = screenConfig,
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
index 4acdb60..b238a8d 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
@@ -32,6 +32,7 @@
easterEggGestureViewModel: EasterEggGestureViewModel,
onDoneButtonClicked: () -> Unit,
onBack: () -> Unit,
+ isAutoProceed: Boolean = false,
) {
val screenConfig =
TutorialScreenConfig(
@@ -46,6 +47,7 @@
bodyErrorResId = R.string.touchpad_home_gesture_error_body,
),
animations = TutorialScreenConfig.Animations(educationResId = R.raw.trackpad_home_edu),
+ hasNextButton = isAutoProceed,
)
GestureTutorialScreen(
screenConfig = screenConfig,
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt
index 76f7609..47e27bc 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyLogger.kt
@@ -49,6 +49,7 @@
hallSensorToDeviceStateChangeMs,
onScreenTurningOnToOnDrawnMs,
onDrawnToOnScreenTurnedOnMs,
+ trackingResult,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
index e1640cd..66de522 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
@@ -37,12 +37,16 @@
import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.shared.system.SysUiStatsLog
import com.android.systemui.unfold.DisplaySwitchLatencyTracker.DisplaySwitchLatencyEvent
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker.TrackingResult.CORRUPTED
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker.TrackingResult.SUCCESS
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker.TrackingResult.TIMED_OUT
import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionStarted
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
import com.android.systemui.util.Compile
import com.android.systemui.util.Utils.isDeviceFoldable
import com.android.systemui.util.animation.data.repository.AnimationStatusRepository
+import com.android.systemui.util.kotlin.WithPrev
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.race
import com.android.systemui.util.time.SystemClock
@@ -56,7 +60,6 @@
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filter
@@ -116,10 +119,9 @@
latencyTracker.onActionStart(ACTION_SWITCH_DISPLAY_UNFOLD)
instantForTrack(TAG) { "unfold latency tracking started" }
}
+ val event = DisplaySwitchLatencyEvent().withBeforeFields(previousState.toStatsInt())
try {
withTimeout(SCREEN_EVENT_TIMEOUT) {
- val event =
- DisplaySwitchLatencyEvent().withBeforeFields(previousState.toStatsInt())
val displaySwitchTimeMs =
measureTimeMillis(systemClock) {
traceAsync(TAG, "displaySwitch") {
@@ -134,27 +136,43 @@
} catch (e: TimeoutCancellationException) {
instantForTrack(TAG) { "tracking timed out" }
latencyTracker.onActionCancel(ACTION_SWITCH_DISPLAY_UNFOLD)
+ logDisplaySwitchEvent(
+ event = event,
+ toFoldableDeviceState = newState,
+ displaySwitchTimeMs = SCREEN_EVENT_TIMEOUT.inWholeMilliseconds,
+ trackingResult = TIMED_OUT,
+ )
} catch (e: CancellationException) {
instantForTrack(TAG) { "new state interrupted, entering cool down" }
latencyTracker.onActionCancel(ACTION_SWITCH_DISPLAY_UNFOLD)
- startCoolDown()
+ startCoolDown(event)
}
}
}
}
@OptIn(FlowPreview::class)
- private fun startCoolDown() {
+ private fun startCoolDown(event: DisplaySwitchLatencyEvent) {
if (isCoolingDown) return
isCoolingDown = true
applicationScope.launch(context = backgroundDispatcher) {
val startTime = systemClock.elapsedRealtime()
+ var lastState: DeviceState? = null
try {
- startOrEndEvent.timeout(COOL_DOWN_DURATION).collect()
- } catch (e: TimeoutCancellationException) {
- instantForTrack(TAG) {
- "cool down finished, lasted ${systemClock.elapsedRealtime() - startTime} ms"
+ startOrEndEvent.timeout(COOL_DOWN_DURATION).collect {
+ if (it is WithPrev<*, *>) {
+ lastState = it.newValue as? DeviceState
+ }
}
+ } catch (e: TimeoutCancellationException) {
+ val totalCooldownTime = systemClock.elapsedRealtime() - startTime
+ logDisplaySwitchEvent(
+ event = event,
+ toFoldableDeviceState = lastState ?: DeviceState.UNKNOWN,
+ displaySwitchTimeMs = totalCooldownTime,
+ trackingResult = CORRUPTED,
+ )
+ instantForTrack(TAG) { "cool down finished, lasted $totalCooldownTime ms" }
isCoolingDown = false
}
}
@@ -164,12 +182,14 @@
event: DisplaySwitchLatencyEvent,
toFoldableDeviceState: DeviceState,
displaySwitchTimeMs: Long,
+ trackingResult: TrackingResult = SUCCESS,
) {
displaySwitchLatencyLogger.log(
event.withAfterFields(
- toFoldableDeviceState.toStatsInt(),
- displaySwitchTimeMs.toInt(),
+ toFoldableDeviceState,
+ displaySwitchTimeMs,
getCurrentState(),
+ trackingResult,
)
)
}
@@ -183,6 +203,13 @@
else -> FOLDABLE_DEVICE_STATE_UNKNOWN
}
+ private fun TrackingResult.toStatsInt(): Int =
+ when (this) {
+ SUCCESS -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__SUCCESS
+ CORRUPTED -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__CORRUPTED
+ TIMED_OUT -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__TIMED_OUT
+ }
+
private suspend fun waitForDisplaySwitch(toFoldableDeviceState: Int) {
val isTransitionEnabled =
unfoldTransitionInteractor.isAvailable &&
@@ -264,21 +291,24 @@
}
private fun DisplaySwitchLatencyEvent.withAfterFields(
- toFoldableDeviceState: Int,
- displaySwitchTimeMs: Int,
+ toFoldableDeviceState: DeviceState,
+ displaySwitchTimeMs: Long,
toState: Int,
+ trackingResult: TrackingResult,
): DisplaySwitchLatencyEvent {
log {
- "toFoldableDeviceState=$toFoldableDeviceState, " +
+ "trackingResult=$trackingResult, " +
+ "toFoldableDeviceState=$toFoldableDeviceState, " +
"toState=$toState, " +
"latencyMs=$displaySwitchTimeMs"
}
instantForTrack(TAG) { "toFoldableDeviceState=$toFoldableDeviceState, toState=$toState" }
return copy(
- toFoldableDeviceState = toFoldableDeviceState,
- latencyMs = displaySwitchTimeMs,
+ toFoldableDeviceState = toFoldableDeviceState.toStatsInt(),
+ latencyMs = displaySwitchTimeMs.toInt(),
toState = toState,
+ trackingResult = trackingResult.toStatsInt(),
)
}
@@ -312,8 +342,16 @@
val hallSensorToDeviceStateChangeMs: Int = VALUE_UNKNOWN,
val onScreenTurningOnToOnDrawnMs: Int = VALUE_UNKNOWN,
val onDrawnToOnScreenTurnedOnMs: Int = VALUE_UNKNOWN,
+ val trackingResult: Int =
+ SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__UNKNOWN_RESULT,
)
+ enum class TrackingResult {
+ SUCCESS,
+ CORRUPTED,
+ TIMED_OUT,
+ }
+
companion object {
private const val VALUE_UNKNOWN = -1
private const val TAG = "DisplaySwitchLatency"
diff --git a/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java b/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
index 32f2ca6..367f54c 100644
--- a/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
@@ -147,7 +147,7 @@
super.onDestroy();
}
- private void addUserNow(String userName, Drawable userIcon, Boolean isAdmin) {
+ private void addUserNow(String userName, Drawable userIcon, String iconPath, Boolean isAdmin) {
mSetupUserDialog.dismiss();
userName = (userName == null || userName.trim().isEmpty())
? getString(com.android.settingslib.R.string.user_new_user_name)
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserLockedInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserLockedInteractor.kt
index ef29a38..3bd8af6 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserLockedInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserLockedInteractor.kt
@@ -18,12 +18,20 @@
import android.os.UserHandle
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.user.data.repository.UserRepository
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOn
@SysUISingleton
-class UserLockedInteractor @Inject constructor(val userRepository: UserRepository) {
+class UserLockedInteractor
+@Inject
+constructor(
+ @Background val backgroundDispatcher: CoroutineDispatcher,
+ val userRepository: UserRepository,
+) {
fun isUserUnlocked(userHandle: UserHandle?): Flow<Boolean> =
- userRepository.isUserUnlocked(userHandle)
+ userRepository.isUserUnlocked(userHandle).flowOn(backgroundDispatcher)
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
index 5ef0319..0bdf99e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
@@ -27,6 +27,8 @@
import androidx.dynamicanimation.animation.FloatValueHolder
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
+import com.android.app.tracing.coroutines.launchInTraced
+import com.android.app.tracing.coroutines.launchTraced
import com.android.internal.R as internalR
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
@@ -47,9 +49,7 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.launch
private const val CLOSE_DRAWER_DELAY = 300L
// Ensure roundness and color of button is updated when progress is changed by a minimum fraction.
@@ -115,7 +115,9 @@
drawerContainer.setTransitionListener(ringerDrawerTransitionListener)
volumeDialogBackgroundView.background = volumeDialogBackgroundView.background.mutate()
ringerBackgroundView.background = ringerBackgroundView.background.mutate()
- launch { dialogViewModel.addTouchableBounds(ringerBackgroundView) }
+ launchTraced("VDRVB#addTouchableBounds") {
+ dialogViewModel.addTouchableBounds(ringerBackgroundView)
+ }
viewModel.ringerViewModel
.mapLatest { ringerState ->
@@ -222,7 +224,7 @@
}
}
}
- .launchIn(this)
+ .launchInTraced("VDRVB#ringerViewModel", this)
}
private suspend fun MotionLayout.animateAndBindDrawerButtons(
@@ -252,7 +254,7 @@
val selectedCornerRadius =
(selectedButton.background as GradientDrawable).cornerRadius
if (selectedCornerRadius.toInt() != selectedButtonUiModel.cornerRadius) {
- launch {
+ launchTraced("VDRVB#selectedButtonAnimation") {
selectedButton.animateTo(
selectedButtonUiModel,
if (uiModel.currentButtonIndex == count - 1) {
@@ -266,7 +268,7 @@
val unselectedCornerRadius =
(unselectedButton.background as GradientDrawable).cornerRadius
if (unselectedCornerRadius.toInt() != unselectedButtonUiModel.cornerRadius) {
- launch {
+ launchTraced("VDRVB#unselectedButtonAnimation") {
unselectedButton.animateTo(
unselectedButtonUiModel,
if (previousIndex == count - 1) {
@@ -277,7 +279,7 @@
)
}
}
- launch {
+ launchTraced("VDRVB#bindButtons") {
delay(CLOSE_DRAWER_DELAY)
bindButtons(viewModel, uiModel, onAnimationEnd, isAnimated = true)
}
@@ -386,7 +388,7 @@
roundnessAnimation.minimumVisibleChange = BUTTON_MIN_VISIBLE_CHANGE
colorAnimation.minimumVisibleChange = BUTTON_MIN_VISIBLE_CHANGE
coroutineScope {
- launch {
+ launchTraced("VDRVB#colorAnimation") {
colorAnimation.suspendAnimate { value ->
val currentIconColor =
rgbEvaluator.evaluate(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt
index 54f04e2..cf9136b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt
@@ -18,6 +18,8 @@
import android.view.View
import android.widget.ImageButton
+import com.android.app.tracing.coroutines.launchInTraced
+import com.android.app.tracing.coroutines.launchTraced
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
import com.android.systemui.volume.dialog.settings.ui.viewmodel.VolumeDialogSettingsButtonViewModel
@@ -25,9 +27,7 @@
import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
@VolumeDialogScope
class VolumeDialogSettingsButtonViewBinder
@@ -39,12 +39,12 @@
override fun CoroutineScope.bind(view: View) {
val button = view.requireViewById<ImageButton>(R.id.volume_dialog_settings)
- launch { dialogViewModel.addTouchableBounds(button) }
+ launchTraced("VDSBVB#addTouchableBounds") { dialogViewModel.addTouchableBounds(button) }
viewModel.isVisible
.onEach { isVisible -> button.visibility = if (isVisible) View.VISIBLE else View.GONE }
- .launchIn(this)
+ .launchInTraced("VDSBVB#isVisible", this)
- viewModel.icon.onEach { button.setImageDrawable(it) }.launchIn(this)
+ viewModel.icon.onEach { button.setImageDrawable(it) }.launchInTraced("VDSBVB#icon", this)
button.setOnClickListener { viewModel.onButtonClicked() }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
index 38feb69..c361b50 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
@@ -20,12 +20,12 @@
import androidx.dynamicanimation.animation.FloatValueHolder
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
+import com.android.app.tracing.coroutines.launchInTraced
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel.OverscrollEventModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@VolumeDialogSliderScope
@@ -62,7 +62,7 @@
}
}
}
- .launchIn(this)
+ .launchInTraced("VDOVB#overscrollEvent", this)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
index 2c9ee54..1c0fabe 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
@@ -39,7 +39,6 @@
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -99,7 +98,6 @@
hapticsViewModelFactory: SliderHapticsViewModel.Factory?,
modifier: Modifier = Modifier,
) {
- val coroutineScope = rememberCoroutineScope()
val colors =
SliderDefaults.colors(
thumbColor = MaterialTheme.colorScheme.primary,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
index 0d970e5..527f8bd 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
@@ -21,6 +21,8 @@
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.compose.ui.util.fastForEachIndexed
+import com.android.app.tracing.coroutines.launchInTraced
+import com.android.app.tracing.coroutines.launchTraced
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderComponent
@@ -29,9 +31,7 @@
import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
@VolumeDialogScope
class VolumeDialogSlidersViewBinder
@@ -50,7 +50,9 @@
val bottomSection: View = view.requireViewById(R.id.volume_dialog_bottom_section_container)
val topSection: View = view.requireViewById(R.id.volume_dialog_top_section_container)
- launch { dialogViewModel.addTouchableBounds(mainSliderContainer, floatingSlidersContainer) }
+ launchTraced("VDSVB#addTouchableBounds") {
+ dialogViewModel.addTouchableBounds(mainSliderContainer, floatingSlidersContainer)
+ }
viewModel.sliders
.onEach { uiModel ->
bindSlider(
@@ -69,7 +71,7 @@
bindSlider(sliderComponent, sliderContainer, arrayOf(sliderContainer))
}
}
- .launchIn(this)
+ .launchInTraced("VDSVB#sliders", this)
}
private fun CoroutineScope.bindSlider(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
index 98042d5..0c10aaa 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
@@ -17,18 +17,22 @@
package com.android.systemui.volume.dialog.ui.binder
import android.app.Dialog
+import android.content.Context
import android.view.View
+import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.WindowInsets
import androidx.compose.ui.util.lerp
-import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.view.updatePadding
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FloatValueHolder
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
+import com.android.app.tracing.coroutines.launchInTraced
+import com.android.app.tracing.coroutines.launchTraced
import com.android.internal.view.RotationPolicy
import com.android.systemui.common.ui.view.onApplyWindowInsets
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.awaitCancellationThenDispose
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
@@ -43,11 +47,9 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.scan
-import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
private const val SPRING_STIFFNESS = 700f
@@ -63,32 +65,43 @@
class VolumeDialogViewBinder
@Inject
constructor(
+ @Application context: Context,
private val viewModel: VolumeDialogViewModel,
private val jankListenerFactory: JankListenerFactory,
private val tracer: VolumeTracer,
private val viewBinders: List<@JvmSuppressWildcards ViewBinder>,
) {
+ private val halfOpenedOffsetPx: Float =
+ context.resources.getDimensionPixelSize(R.dimen.volume_dialog_half_opened_offset).toFloat()
+
fun CoroutineScope.bind(dialog: Dialog) {
val insets: MutableStateFlow<WindowInsets> =
MutableStateFlow(WindowInsets.Builder().build())
// Root view of the Volume Dialog.
- val root: MotionLayout = dialog.requireViewById(R.id.volume_dialog)
+ val root: ViewGroup = dialog.requireViewById(R.id.volume_dialog)
animateVisibility(root, dialog, viewModel.dialogVisibilityModel)
- viewModel.dialogTitle.onEach { dialog.window?.setTitle(it) }.launchIn(this)
- viewModel.motionState
- .scan(0) { acc, motionState ->
+ viewModel.dialogTitle
+ .onEach { dialog.window?.setTitle(it) }
+ .launchInTraced("VDVB#dialogTitle", this)
+ viewModel.isHalfOpened
+ .scan<Boolean, Boolean?>(null) { acc, isHalfOpened ->
// don't animate the initial state
- root.transitionToState(motionState, animate = acc != 0)
- acc + 1
+ root.applyVerticalOffset(
+ offsetPx = if (isHalfOpened) halfOpenedOffsetPx else 0f,
+ shouldAnimate = acc != null,
+ )
+ isHalfOpened
}
- .launchIn(this)
+ .launchInTraced("VDVB#isHalfOpened", this)
- launch { root.viewTreeObserver.listenToComputeInternalInsets() }
+ launchTraced("VDVB#viewTreeObserver") {
+ root.viewTreeObserver.listenToComputeInternalInsets()
+ }
- launch {
+ launchTraced("VDVB#insets") {
root
.onApplyWindowInsets { v, newInsets ->
val insetsValues = newInsets.getInsets(WindowInsets.Type.displayCutout())
@@ -135,7 +148,7 @@
junkListener?.let(animation::removeUpdateListener)
junkListener =
jankListenerFactory.show(view).also(animation::addUpdateListener)
- animation.suspendAnimate(FRACTION_SHOW)
+ animation.animateToFinalPosition(FRACTION_SHOW)
}
is VolumeDialogVisibilityModel.Dismissed -> {
tracer.traceVisibilityEnd(it)
@@ -150,7 +163,7 @@
}
}
}
- .launchIn(this)
+ .launchInTraced("VDVB#visibilityModel", this)
}
/**
@@ -180,11 +193,11 @@
continuation.invokeOnCancellation { removeOnComputeInternalInsetsListener(listener) }
}
- private fun MotionLayout.transitionToState(newState: Int, animate: Boolean) {
- if (animate) {
- transitionToState(newState)
- } else {
- jumpToState(newState)
+ private suspend fun View.applyVerticalOffset(offsetPx: Float, shouldAnimate: Boolean) {
+ if (!shouldAnimate) {
+ translationY = offsetPx
+ return
}
+ animate().setDuration(150).translationY(offsetPx).suspendAnimate()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt
index e47b531..8bfbc36 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt
@@ -56,18 +56,14 @@
configurationController: ConfigurationController,
) {
- val motionState: Flow<Int> =
+ val isHalfOpened: Flow<Boolean> =
combine(
devicePostureController.devicePosture(),
configurationController.onConfigChanged.onStart {
emit(context.resources.configuration)
},
) { devicePosture, configuration ->
- if (shouldOffsetVolumeDialog(devicePosture, configuration)) {
- R.id.volume_dialog_half_folded_constraint_set
- } else {
- R.id.volume_dialog_constraint_set
- }
+ shouldOffsetVolumeDialog(devicePosture, configuration)
}
val dialogVisibilityModel: Flow<VolumeDialogVisibilityModel> =
dialogVisibilityInteractor.dialogVisibility
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
index 2e63439..c2a495d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
@@ -64,6 +64,12 @@
"'wght' 500, 'ital' 0.5, 'GRAD' 450",
interp.lerp(startFont, endFont, 0.5f, 0.5f),
)
+
+ // Ensure axes rounded correctly to nearest step
+ assertSameAxes(
+ "'wght' 490, 'ital' 0.5, 'GRAD' 446",
+ interp.lerp(startFont, endFont, 0.492f, 0.492f),
+ )
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransitionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransitionTest.kt
index 4d0605f..90a8ad5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransitionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/ColorSchemeTransitionTest.kt
@@ -18,9 +18,12 @@
import android.animation.ValueAnimator
import android.graphics.Color
+import android.platform.test.annotations.DisableFlags
+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.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.media.controls.ui.view.GutsViewHolder
import com.android.systemui.media.controls.ui.view.MediaViewHolder
@@ -33,6 +36,7 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -49,7 +53,9 @@
class ColorSchemeTransitionTest : SysuiTestCase() {
private interface ExtractCB : (ColorScheme) -> Int
+
private interface ApplyCB : (Int) -> Unit
+
private lateinit var colorTransition: AnimatingColorTransition
private lateinit var colorSchemeTransition: ColorSchemeTransition
@@ -79,7 +85,7 @@
mediaViewHolder,
multiRippleController,
turbulenceNoiseController,
- animatingColorTransitionFactory
+ animatingColorTransitionFactory,
)
colorTransition =
@@ -154,10 +160,21 @@
verify(applyColor).invoke(expectedColor)
}
+ @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_A11Y_COLORS)
@Test
- fun testColorSchemeTransition_update() {
+ fun testColorSchemeTransition_update_legacy() {
colorSchemeTransition.updateColorScheme(colorScheme)
verify(mockAnimatingTransition, times(8)).updateColorScheme(colorScheme)
verify(gutsViewHolder).colorScheme = colorScheme
}
+
+ @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_A11Y_COLORS)
+ @Test
+ fun testColorSchemeTransition_update() {
+ colorSchemeTransition.updateColorScheme(colorScheme)
+ verify(mockAnimatingTransition, times(3)).updateColorScheme(colorScheme)
+ verify(gutsViewHolder).setColors(colorScheme)
+ verify(multiRippleController).updateColor(anyInt())
+ verify(turbulenceNoiseController).updateNoiseColor(anyInt())
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt
index a0be02f..bd4c5f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/ResizingTest.kt
@@ -43,6 +43,7 @@
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.shared.model.TileCategory
+import com.android.systemui.res.R
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -85,7 +86,9 @@
composeRule
.onNodeWithContentDescription("tileA")
- .performCustomAccessibilityActionWithLabel("Toggle size")
+ .performCustomAccessibilityActionWithLabel(
+ context.getString(R.string.accessibility_qs_edit_toggle_tile_size_action)
+ )
assertThat(tiles.find { it.tile.tileSpec.spec == "tileA" }?.width).isEqualTo(2)
}
@@ -101,7 +104,9 @@
composeRule
.onNodeWithContentDescription("tileD_large")
- .performCustomAccessibilityActionWithLabel("Toggle size")
+ .performCustomAccessibilityActionWithLabel(
+ context.getString(R.string.accessibility_qs_edit_toggle_tile_size_action)
+ )
assertThat(tiles.find { it.tile.tileSpec.spec == "tileD_large" }?.width).isEqualTo(1)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
index cfe34f4..a7464e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
@@ -39,6 +39,7 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import dagger.Lazy
import kotlin.test.assertTrue
import kotlinx.coroutines.Job
import org.junit.After
@@ -96,8 +97,7 @@
qsLogger,
bluetoothController,
featureFlags,
- bluetoothDetailsContentViewModel,
- )
+ ) { bluetoothDetailsContentViewModel }
tile.initialize()
testableLooper.processAllMessages()
@@ -308,7 +308,7 @@
qsLogger: QSLogger,
bluetoothController: BluetoothController,
featureFlags: FeatureFlagsClassic,
- bluetoothDetailsContentViewModel: BluetoothDetailsContentViewModel,
+ lazyBluetoothDetailsContentViewModel: Lazy<BluetoothDetailsContentViewModel>,
) :
BluetoothTile(
qsHost,
@@ -322,7 +322,7 @@
qsLogger,
bluetoothController,
featureFlags,
- bluetoothDetailsContentViewModel,
+ lazyBluetoothDetailsContentViewModel,
) {
var restrictionChecked: String? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 4ff09d3..81213ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -45,6 +45,9 @@
import static java.util.Collections.singletonList;
import android.os.SystemClock;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArrayMap;
@@ -74,10 +77,14 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -123,10 +130,13 @@
private CollectionReadyForBuildListener mReadyForBuildListener;
private List<NotificationEntryBuilder> mPendingSet = new ArrayList<>();
private List<NotificationEntry> mEntrySet = new ArrayList<>();
- private List<ListEntry> mBuiltList = new ArrayList<>();
+ private List<PipelineEntry> mBuiltList = new ArrayList<>();
private TestableStabilityManager mStabilityManager;
private TestableNotifFilter mFinalizeFilter;
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private Map<String, Integer> mNextIdMap = new ArrayMap<>();
private int mNextRank = 0;
@@ -561,6 +571,7 @@
}
@Test
+ @DisableFlags(NotificationBundleUi.FLAG_NAME)
public void testFilter_resetsInitalizationTime() {
// GIVEN a NotifFilter that filters out a specific package
NotifFilter filter1 = spy(new PackageFilter(PACKAGE_1));
@@ -584,6 +595,31 @@
}
@Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
+ public void testFilter_resetsInitializationTime_onRow() throws Exception {
+ // GIVEN a NotifFilter that filters out a specific package
+ NotifFilter filter1 = spy(new PackageFilter(PACKAGE_1));
+ mListBuilder.addFinalizeFilter(filter1);
+
+ // GIVEN a notification that was initialized 1 second ago that will be filtered out
+ final NotificationEntry entry = new NotificationEntryBuilder()
+ .setPkg(PACKAGE_1)
+ .setId(nextId(PACKAGE_1))
+ .setRank(nextRank())
+ .build();
+ entry.setRow(new NotificationTestHelper(mContext, mDependency).createRow());
+ entry.getRow().setInitializationTime(SystemClock.elapsedRealtime() - 1000);
+ assertTrue(entry.getRow().hasFinishedInitialization());
+
+ // WHEN the pipeline is kicked off
+ mReadyForBuildListener.onBuildList(singletonList(entry), "test");
+ mPipelineChoreographer.runIfScheduled();
+
+ // THEN the entry's initialization time is reset
+ assertFalse(entry.getRow().hasFinishedInitialization());
+ }
+
+ @Test
public void testNotifFiltersCanBePreempted() {
// GIVEN two notif filters
NotifFilter filter1 = spy(new PackageFilter(PACKAGE_2));
@@ -687,26 +723,26 @@
@Test
public void testNotifSectionsChildrenUpdated() {
- ArrayList<ListEntry> pkg1Entries = new ArrayList<>();
- ArrayList<ListEntry> pkg2Entries = new ArrayList<>();
- ArrayList<ListEntry> pkg3Entries = new ArrayList<>();
+ ArrayList<PipelineEntry> pkg1Entries = new ArrayList<>();
+ ArrayList<PipelineEntry> pkg2Entries = new ArrayList<>();
+ ArrayList<PipelineEntry> pkg3Entries = new ArrayList<>();
final NotifSectioner pkg1Sectioner = spy(new PackageSectioner(PACKAGE_1) {
@Override
- public void onEntriesUpdated(List<ListEntry> entries) {
+ public void onEntriesUpdated(List<PipelineEntry> entries) {
super.onEntriesUpdated(entries);
pkg1Entries.addAll(entries);
}
});
final NotifSectioner pkg2Sectioner = spy(new PackageSectioner(PACKAGE_2) {
@Override
- public void onEntriesUpdated(List<ListEntry> entries) {
+ public void onEntriesUpdated(List<PipelineEntry> entries) {
super.onEntriesUpdated(entries);
pkg2Entries.addAll(entries);
}
});
final NotifSectioner pkg3Sectioner = spy(new PackageSectioner(PACKAGE_3) {
@Override
- public void onEntriesUpdated(List<ListEntry> entries) {
+ public void onEntriesUpdated(List<PipelineEntry> entries) {
super.onEntriesUpdated(entries);
pkg3Entries.addAll(entries);
}
@@ -2442,7 +2478,7 @@
mBuiltList.size());
for (int i = 0; i < expectedEntries.length; i++) {
- ListEntry outEntry = mBuiltList.get(i);
+ PipelineEntry outEntry = mBuiltList.get(i);
ExpectedEntry expectedEntry = expectedEntries[i];
if (expectedEntry instanceof ExpectedNotif) {
@@ -2617,7 +2653,7 @@
}
@Override
- public int compare(@NonNull ListEntry o1, @NonNull ListEntry o2) {
+ public int compare(@NonNull PipelineEntry o1, @NonNull PipelineEntry o2) {
boolean contains1 = mPreferredPackages.contains(
o1.getRepresentativeEntry().getSbn().getPackageName());
boolean contains2 = mPreferredPackages.contains(
@@ -2655,37 +2691,37 @@
}
@Override
- public boolean isInSection(ListEntry entry) {
+ public boolean isInSection(PipelineEntry entry) {
return mPackages.contains(entry.getRepresentativeEntry().getSbn().getPackageName());
}
}
private static class RecordingOnBeforeTransformGroupsListener
implements OnBeforeTransformGroupsListener {
- List<ListEntry> mEntriesReceived;
+ List<PipelineEntry> mEntriesReceived;
@Override
- public void onBeforeTransformGroups(List<ListEntry> list) {
+ public void onBeforeTransformGroups(List<PipelineEntry> list) {
mEntriesReceived = new ArrayList<>(list);
}
}
private static class RecordingOnBeforeSortListener
implements OnBeforeSortListener {
- List<ListEntry> mEntriesReceived;
+ List<PipelineEntry> mEntriesReceived;
@Override
- public void onBeforeSort(List<ListEntry> list) {
+ public void onBeforeSort(List<PipelineEntry> list) {
mEntriesReceived = new ArrayList<>(list);
}
}
private static class RecordingOnBeforeRenderListener
implements OnBeforeRenderListListener {
- List<ListEntry> mEntriesReceived;
+ List<PipelineEntry> mEntriesReceived;
@Override
- public void onBeforeRenderList(List<ListEntry> list) {
+ public void onBeforeRenderList(List<PipelineEntry> list) {
mEntriesReceived = new ArrayList<>(list);
}
}
@@ -2764,7 +2800,7 @@
}
@Override
- public boolean isEntryReorderingAllowed(@NonNull ListEntry entry) {
+ public boolean isEntryReorderingAllowed(@NonNull PipelineEntry entry) {
return mAllowEntryReodering;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index a6722c5..24d8d1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -75,6 +75,7 @@
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiForceExpanded;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
+import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -589,6 +590,7 @@
}
@Test
+ @DisableFlags(NotificationBundleUi.FLAG_NAME)
public void testGetIsNonblockable() throws Exception {
ExpandableNotificationRow row =
mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
@@ -663,8 +665,8 @@
Assert.assertTrue(group.getAttachedChildren().isEmpty());
Assert.assertNotEquals(group, child.getNotificationParent());
verify(mNotificationTestHelper.getMockLogger()).logSkipAttachingKeepInParentChild(
- /*child=*/ child.getEntry(),
- /*newParent=*/ group.getEntry()
+ /*child=*/ child.getLoggingKey(),
+ /*newParent=*/ group.getLoggingKey()
);
}
@@ -680,7 +682,7 @@
Assert.assertNull(child.getNotificationParent());
Assert.assertFalse(child.keepInParentForDismissAnimation());
verify(mNotificationTestHelper.getMockLogger())
- .logCancelAppearDrawing(child.getEntry(), false);
+ .logCancelAppearDrawing(child.getLoggingKey(), false);
verifyNoMoreInteractions(mNotificationTestHelper.getMockLogger());
}
@@ -696,8 +698,8 @@
Assert.assertNull(child.getNotificationParent());
Assert.assertFalse(child.keepInParentForDismissAnimation());
verify(mNotificationTestHelper.getMockLogger()).logKeepInParentChildDetached(
- /*child=*/ child.getEntry(),
- /*oldParent=*/ group.getEntry()
+ /*child=*/ child.getLoggingKey(),
+ /*oldParent=*/ group.getLoggingKey()
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
index 47238fe..c874bc6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
@@ -36,6 +36,7 @@
import com.android.internal.widget.NotificationExpandButton
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.FeedbackIcon
+import com.android.systemui.statusbar.notification.collection.EntryAdapter
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.shared.NotificationBundleUi
@@ -82,6 +83,7 @@
fakeParent =
spy(FrameLayout(mContext, /* attrs= */ null).also { it.visibility = View.GONE })
val mockEntry = createMockNotificationEntry()
+ val mockEntryAdapter = createMockNotificationEntryAdapter()
row =
spy(
when (NotificationBundleUi.isEnabled) {
@@ -92,6 +94,7 @@
UserHandle.CURRENT
).apply {
entry = mockEntry
+ entryAdapter = mockEntryAdapter
}
}
false -> {
@@ -611,6 +614,7 @@
whenever(this.entry).thenReturn(notificationEntry)
whenever(this.context).thenReturn(mContext)
whenever(this.bubbleClickListener).thenReturn(View.OnClickListener {})
+ whenever(this.entryAdapter).thenReturn(createMockNotificationEntryAdapter())
}
private fun createMockNotificationEntry() =
@@ -624,6 +628,9 @@
whenever(sbnMock.user).thenReturn(userMock)
}
+ private fun createMockNotificationEntryAdapter() =
+ mock<EntryAdapter>()
+
private fun createLinearLayoutWithBottomMargin(bottomMargin: Int): LinearLayout {
val outerLayout = LinearLayout(mContext)
val innerLayout = LinearLayout(mContext)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
index 3d4c901..99b99ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
@@ -427,7 +427,6 @@
.setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
.setImportance(NotificationManager.IMPORTANCE_HIGH)
.build()
- whenever(row.getIsNonblockable()).thenReturn(false)
whenever(highPriorityProvider.isHighPriority(entry)).thenReturn(true)
val statusBarNotification = entry.sbn
gutsManager.initializeNotificationInfo(row, notificationInfoView)
@@ -463,7 +462,6 @@
NotificationEntryHelper.modifyRanking(row.entry)
.setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
.build()
- whenever(row.getIsNonblockable()).thenReturn(false)
val statusBarNotification = row.entry.sbn
val entry = row.entry
gutsManager.initializeNotificationInfo(row, notificationInfoView)
@@ -499,7 +497,6 @@
NotificationEntryHelper.modifyRanking(row.entry)
.setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
.build()
- whenever(row.getIsNonblockable()).thenReturn(false)
val statusBarNotification = row.entry.sbn
val entry = row.entry
gutsManager.initializeNotificationInfo(row, notificationInfoView)
@@ -566,7 +563,7 @@
): NotificationMenuRowPlugin.MenuItem {
val menuRow: NotificationMenuRowPlugin =
NotificationMenuRow(mContext, peopleNotificationIdentifier)
- menuRow.createMenu(row, row!!.entry.sbn)
+ menuRow.createMenu(row)
val menuItem = menuRow.getLongpressMenuItem(mContext)
Assert.assertNotNull(menuItem)
return menuItem
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 6ac20d4..955de273 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
@@ -675,7 +675,7 @@
@Test
public void testClearNotifications_clearAllInProgress() {
ExpandableNotificationRow row = createClearableRow();
- when(row.getEntry().hasFinishedInitialization()).thenReturn(true);
+ when(row.hasFinishedInitialization()).thenReturn(true);
doReturn(true).when(mStackScroller).isVisible(row);
mStackScroller.addContainerView(row);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 3190d3a..28eafa9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -76,6 +76,7 @@
import com.android.systemui.shade.ShadeControllerImpl;
import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.shade.data.repository.ShadeAnimationRepository;
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor;
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl;
import com.android.systemui.statusbar.CommandQueue;
@@ -171,6 +172,7 @@
private final FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private ExpandableNotificationRow mNotificationRow;
private ExpandableNotificationRow mBubbleNotificationRow;
+ private FakeShadeDialogContextInteractor mContextInteractor;
private final Answer<Void> mCallOnDismiss = answerVoid(
(OnDismissAction dismissAction, Runnable cancel,
@@ -187,6 +189,8 @@
mDependency,
TestableLooper.get(this));
+ mContextInteractor = new FakeShadeDialogContextInteractor(mContext);
+
// Create standard notification with contentIntent
mNotificationRow = notificationTestHelper.createRow();
StatusBarNotification sbn = mNotificationRow.getEntry().getSbn();
@@ -199,10 +203,6 @@
bubbleSbn.getNotification().contentIntent = mContentIntent;
bubbleSbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
-// ArrayList<NotificationEntry> activeNotifications = new ArrayList<>();
-// activeNotifications.add(mNotificationRow.getEntry());
-// activeNotifications.add(mBubbleNotificationRow.getEntry());
-// when(mEntryManager.getVisibleNotifications()).thenReturn(activeNotifications);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
when(mOnUserInteractionCallback.registerFutureDismissal(eq(mNotificationRow.getEntry()),
anyInt())).thenReturn(mFutureDismissalRunnable);
@@ -232,6 +232,7 @@
mNotificationActivityStarter =
new StatusBarNotificationActivityStarter(
getContext(),
+ mContextInteractor,
mHandler,
mUiBgExecutor,
mVisibilityProvider,
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 df5c6e9..a51e919 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
@@ -129,11 +129,7 @@
@Mock private lateinit var context: Context
private val mobileMappings = FakeMobileMappingsProxy()
- private val systemUiCarrierConfig =
- SystemUiCarrierConfig(
- SUB_1_ID,
- createTestConfig(),
- )
+ private val systemUiCarrierConfig = SystemUiCarrierConfig(SUB_1_ID, createTestConfig())
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
@@ -902,11 +898,7 @@
assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
- val intentWithoutInfo =
- spnIntent(
- showSpn = false,
- showPlmn = false,
- )
+ val intentWithoutInfo = spnIntent(showSpn = false, showPlmn = false)
captor.lastValue.onReceive(context, intentWithoutInfo)
@@ -929,11 +921,7 @@
assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
- val intentWithoutInfo =
- spnIntent(
- showSpn = false,
- showPlmn = false,
- )
+ val intentWithoutInfo = spnIntent(showSpn = false, showPlmn = false)
captor.lastValue.onReceive(context, intentWithoutInfo)
@@ -1301,7 +1289,6 @@
}
@Test
- @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
fun isNonTerrestrial_updatesFromCallback0() =
testScope.runTest {
val latest by collectLastValue(underTest.isNonTerrestrial)
@@ -1430,10 +1417,7 @@
return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager)
}
- private fun carrierIdIntent(
- subId: Int = SUB_1_ID,
- carrierId: Int,
- ): Intent =
+ private fun carrierIdIntent(subId: Int = SUB_1_ID, carrierId: Int): Intent =
Intent(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED).apply {
putExtra(EXTRA_SUBSCRIPTION_ID, subId)
putExtra(EXTRA_CARRIER_ID, carrierId)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
index 5739275..7e27783 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
@@ -25,6 +25,9 @@
import android.app.NotificationChannel
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.app.NotificationManager.VISIBILITY_NO_OVERRIDE
+import android.app.role.OnRoleHoldersChangedListener
+import android.app.role.RoleManager
+import android.companion.AssociationRequest
import android.content.pm.PackageManager
import android.media.projection.MediaProjectionInfo
import android.media.projection.MediaProjectionManager
@@ -89,6 +92,7 @@
@Mock private lateinit var activityManager: IActivityManager
@Mock private lateinit var mediaProjectionManager: MediaProjectionManager
@Mock private lateinit var packageManager: PackageManager
+ @Mock private lateinit var roleManager: RoleManager
@Mock private lateinit var telephonyManager: TelephonyManager
@Mock private lateinit var listener1: Runnable
@Mock private lateinit var listener2: Runnable
@@ -98,6 +102,7 @@
private lateinit var executor: FakeExecutor
private lateinit var globalSettings: FakeGlobalSettings
private lateinit var mediaProjectionCallback: MediaProjectionManager.Callback
+ private lateinit var roleHolderCallback: OnRoleHoldersChangedListener
private lateinit var controller: SensitiveNotificationProtectionControllerImpl
private lateinit var mediaProjectionInfo: MediaProjectionInfo
@@ -117,14 +122,14 @@
whenever(
packageManager.getPackageUidAsUser(
TEST_PROJECTION_PACKAGE_NAME,
- UserHandle.CURRENT.identifier
+ UserHandle.CURRENT.identifier,
)
)
.thenReturn(TEST_PROJECTION_PACKAGE_UID)
whenever(
packageManager.getPackageUidAsUser(
BUGREPORT_PACKAGE_NAME,
- UserHandle.CURRENT.identifier
+ UserHandle.CURRENT.identifier,
)
)
.thenReturn(BUGREPORT_PACKAGE_UID)
@@ -134,7 +139,7 @@
whenever(
packageManager.getPackageUidAsUser(
mContext.packageName,
- UserHandle.CURRENT.identifier
+ UserHandle.CURRENT.identifier,
)
)
.thenReturn(mContext.applicationInfo.uid)
@@ -155,9 +160,10 @@
activityManager,
packageManager,
telephonyManager,
+ roleManager,
mockExecutorHandler(executor),
executor,
- logger
+ logger,
)
// Process pending work (getting global setting and list of exemptions)
@@ -167,6 +173,9 @@
mediaProjectionCallback = withArgCaptor {
verify(mediaProjectionManager).addCallback(capture(), any())
}
+ roleHolderCallback = withArgCaptor {
+ verify(roleManager).addOnRoleHoldersChangedListenerAsUser(any(), capture(), any())
+ }
}
@After
@@ -307,7 +316,7 @@
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -322,7 +331,7 @@
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -340,6 +349,25 @@
}
@Test
+ fun isSensitiveStateActive_projectionActive_appStreamingRoleHolderExempt_false() {
+ setShareFullScreen()
+ whenever(
+ roleManager.getRoleHoldersAsUser(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mediaProjectionInfo.userHandle,
+ )
+ )
+ .thenReturn(listOf(TEST_PROJECTION_PACKAGE_NAME))
+ roleHolderCallback.onRoleHoldersChanged(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mediaProjectionInfo.userHandle,
+ )
+ mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+ assertFalse(controller.isSensitiveStateActive)
+ }
+
+ @Test
fun isSensitiveStateActive_projectionActive_disabledViaDevOption_false() {
setDisabledViaDeveloperOption()
mediaProjectionCallback.onStart(mediaProjectionInfo)
@@ -449,7 +477,7 @@
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -466,7 +494,7 @@
whenever(
packageManager.checkPermission(
android.Manifest.permission.RECORD_SENSITIVE_CONTENT,
- mediaProjectionInfo.packageName
+ mediaProjectionInfo.packageName,
)
)
.thenReturn(PackageManager.PERMISSION_GRANTED)
@@ -528,7 +556,7 @@
eq(TEST_PROJECTION_PACKAGE_UID),
eq(false),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -541,7 +569,7 @@
eq(TEST_PROJECTION_PACKAGE_UID),
eq(false),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -559,7 +587,7 @@
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -572,7 +600,7 @@
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -590,7 +618,7 @@
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -603,7 +631,7 @@
eq(TEST_PROJECTION_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -623,7 +651,7 @@
eq(mContext.applicationInfo.uid),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -636,7 +664,7 @@
eq(mContext.applicationInfo.uid),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -654,7 +682,7 @@
eq(BUGREPORT_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
@@ -667,7 +695,7 @@
eq(BUGREPORT_PACKAGE_UID),
eq(true),
eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP),
- eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI)
+ eq(FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__SYS_UI),
)
}
}
@@ -757,7 +785,7 @@
return setupNotificationEntry(
packageName,
overrideVisibility = true,
- overrideChannelVisibility = true
+ overrideChannelVisibility = true,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
index a1122c3..a553b17 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
@@ -18,10 +18,12 @@
import android.hardware.devicestate.DeviceStateManager
import android.hardware.devicestate.DeviceStateManager.FoldStateListener
+import android.platform.test.annotations.DisableFlags
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.util.LatencyTracker
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.foldedDeviceStateList
import com.android.systemui.halfFoldedDeviceState
@@ -46,6 +48,7 @@
@RunWith(AndroidJUnit4::class)
@SmallTest
+@DisableFlags(Flags.FLAG_UNFOLD_LATENCY_TRACKING_FIX)
class UnfoldLatencyTrackerTest : SysuiTestCase() {
@Mock lateinit var latencyTracker: LatencyTracker
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/BatteryMeterViewControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/BatteryMeterViewControllerKosmos.kt
new file mode 100644
index 0000000..f3bccb1
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/BatteryMeterViewControllerKosmos.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.battery
+
+import android.os.Handler
+import android.test.mock.MockContentResolver
+import com.android.systemui.flags.fake
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.settings.userTracker
+import com.android.systemui.statusbar.policy.batteryController
+import com.android.systemui.statusbar.policy.configurationController
+import com.android.systemui.tuner.tunerService
+import org.mockito.kotlin.mock
+
+val Kosmos.batteryMeterViewControllerFactory: BatteryMeterViewController.Factory by
+Kosmos.Fixture {
+ BatteryMeterViewController.Factory(
+ userTracker,
+ configurationController,
+ tunerService,
+ mock<Handler>(),
+ MockContentResolver(),
+ featureFlagsClassic.fake,
+ batteryController
+ )
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
index 0f21a16..b8b2ec5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.communal.domain.interactor
+import android.content.pm.UserInfo
import android.content.testableContext
import android.os.userManager
import com.android.systemui.broadcast.broadcastDispatcher
@@ -85,27 +86,28 @@
)
}
-suspend fun Kosmos.setCommunalEnabled(enabled: Boolean) {
+suspend fun Kosmos.setCommunalEnabled(enabled: Boolean): UserInfo {
fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, enabled)
- if (enabled) {
+ return if (enabled) {
fakeUserRepository.asMainUser()
} else {
fakeUserRepository.asDefaultUser()
}
}
-suspend fun Kosmos.setCommunalV2Enabled(enabled: Boolean) {
+suspend fun Kosmos.setCommunalV2Enabled(enabled: Boolean): UserInfo {
setCommunalV2ConfigEnabled(enabled)
- setCommunalEnabled(enabled)
+ return setCommunalEnabled(enabled)
}
-suspend fun Kosmos.setCommunalAvailable(available: Boolean) {
- setCommunalEnabled(available)
+suspend fun Kosmos.setCommunalAvailable(available: Boolean): UserInfo {
+ val user = setCommunalEnabled(available)
fakeKeyguardRepository.setKeyguardShowing(available)
fakeUserRepository.setUserUnlocked(FakeUserRepository.MAIN_USER_ID, available)
+ return user
}
-suspend fun Kosmos.setCommunalV2Available(available: Boolean) {
+suspend fun Kosmos.setCommunalV2Available(available: Boolean): UserInfo {
setCommunalV2ConfigEnabled(available)
- setCommunalAvailable(available)
+ return setCommunalAvailable(available)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
index 93a59eb..bdfa875 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
@@ -16,6 +16,9 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.domain.interactor.communalSceneInteractor
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.deviceentry.data.repository.deviceEntryRepository
import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
import com.android.systemui.kosmos.Kosmos
@@ -38,5 +41,8 @@
keyguardOcclusionInteractor = keyguardOcclusionInteractor,
deviceEntryRepository = deviceEntryRepository,
wakeToGoneInteractor = keyguardWakeDirectlyToGoneInteractor,
+ communalSettingsInteractor = communalSettingsInteractor,
+ communalSceneInteractor = communalSceneInteractor,
+ communalInteractor = communalInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToGlanceableHubTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..1eeecd4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToGlanceableHubTransitionViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.ui.glanceableHubBlurComponentFactory
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.aodToGlanceableHubTransitionViewModel by
+ Kosmos.Fixture {
+ AodToGlanceableHubTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt
index bd00455..2797b44 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt
@@ -47,5 +47,6 @@
primaryBouncerToLockscreenTransitionViewModel =
primaryBouncerToLockscreenTransitionViewModel,
lockscreenToDozingTransitionViewModel = lockscreenToDozingTransitionViewModel,
+ glanceableHubToAodTransitionViewModel = glanceableHubToAodTransitionViewModel,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToAodTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..6004c7f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToAodTransitionViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.glanceableHubToAodTransitionViewModel by
+ Kosmos.Fixture {
+ GlanceableHubToAodTransitionViewModel(
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
index 7835631..27ca0f86 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
@@ -94,5 +94,7 @@
shadeInteractor = shadeInteractor,
wallpaperFocalAreaInteractor = wallpaperFocalAreaInteractor,
dumpManager = dumpManager,
+ glanceableHubToAodTransitionViewModel = glanceableHubToAodTransitionViewModel,
+ aodToGlanceableHubTransitionViewModel = aodToGlanceableHubTransitionViewModel,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
index 8d4db8b..8a6f68c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.qs.panels.domain.interactor
+import com.android.internal.logging.uiEventLoggerFake
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.log.core.FakeLogBuffer
@@ -29,6 +30,7 @@
defaultLargeTilesRepository,
currentTilesInteractor,
qsPreferencesInteractor,
+ uiEventLoggerFake,
largeTileSpanRepository,
FakeLogBuffer.Factory.create(),
applicationCoroutineScope,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegateKosmos.kt
index c58d55e..73d8dc6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegateKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/dialog/QSResetDialogDelegateKosmos.kt
@@ -18,7 +18,14 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.qs.panels.domain.interactor.sizedTilesResetInteractor
+import com.android.systemui.shade.data.repository.shadeDialogContextInteractor
import com.android.systemui.statusbar.phone.systemUIDialogFactory
val Kosmos.qsResetDialogDelegateKosmos by
- Kosmos.Fixture { QSResetDialogDelegate(systemUIDialogFactory, sizedTilesResetInteractor) }
+ Kosmos.Fixture {
+ QSResetDialogDelegate(
+ systemUIDialogFactory,
+ shadeDialogContextInteractor,
+ sizedTilesResetInteractor,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelKosmos.kt
index 31be050..4f662e0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModelKosmos.kt
@@ -18,28 +18,37 @@
import com.android.systemui.brightness.ui.viewmodel.brightnessSliderViewModelFactory
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
+import com.android.systemui.media.controls.ui.controller.mediaCarouselController
+import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.qs.panels.ui.viewmodel.detailsViewModel
import com.android.systemui.qs.panels.ui.viewmodel.editModeViewModel
import com.android.systemui.qs.panels.ui.viewmodel.tileGridViewModelFactory
import com.android.systemui.qs.panels.ui.viewmodel.toolbar.toolbarViewModelFactory
import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory
+import org.mockito.kotlin.mock
val Kosmos.quickSettingsContainerViewModelFactory by
Kosmos.Fixture {
object : QuickSettingsContainerViewModel.Factory {
override fun create(
- supportsBrightnessMirroring: Boolean
+ supportsBrightnessMirroring: Boolean,
+ expansion: Float?,
): QuickSettingsContainerViewModel {
return QuickSettingsContainerViewModel(
- brightnessSliderViewModelFactory,
- shadeHeaderViewModelFactory,
- tileGridViewModelFactory,
- supportsBrightnessMirroring,
- editModeViewModel,
- detailsViewModel,
- toolbarViewModelFactory,
- shadeModeInteractor,
+ brightnessSliderViewModelFactory = brightnessSliderViewModelFactory,
+ shadeHeaderViewModelFactory = shadeHeaderViewModelFactory,
+ tileGridViewModelFactory = tileGridViewModelFactory,
+ supportsBrightnessMirroring = supportsBrightnessMirroring,
+ expansion = expansion,
+ editModeViewModel = editModeViewModel,
+ detailsViewModel = detailsViewModel,
+ toolbarViewModelFactory = toolbarViewModelFactory,
+ shadeModeInteractor = shadeModeInteractor,
+ mediaCarouselInteractor = mediaCarouselInteractor,
+ mediaCarouselController = mediaCarouselController,
+ mediaHost = mock<MediaHost>(),
)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt
index 3ed7302..e1ca86a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt
@@ -18,12 +18,8 @@
import android.content.applicationContext
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
-import org.mockito.kotlin.doReturn
-import org.mockito.kotlin.mock
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor
val Kosmos.shadeAnimationRepository by Kosmos.Fixture { ShadeAnimationRepository() }
val Kosmos.shadeDialogContextInteractor by
- Kosmos.Fixture {
- mock<ShadeDialogContextInteractor> { on { context } doReturn applicationContext }
- }
+ Kosmos.Fixture { FakeShadeDialogContextInteractor(applicationContext) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt
index ba7557e..26a441b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryKosmos.kt
@@ -30,7 +30,6 @@
import com.android.systemui.shade.display.StatusBarTouchShadeDisplayPolicy
import com.android.systemui.shade.domain.interactor.notificationElement
import com.android.systemui.shade.domain.interactor.qsElement
-import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.util.settings.fakeGlobalSettings
val Kosmos.defaultShadeDisplayPolicy: DefaultDisplayShadePolicy by
@@ -49,9 +48,8 @@
StatusBarTouchShadeDisplayPolicy(
displayRepository = displayRepository,
backgroundScope = testScope.backgroundScope,
- shadeInteractor = { shadeInteractor },
- notificationElement = { notificationElement },
qsShadeElement = { qsElement },
+ notificationElement = { notificationElement },
)
}
val Kosmos.shadeExpansionIntent: ShadeExpansionIntent by
@@ -65,6 +63,7 @@
defaultPolicy = defaultShadeDisplayPolicy,
shadeOnDefaultDisplayWhenLocked = true,
keyguardRepository = keyguardRepository,
+ displayRepository = displayRepository,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorKosmos.kt
index 6fd7cf6..2ea2119 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeHeaderClockInteractorKosmos.kt
@@ -16,14 +16,18 @@
package com.android.systemui.shade.domain.interactor
+import com.android.systemui.broadcast.broadcastDispatcher
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.plugins.activityStarter
import com.android.systemui.shade.data.repository.shadeHeaderClockRepository
+import com.android.systemui.util.time.systemClock
var Kosmos.shadeHeaderClockInteractor: ShadeHeaderClockInteractor by
Kosmos.Fixture {
ShadeHeaderClockInteractor(
repository = shadeHeaderClockRepository,
activityStarter = activityStarter,
+ broadcastDispatcher = broadcastDispatcher,
+ systemClock = systemClock,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt
index cfc2075..34e5bfd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt
@@ -17,8 +17,7 @@
package com.android.systemui.shade.ui.viewmodel
import android.content.applicationContext
-import com.android.systemui.battery.BatteryMeterViewController
-import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.battery.batteryMeterViewControllerFactory
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.plugins.activityStarter
import com.android.systemui.scene.domain.interactor.sceneInteractor
@@ -26,9 +25,8 @@
import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.domain.interactor.shadeModeInteractor
-import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
-import com.android.systemui.statusbar.phone.ui.TintedIconManager
+import com.android.systemui.statusbar.phone.ui.tintedIconManagerFactory
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.mobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.mobileIconsViewModel
import org.mockito.kotlin.mock
@@ -45,12 +43,9 @@
mobileIconsViewModel = mobileIconsViewModel,
privacyChipInteractor = privacyChipInteractor,
clockInteractor = shadeHeaderClockInteractor,
- tintedIconManagerFactory = mock<TintedIconManager.Factory>(),
- batteryMeterViewControllerFactory = mock<BatteryMeterViewController.Factory>(),
+ tintedIconManagerFactory = tintedIconManagerFactory,
+ batteryMeterViewControllerFactory = batteryMeterViewControllerFactory,
statusBarIconController = mock<StatusBarIconController>(),
- notificationIconContainerStatusBarViewBinder =
- mock<NotificationIconContainerStatusBarViewBinder>(),
- broadcastDispatcher = broadcastDispatcher,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderKosmos.kt
new file mode 100644
index 0000000..18d6520
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderKosmos.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.connectivity.ui
+
+import com.android.systemui.kosmos.Kosmos
+import org.mockito.kotlin.mock
+
+// NOTE: `mobileContextProvider` is a mock instance.
+val Kosmos.mobileContextProvider by
+Kosmos.Fixture {
+ mock<MobileContextProvider>()
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
index 562ac0c..804ec9f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
@@ -56,7 +56,7 @@
private StatusBarNotification mSbn = null;
/* ListEntry properties */
- private GroupEntry mParent;
+ private PipelineEntry mParent;
private NotifSection mNotifSection;
/* If set, use this creation time instead of mClock.uptimeMillis */
@@ -91,7 +91,7 @@
}
/** Update an the parent on an existing entry */
- public static void setNewParent(NotificationEntry entry, GroupEntry parent) {
+ public static void setNewParent(NotificationEntry entry, PipelineEntry parent) {
entry.setParent(parent);
}
@@ -135,7 +135,7 @@
/**
* Sets the parent.
*/
- public NotificationEntryBuilder setParent(@Nullable GroupEntry parent) {
+ public NotificationEntryBuilder setParent(@Nullable PipelineEntry parent) {
mParent = parent;
return this;
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
index e55cd0dc..da879d9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
@@ -22,12 +22,14 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.RowImageInflater
import com.android.systemui.statusbar.notification.row.shared.skeletonImageTransform
+import com.android.systemui.util.time.systemClock
var Kosmos.promotedNotificationContentExtractor by
Kosmos.Fixture {
PromotedNotificationContentExtractorImpl(
applicationContext,
skeletonImageTransform,
+ systemClock,
promotedNotificationLogger,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
index 8b19491..09c632c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
@@ -228,6 +228,7 @@
PromotedNotificationContentExtractorImpl(
context,
SkeletonImageTransform(context),
+ mFakeSystemClock,
PromotedNotificationLogger(logcatLogBuffer("PromotedNotifLog")),
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
index 7a2b7c2..51bb94f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
@@ -25,15 +25,18 @@
import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.aodBurnInViewModel
+import com.android.systemui.keyguard.ui.viewmodel.aodToGlanceableHubTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.aodToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.aodToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.aodToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.aodToPrimaryBouncerTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.dozingToDreamingTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.dozingToGlanceableHubTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.dozingToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.dozingToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.dozingToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.dreamingToLockscreenTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.goneToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.goneToDozingTransitionViewModel
@@ -81,6 +84,7 @@
aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
aodToOccludedTransitionViewModel = aodToOccludedTransitionViewModel,
aodToPrimaryBouncerTransitionViewModel = aodToPrimaryBouncerTransitionViewModel,
+ dozingToDreamingTransitionViewModel = dozingToDreamingTransitionViewModel,
dozingToGlanceableHubTransitionViewModel = dozingToGlanceableHubTransitionViewModel,
dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel,
dozingToOccludedTransitionViewModel = dozingToOccludedTransitionViewModel,
@@ -110,5 +114,7 @@
headsUpNotificationInteractor = { headsUpNotificationInteractor },
largeScreenHeaderHelperLazy = { largeScreenHeaderHelper },
unfoldTransitionInteractor = unfoldTransitionInteractor,
+ glanceableHubToAodTransitionViewModel = glanceableHubToAodTransitionViewModel,
+ aodToGlanceableHubTransitionViewModel = aodToGlanceableHubTransitionViewModel,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterKosmos.kt
index d787e2c..91404e0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterKosmos.kt
@@ -30,6 +30,7 @@
import com.android.systemui.plugins.activityStarter
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.settings.userTracker
+import com.android.systemui.shade.data.repository.shadeDialogContextInteractor
import com.android.systemui.shade.domain.interactor.panelExpansionInteractor
import com.android.systemui.shade.domain.interactor.shadeAnimationInteractor
import com.android.systemui.shade.shadeController
@@ -52,6 +53,7 @@
Kosmos.Fixture {
StatusBarNotificationActivityStarter(
applicationContext,
+ shadeDialogContextInteractor,
fakeExecutorHandler,
fakeExecutor,
notificationVisibilityProvider,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/DisableChipsModernization.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/DisableChipsModernization.kt
new file mode 100644
index 0000000..69eecc0
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/DisableChipsModernization.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.platform.test.annotations.DisableFlags
+
+/** Disables all the flags necessary for [StatusBarChipsModernization.isEnabled] to return false. */
+@DisableFlags(StatusBarChipsModernization.FLAG_NAME)
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
+annotation class DisableChipsModernization
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/EnableChipsModernization.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/EnableChipsModernization.kt
new file mode 100644
index 0000000..caa4373
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/EnableChipsModernization.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.platform.test.annotations.EnableFlags
+import com.android.systemui.statusbar.core.StatusBarRootModernization
+
+/** Enables all the flags necessary for [StatusBarChipsModernization.isEnabled] to return true. */
+@EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
+annotation class EnableChipsModernization
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallTestHelper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallTestHelper.kt
index d09d010..8ff7c7d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallTestHelper.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/shared/model/OngoingCallTestHelper.kt
@@ -76,6 +76,7 @@
promotedContent: PromotedNotificationContentModel? = null,
contentIntent: PendingIntent? = null,
uid: Int = DEFAULT_UID,
+ appName: String = "Fake name",
) {
if (StatusBarChipsModernization.isEnabled) {
activeNotificationListRepository.addNotif(
@@ -87,6 +88,7 @@
contentIntent = contentIntent,
promotedContent = promotedContent,
uid = uid,
+ appName = appName,
)
)
} else {
@@ -96,6 +98,7 @@
notificationIcon = statusBarChipIconView,
intent = contentIntent,
notificationKey = key,
+ appName = appName,
promotedContent = promotedContent,
)
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerKosmos.kt
new file mode 100644
index 0000000..0a387f8
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerKosmos.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ui
+
+import com.android.systemui.kosmos.Kosmos
+import org.mockito.kotlin.mock
+
+// NOTE: `statusBarIconController` is a mock instance.
+val Kosmos.statusBarIconController by Kosmos.Fixture {
+ mock<StatusBarIconControllerImpl>()
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ui/TintedIconManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ui/TintedIconManagerKosmos.kt
new file mode 100644
index 0000000..8e13b62
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ui/TintedIconManagerKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ui
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.connectivity.ui.mobileContextProvider
+import com.android.systemui.statusbar.pipeline.mobile.ui.mobileUiAdapter
+import com.android.systemui.statusbar.pipeline.wifi.ui.wifiUiAdapter
+
+val Kosmos.tintedIconManagerFactory by
+Kosmos.Fixture {
+ TintedIconManager.Factory(
+ wifiUiAdapter,
+ mobileUiAdapter,
+ mobileContextProvider,
+ )
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelKosmos.kt
new file mode 100644
index 0000000..5089545
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelKosmos.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.backgroundScope
+import com.android.systemui.log.table.logcatTableLogBuffer
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.airplaneModeInteractor
+
+val Kosmos.airplaneModeViewModel by Kosmos.Fixture {
+ AirplaneModeViewModelImpl(
+ airplaneModeInteractor,
+ logcatTableLogBuffer(this, "AirplaneModeTableLogBuffer"),
+ backgroundScope,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
index 9b6f205..8fa82ca 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
@@ -58,6 +58,8 @@
override val defaultDataSubId: MutableStateFlow<Int?> = MutableStateFlow(DEFAULT_DATA_SUB_ID)
+ override val activeMobileDataSubscriptionId: MutableStateFlow<Int?> = MutableStateFlow(null)
+
private val _activeDataConnectionHasDataEnabled = MutableStateFlow(false)
override val activeDataConnectionHasDataEnabled = _activeDataConnectionHasDataEnabled
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapterKosmos.kt
new file mode 100644
index 0000000..a87d3b0
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapterKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.statusbar.phone.ui.statusBarIconController
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.mobileIconsViewModel
+
+val Kosmos.mobileUiAdapter by
+ Kosmos.Fixture {
+ MobileUiAdapter(
+ statusBarIconController,
+ mobileIconsViewModel,
+ mobileViewLogger,
+ applicationCoroutineScope,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerKosmos.kt
new file mode 100644
index 0000000..206ecd3
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui
+
+import com.android.systemui.kosmos.Kosmos
+import org.mockito.kotlin.mock
+
+// NOTE: `mobileViewLogger` is a mock instance.
+val Kosmos.mobileViewLogger by Kosmos.Fixture { mock<MobileViewLogger>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelKosmos.kt
new file mode 100644
index 0000000..880ba5e
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.stackedMobileIconViewModel: StackedMobileIconViewModel by
+ Kosmos.Fixture { StackedMobileIconViewModel(mobileIconsViewModel) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapterKosmos.kt
new file mode 100644
index 0000000..d4d5896
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapterKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.wifi.ui
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.phone.ui.statusBarIconController
+import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.wifiViewModel
+
+val Kosmos.wifiUiAdapter by
+ Kosmos.Fixture {
+ WifiUiAdapter(
+ statusBarIconController,
+ wifiViewModel,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelKosmos.kt
new file mode 100644
index 0000000..3f876ef
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelKosmos.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel
+
+import android.content.applicationContext
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.log.table.logcatTableLogBuffer
+import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.airplaneModeViewModel
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.wifiInteractor
+import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
+import kotlinx.coroutines.flow.flowOf
+import org.mockito.kotlin.mock
+
+val Kosmos.wifiViewModel by
+ Kosmos.Fixture {
+ WifiViewModel(
+ airplaneModeViewModel,
+ { flowOf(false) },
+ mock<ConnectivityConstants>(),
+ applicationContext,
+ logcatTableLogBuffer(this, "WifiViewModelTest"),
+ wifiInteractor,
+ applicationCoroutineScope,
+ mock<WifiConstants>(),
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserLockedInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserLockedInteractorKosmos.kt
index fd95508..933c351 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserLockedInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/UserLockedInteractorKosmos.kt
@@ -17,7 +17,10 @@
package com.android.systemui.user.domain.interactor
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.user.data.repository.userRepository
val Kosmos.userLockedInteractor by
- Kosmos.Fixture { UserLockedInteractor(userRepository = userRepository) }
+ Kosmos.Fixture {
+ UserLockedInteractor(backgroundDispatcher = testDispatcher, userRepository = userRepository)
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/time/FakeSystemClockKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/time/FakeSystemClockKosmos.kt
index a209ec9..b23ccbf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/time/FakeSystemClockKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/time/FakeSystemClockKosmos.kt
@@ -14,19 +14,23 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.util.time
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.currentTime
-val Kosmos.systemClock by
+var Kosmos.systemClock by
Kosmos.Fixture<SystemClock> {
mock {
whenever(elapsedRealtime()).thenAnswer { testScope.currentTime }
whenever(uptimeMillis()).thenAnswer { testScope.currentTime }
+ whenever(currentTimeMillis()).thenAnswer { testScope.currentTime }
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinderKosmos.kt
index 386e0fe..5411884 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinderKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.volume.dialog.ui.binder
+import android.content.applicationContext
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.volume.dialog.ringer.volumeDialogRingerViewBinder
import com.android.systemui.volume.dialog.settings.ui.binder.volumeDialogSettingsButtonViewBinder
@@ -27,6 +28,7 @@
val Kosmos.volumeDialogViewBinder by
Kosmos.Fixture {
VolumeDialogViewBinder(
+ applicationContext,
volumeDialogViewModel,
jankListenerFactory,
volumeTracer,
diff --git a/packages/Vcn/TEST_MAPPING b/packages/Vcn/TEST_MAPPING
index 9722a83..9ca5304 100644
--- a/packages/Vcn/TEST_MAPPING
+++ b/packages/Vcn/TEST_MAPPING
@@ -14,5 +14,13 @@
{
"name": "CtsVcnTestCases"
}
+ ],
+ "tethering-mainline-presubmit": [
+ {
+ "name": "FrameworksVcnTests"
+ },
+ {
+ "name": "CtsVcnTestCases"
+ }
]
}
\ No newline at end of file
diff --git a/packages/Vcn/framework-b/Android.bp b/packages/Vcn/framework-b/Android.bp
index edb22c0..c531233 100644
--- a/packages/Vcn/framework-b/Android.bp
+++ b/packages/Vcn/framework-b/Android.bp
@@ -77,8 +77,7 @@
],
soong_config_variables: {
is_vcn_in_mainline: {
- //TODO: b/380155299 Make it Baklava when aidl tool can understand it
- min_sdk_version: "current",
+ min_sdk_version: "36",
static_libs: ["android.net.vcn.flags-aconfig-java"],
apex_available: ["com.android.tethering"],
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 65550f2..ccbc46f 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -121,6 +121,7 @@
name: "ravenwood-helper-framework-runtime",
srcs: [
"runtime-helper-src/framework/**/*.java",
+ ":framework-graphics-srcs",
],
static_libs: [
"ravenwood-runtime-common",
@@ -278,6 +279,7 @@
cc_library_host_shared {
name: "libravenwood_runtime",
defaults: ["ravenwood_jni_defaults"],
+ header_libs: ["libicuuc_headers"],
srcs: [
"runtime-jni/ravenwood_runtime.cpp",
"runtime-jni/ravenwood_os_constants.cpp",
@@ -372,6 +374,13 @@
visibility: ["//visibility:private"],
}
+java_library {
+ name: "ext-ravenwood",
+ installable: false,
+ static_libs: ["ext"],
+ visibility: ["//visibility:private"],
+}
+
filegroup {
name: "ravenwood-data",
device_common_srcs: [
@@ -637,6 +646,7 @@
libs: [
"100-framework-minus-apex.ravenwood",
"200-kxml2-android",
+ "ext-ravenwood",
"ravenwood-runtime-common-ravenwood",
diff --git a/ravenwood/Framework.bp b/ravenwood/Framework.bp
index 71496b0..e366771 100644
--- a/ravenwood/Framework.bp
+++ b/ravenwood/Framework.bp
@@ -419,11 +419,13 @@
"--out-impl-jar $(location ravenwood.jar) " +
"--in-jar $(location :framework-graphics.impl{.jar}) " +
- "--policy-override-file $(location :ravenwood-common-policies) ",
+ "--policy-override-file $(location :ravenwood-common-policies) " +
+ "--policy-override-file $(location :framework-graphics-ravenwood-policies) ",
srcs: [
":framework-graphics.impl{.jar}",
":ravenwood-common-policies",
+ ":framework-graphics-ravenwood-policies",
":ravenwood-standard-options",
],
out: [
diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING
index cb54e9f..df63cb9 100644
--- a/ravenwood/TEST_MAPPING
+++ b/ravenwood/TEST_MAPPING
@@ -2,6 +2,7 @@
"presubmit": [
{ "name": "tiny-framework-dump-test" },
{ "name": "hoststubgentest" },
+ { "name": "ravenhelpertest" },
{ "name": "hoststubgen-test-tiny-test" },
{ "name": "hoststubgen-invoke-test" },
{ "name": "RavenwoodMockitoTest_device" },
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodContext.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodContext.java
index a332633..9e6b12f 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodContext.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodContext.java
@@ -230,6 +230,16 @@
return mAppContext;
}
+ @Override
+ public boolean isRestricted() {
+ return false;
+ }
+
+ @Override
+ public boolean canLoadUnsafeResources() {
+ return true;
+ }
+
/**
* Wrap the given {@link Supplier} to become memoized.
*
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodNativeLoader.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodNativeLoader.java
index a208d6d..7e935d0 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodNativeLoader.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodNativeLoader.java
@@ -48,6 +48,7 @@
android.content.res.AssetManager.class,
android.content.res.StringBlock.class,
android.content.res.XmlBlock.class,
+ android.text.AndroidCharacter.class,
};
/**
@@ -61,15 +62,49 @@
android.graphics.Path.class,
android.graphics.Color.class,
android.graphics.ColorSpace.class,
+ android.graphics.Bitmap.class,
+ android.graphics.BitmapFactory.class,
+ android.graphics.BitmapRegionDecoder.class,
+ android.graphics.Camera.class,
+ android.graphics.Canvas.class,
+ android.graphics.CanvasProperty.class,
+ android.graphics.ColorFilter.class,
+ android.graphics.DrawFilter.class,
+ android.graphics.FontFamily.class,
+ android.graphics.Gainmap.class,
+ android.graphics.ImageDecoder.class,
+ android.graphics.MaskFilter.class,
+ android.graphics.NinePatch.class,
+ android.graphics.Paint.class,
+ android.graphics.PathEffect.class,
+ android.graphics.PathIterator.class,
+ android.graphics.PathMeasure.class,
+ android.graphics.Picture.class,
+ android.graphics.RecordingCanvas.class,
+ android.graphics.Region.class,
+ android.graphics.RenderNode.class,
+ android.graphics.Shader.class,
+ android.graphics.RenderEffect.class,
+ android.graphics.Typeface.class,
+ android.graphics.YuvImage.class,
+ android.graphics.fonts.Font.class,
+ android.graphics.fonts.FontFamily.class,
+ android.graphics.text.LineBreaker.class,
+ android.graphics.text.MeasuredText.class,
+ android.graphics.text.TextRunShaper.class,
+ android.graphics.text.GraphemeBreak.class,
+ android.util.PathParser.class,
};
/**
* Extra strings needed to pass to register_android_graphics_classes().
*
- * `android.graphics.Graphics` is not actually a class, so we just hardcode it here.
+ * Several entries are not actually a class, so we just hardcode them here.
*/
public final static String[] GRAPHICS_EXTRA_INIT_PARAMS = new String[] {
- "android.graphics.Graphics"
+ "android.graphics.Graphics",
+ "android.graphics.ByteBufferStreamAdaptor",
+ "android.graphics.CreateJavaOutputStreamAdaptor"
};
private RavenwoodNativeLoader() {
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
index ae88bb2..f205d23 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
@@ -43,6 +43,7 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
+import android.graphics.Typeface;
import android.icu.util.ULocale;
import android.os.Binder;
import android.os.Build;
@@ -246,6 +247,13 @@
// Do the basic set up for the android sysprops.
RavenwoodSystemProperties.initialize();
+ // Set ICU data file
+ String icuData = RavenwoodCommonUtils.getRavenwoodRuntimePath()
+ + "ravenwood-data/"
+ + RavenwoodRuntimeNative.getIcuDataName()
+ + ".dat";
+ RavenwoodRuntimeNative.setSystemProperty("ro.icu.data.path", icuData);
+
// Enable all log levels for native logging, until we'll have a way to change the native
// side log level at runtime.
// Do this after loading RAVENWOOD_NATIVE_RUNTIME_NAME (which backs Os.setenv()),
@@ -268,6 +276,11 @@
Objects.requireNonNull(Build.TYPE);
Objects.requireNonNull(Build.VERSION.SDK);
+ // Fonts can only be initialized once
+ Typeface.init();
+ Typeface.loadPreinstalledSystemFontMap();
+ Typeface.loadNativeSystemFonts();
+
System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1");
// This will let AndroidJUnit4 use the original runner.
System.setProperty("android.junit.runner",
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodJdkPatch.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodJdkPatch.java
index 96aed4b..d5a96dd 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodJdkPatch.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodJdkPatch.java
@@ -20,6 +20,7 @@
import java.io.FileDescriptor;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.regex.Pattern;
/**
* Class to host APIs that exist in libcore, but not in standard JRE.
@@ -46,4 +47,22 @@
final var it = map.entrySet().iterator();
return it.hasNext() ? it.next() : null;
}
+
+ /**
+ * Implements Pattern.compile(String)
+ *
+ * ART always assumes UNICODE_CHARACTER_CLASS is set.
+ */
+ public static Pattern compilePattern(String regex) {
+ return Pattern.compile(regex, Pattern.UNICODE_CHARACTER_CLASS);
+ }
+
+ /**
+ * Implements Pattern.compile(String, int)
+ *
+ * ART always assumes UNICODE_CHARACTER_CLASS is set.
+ */
+ public static Pattern compilePattern(String regex, int flag) {
+ return Pattern.compile(regex, flag | Pattern.UNICODE_CHARACTER_CLASS);
+ }
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
index acbcdf1..0d82a86 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
@@ -66,6 +66,8 @@
public static native int gettid();
+ public static native String getIcuDataName();
+
public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence);
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/dalvik/system/CloseGuard.java b/ravenwood/runtime-helper-src/libcore-fake/dalvik/system/CloseGuard.java
new file mode 100644
index 0000000..82bab64
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/dalvik/system/CloseGuard.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 dalvik.system;
+
+/**
+ * A no-op copy of libcore/dalvik/src/main/java/dalvik/system/CloseGuard.java
+ */
+public final class CloseGuard {
+
+ /**
+ * Returns a CloseGuard instance. {@code #open(String)} can be used to set
+ * up the instance to warn on failure to close.
+ *
+ * @return {@link CloseGuard} instance.
+ *
+ * @hide
+ */
+ public static CloseGuard get() {
+ return new CloseGuard();
+ }
+
+ /**
+ * Enables/disables stack capture and tracking. A call stack is captured
+ * during open(), and open/close events are reported to the Tracker, only
+ * if enabled is true. If a stack trace was captured, the {@link
+ * #getReporter() reporter} is informed of unclosed resources; otherwise a
+ * one-line warning is logged.
+ *
+ * @param enabled whether stack capture and tracking is enabled.
+ *
+ * @hide
+ */
+ public static void setEnabled(boolean enabled) {
+ }
+
+ /**
+ * True if CloseGuard stack capture and tracking are enabled.
+ *
+ * @hide
+ */
+ public static boolean isEnabled() {
+ return false;
+ }
+
+ /**
+ * Used to replace default Reporter used to warn of CloseGuard
+ * violations when stack tracking is enabled. Must be non-null.
+ *
+ * @param rep replacement for default Reporter.
+ *
+ * @hide
+ */
+ public static void setReporter(Reporter rep) {
+ if (rep == null) {
+ throw new NullPointerException("reporter == null");
+ }
+ }
+
+ /**
+ * Returns non-null CloseGuard.Reporter.
+ *
+ * @return CloseGuard's Reporter.
+ *
+ * @hide
+ */
+ public static Reporter getReporter() {
+ return null;
+ }
+
+ /**
+ * Sets the {@link Tracker} that is notified when resources are allocated and released.
+ * The Tracker is invoked only if CloseGuard {@link #isEnabled()} held when {@link #open()}
+ * was called. A null argument disables tracking.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ *
+ * @hide
+ */
+ public static void setTracker(Tracker tracker) {
+ }
+
+ /**
+ * Returns {@link #setTracker(Tracker) last Tracker that was set}, or null to indicate
+ * there is none.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ *
+ * @hide
+ */
+ public static Tracker getTracker() {
+ return null;
+ }
+
+ private CloseGuard() {}
+
+ /**
+ * {@code open} initializes the instance with a warning that the caller
+ * should have explicitly called the {@code closer} method instead of
+ * relying on finalization.
+ *
+ * @param closer non-null name of explicit termination method. Printed by warnIfOpen.
+ * @throws NullPointerException if closer is null.
+ *
+ * @hide
+ */
+ public void open(String closer) {
+ openWithCallSite(closer, null /* callsite */);
+ }
+
+ /**
+ * Like {@link #open(String)}, but with explicit callsite string being passed in for better
+ * performance.
+ * <p>
+ * This only has better performance than {@link #open(String)} if {@link #isEnabled()} returns {@code true}, which
+ * usually shouldn't happen on release builds.
+ *
+ * @param closer Non-null name of explicit termination method. Printed by warnIfOpen.
+ * @param callsite Non-null string uniquely identifying the callsite.
+ *
+ * @hide
+ */
+ public void openWithCallSite(String closer, String callsite) {
+ }
+
+ // We keep either an allocation stack containing the closer String or, when
+ // in disabled state, just the closer String.
+ // We keep them in a single field only to minimize overhead.
+ private Object /* String or Throwable */ closerNameOrAllocationInfo;
+
+ /**
+ * Marks this CloseGuard instance as closed to avoid warnings on
+ * finalization.
+ *
+ * @hide
+ */
+ public void close() {
+ }
+
+ /**
+ * Logs a warning if the caller did not properly cleanup by calling an
+ * explicit close method before finalization. If CloseGuard was enabled
+ * when the CloseGuard was created, passes the stacktrace associated with
+ * the allocation to the current reporter. If it was not enabled, it just
+ * directly logs a brief message.
+ *
+ * @hide
+ */
+ public void warnIfOpen() {
+ }
+
+
+ /**
+ * Interface to allow customization of tracking behaviour.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ *
+ * @hide
+ */
+ public interface Tracker {
+ void open(Throwable allocationSite);
+ void close(Throwable allocationSite);
+ }
+
+ /**
+ * Interface to allow customization of reporting behavior.
+ * @hide
+ */
+ public interface Reporter {
+ /**
+ *
+ * @hide
+ */
+ void report(String message, Throwable allocationSite);
+
+ /**
+ *
+ * @hide
+ */
+ default void report(String message) {}
+ }
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/io/IoBridge.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/io/IoBridge.java
new file mode 100644
index 0000000..2a1ee25
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/io/IoBridge.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 libcore.io;
+
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+public class IoBridge {
+
+ public static void closeAndSignalBlockedThreads(FileDescriptor fd) throws IOException {
+ if (fd == null) {
+ return;
+ }
+ try {
+ Os.close(fd);
+ } catch (ErrnoException errnoException) {
+ throw errnoException.rethrowAsIOException();
+ }
+ }
+
+ public static FileDescriptor open(String path, int flags) throws FileNotFoundException {
+ FileDescriptor fd = null;
+ try {
+ fd = Os.open(path, flags, 0666);
+ // Posix open(2) fails with EISDIR only if you ask for write permission.
+ // Java disallows reading directories too.f
+ if (OsConstants.S_ISDIR(Os.fstat(fd).st_mode)) {
+ throw new ErrnoException("open", OsConstants.EISDIR);
+ }
+ return fd;
+ } catch (ErrnoException errnoException) {
+ try {
+ if (fd != null) {
+ closeAndSignalBlockedThreads(fd);
+ }
+ } catch (IOException ignored) {
+ }
+ FileNotFoundException ex = new FileNotFoundException(path + ": "
+ + errnoException.getMessage());
+ ex.initCause(errnoException);
+ throw ex;
+ }
+ }
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
index ad86135..cf1a513 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
@@ -35,6 +35,11 @@
return new NativeAllocationRegistry(classLoader, freeFunction, size);
}
+ public static NativeAllocationRegistry createNonmalloced(
+ Class clazz, long freeFunction, long size) {
+ return new NativeAllocationRegistry(clazz.getClassLoader(), freeFunction, size);
+ }
+
public static NativeAllocationRegistry createMalloced(
ClassLoader classLoader, long freeFunction, long size) {
return new NativeAllocationRegistry(classLoader, freeFunction, size);
@@ -45,6 +50,11 @@
return new NativeAllocationRegistry(classLoader, freeFunction, 0);
}
+ public static NativeAllocationRegistry createMalloced(
+ Class clazz, long freeFunction, long size) {
+ return new NativeAllocationRegistry(clazz.getClassLoader(), freeFunction, size);
+ }
+
public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) {
if (size < 0) {
throw new IllegalArgumentException("Invalid native allocation size: " + size);
@@ -52,6 +62,37 @@
mFreeFunction = freeFunction;
}
+ private class CleanerThunk implements Runnable {
+ private long nativePtr;
+
+ public CleanerThunk() {
+ nativePtr = 0;
+ }
+
+ public void setNativePtr(long ptr) {
+ nativePtr = ptr;
+ }
+
+ @Override
+ public void run() {
+ if (nativePtr != 0) {
+ applyFreeFunction(mFreeFunction, nativePtr);
+ }
+ }
+ }
+
+ private static class CleanableRunner implements Runnable {
+ private final Cleaner.Cleanable mCleanable;
+
+ public CleanableRunner(Cleaner.Cleanable cleanable) {
+ mCleanable = cleanable;
+ }
+
+ public void run() {
+ mCleanable.clean();
+ }
+ }
+
public Runnable registerNativeAllocation(Object referent, long nativePtr) {
if (referent == null) {
throw new IllegalArgumentException("referent is null");
@@ -60,13 +101,25 @@
throw new IllegalArgumentException("nativePtr is null");
}
- final Runnable releaser = () -> {
- RavenwoodRuntimeNative.applyFreeFunction(mFreeFunction, nativePtr);
- };
- sCleaner.register(referent, releaser);
+ final CleanerThunk thunk;
+ final CleanableRunner result;
+ try {
+ thunk = new CleanerThunk();
+ final var cleanable = sCleaner.register(referent, thunk);
+ result = new CleanableRunner(cleanable);
+ } catch (VirtualMachineError vme /* probably OutOfMemoryError */) {
+ applyFreeFunction(mFreeFunction, nativePtr);
+ throw vme;
+ }
+ // Enable the cleaner only after we can no longer throw anything, including OOME.
+ thunk.setNativePtr(nativePtr);
// Ensure that cleaner doesn't get invoked before we enable it.
Reference.reachabilityFence(referent);
- return releaser;
+ return result;
+ }
+
+ public static void applyFreeFunction(long freeFunction, long nativePtr) {
+ RavenwoodRuntimeNative.applyFreeFunction(freeFunction, nativePtr);
}
}
diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp
index 8d8ed71..01ebdc9 100644
--- a/ravenwood/runtime-jni/ravenwood_runtime.cpp
+++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp
@@ -20,6 +20,7 @@
#include <sys/syscall.h>
#include <unistd.h>
#include <utils/misc.h>
+#include <unicode/utypes.h>
#include <string>
@@ -183,6 +184,10 @@
return syscall(__NR_gettid);
}
+static jstring getIcuDataName(JNIEnv* env, jclass clazz) {
+ return env->NewStringUTF(U_ICUDATA_NAME);
+}
+
// ---- Registration ----
extern void register_android_system_OsConstants(JNIEnv* env);
@@ -201,6 +206,7 @@
{ "setenv", "(Ljava/lang/String;Ljava/lang/String;Z)V", (void*)Linux_setenv },
{ "getpid", "()I", (void*)Linux_getpid },
{ "gettid", "()I", (void*)Linux_gettid },
+ { "getIcuDataName", "()Ljava/lang/String;", (void*)getIcuDataName },
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
diff --git a/ravenwood/scripts/run-ravenwood-tests.sh b/ravenwood/scripts/run-ravenwood-tests.sh
index 27c5ea1..67ebb1f 100755
--- a/ravenwood/scripts/run-ravenwood-tests.sh
+++ b/ravenwood/scripts/run-ravenwood-tests.sh
@@ -66,7 +66,7 @@
done
shift $(($OPTIND - 1))
-all_tests=(hoststubgentest tiny-framework-dump-test hoststubgen-invoke-test ravenwood-stats-checker)
+all_tests=(hoststubgentest tiny-framework-dump-test hoststubgen-invoke-test ravenwood-stats-checker ravenhelpertest)
all_tests+=( $(${0%/*}/list-ravenwood-tests.sh) )
filter() {
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index e202d0e..7462cc2 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -259,6 +259,8 @@
android.database.sqlite.SQLiteException
android.text.TextUtils
+android.text.Html
+android.text.HtmlToSpannedConverter
android.accounts.Account
@@ -278,6 +280,10 @@
android.graphics.Rect
android.graphics.RectF
+android.graphics.fonts.SystemFonts
+
+android.graphics.text.LineBreakConfig
+
android.content.ContentProvider
android.app.ActivityManager
@@ -383,3 +389,228 @@
com.android.server.compat.*
com.android.internal.compat.*
android.app.AppCompatCallbacks
+android.graphics.AvoidXfermode
+android.graphics.BLASTBufferQueue
+android.graphics.BaseCanvas
+android.graphics.BaseRecordingCanvas
+android.graphics.Bitmap
+android.graphics.BitmapFactory
+android.graphics.BitmapRegionDecoder
+android.graphics.BitmapShader
+android.graphics.BlendMode
+android.graphics.BlendModeColorFilter
+android.graphics.BlurMaskFilter
+android.graphics.Camera
+android.graphics.Canvas
+android.graphics.CanvasProperty
+android.graphics.ColorFilter
+android.graphics.ColorMatrix
+android.graphics.ColorMatrixColorFilter
+android.graphics.Compatibility
+android.graphics.ComposePathEffect
+android.graphics.ComposeShader
+android.graphics.CornerPathEffect
+android.graphics.DashPathEffect
+android.graphics.DiscretePathEffect
+android.graphics.DrawFilter
+android.graphics.EmbossMaskFilter
+android.graphics.FontFamily
+android.graphics.FontListParser
+android.graphics.ForceDarkType
+android.graphics.FrameInfo
+android.graphics.Gainmap
+android.graphics.GraphicBuffer
+android.graphics.GraphicsProtos
+android.graphics.GraphicsStatsService
+android.graphics.HardwareBufferRenderer
+android.graphics.HardwareRenderer
+android.graphics.HardwareRendererObserver
+android.graphics.ImageDecoder
+android.graphics.ImageFormat
+android.graphics.LayerRasterizer
+android.graphics.LeakyTypefaceStorage
+android.graphics.LightingColorFilter
+android.graphics.LinearGradient
+android.graphics.MaskFilter
+android.graphics.Mesh
+android.graphics.MeshSpecification
+android.graphics.Movie
+android.graphics.NinePatch
+android.graphics.Paint
+android.graphics.PaintFlagsDrawFilter
+android.graphics.PathDashPathEffect
+android.graphics.PathEffect
+android.graphics.PathIterator
+android.graphics.PathMeasure
+android.graphics.Picture
+android.graphics.PixelXorXfermode
+android.graphics.PorterDuff
+android.graphics.PorterDuffColorFilter
+android.graphics.PorterDuffXfermode
+android.graphics.PostProcessor
+android.graphics.RadialGradient
+android.graphics.Rasterizer
+android.graphics.RecordingCanvas
+android.graphics.Region
+android.graphics.RegionIterator
+android.graphics.RenderEffect
+android.graphics.RenderNode
+android.graphics.RuntimeColorFilter
+android.graphics.RuntimeShader
+android.graphics.RuntimeXfermode
+android.graphics.Shader
+android.graphics.SumPathEffect
+android.graphics.SurfaceTexture
+android.graphics.SweepGradient
+android.graphics.TableMaskFilter
+android.graphics.TemporaryBuffer
+android.graphics.TextureLayer
+android.graphics.Typeface
+android.graphics.Xfermode
+android.graphics.YuvImage
+android.graphics.fonts.Font
+android.graphics.fonts.FontCustomizationParser
+android.graphics.fonts.FontFamily
+android.graphics.fonts.FontFamilyUpdateRequest
+android.graphics.fonts.FontFileUpdateRequest
+android.graphics.fonts.FontFileUtil
+android.graphics.fonts.FontStyle
+android.graphics.fonts.FontVariationAxis
+android.graphics.text.GraphemeBreak
+android.graphics.text.LineBreaker
+android.graphics.text.MeasuredText
+android.graphics.text.PositionedGlyphs
+android.graphics.text.TextRunShaper
+android.text.AlteredCharSequence
+android.text.AndroidBidi
+android.text.AndroidCharacter
+android.text.Annotation
+android.text.AutoGrowArray
+android.text.AutoText
+android.text.BidiFormatter
+android.text.BoringLayout
+android.text.CharSequenceCharacterIterator
+android.text.ClipboardManager
+android.text.DynamicLayout
+android.text.Editable
+android.text.Emoji
+android.text.EmojiConsistency
+android.text.FontConfig
+android.text.GetChars
+android.text.GraphemeClusterSegmentFinder
+android.text.GraphicsOperations
+android.text.Highlights
+android.text.Hyphenator
+android.text.InputFilter
+android.text.InputType
+android.text.Layout
+android.text.LoginFilter
+android.text.MeasuredParagraph
+android.text.NoCopySpan
+android.text.PackedIntVector
+android.text.PackedObjectVector
+android.text.ParcelableSpan
+android.text.PrecomputedText
+android.text.SegmentFinder
+android.text.Selection
+android.text.SpanColors
+android.text.SpanSet
+android.text.SpanWatcher
+android.text.Spannable
+android.text.SpannableString
+android.text.SpannableStringBuilder
+android.text.SpannableStringInternal
+android.text.Spanned
+android.text.SpannedString
+android.text.StaticLayout
+android.text.TextDirectionHeuristic
+android.text.TextDirectionHeuristics
+android.text.TextLine
+android.text.TextPaint
+android.text.TextShaper
+android.text.TextWatcher
+android.text.WordSegmentFinder
+android.text.format.DateFormat
+android.text.format.DateIntervalFormat
+android.text.format.DateTimeFormat
+android.text.format.DateUtils
+android.text.format.DateUtilsBridge
+android.text.format.Formatter
+android.text.format.RelativeDateTimeFormatter
+android.text.format.Time
+android.text.format.TimeFormatter
+android.text.format.TimeMigrationUtils
+android.text.method.AllCapsTransformationMethod
+android.text.method.ArrowKeyMovementMethod
+android.text.method.BaseKeyListener
+android.text.method.BaseMovementMethod
+android.text.method.CharacterPickerDialog
+android.text.method.DateKeyListener
+android.text.method.DateTimeKeyListener
+android.text.method.DialerKeyListener
+android.text.method.DigitsKeyListener
+android.text.method.HideReturnsTransformationMethod
+android.text.method.InsertModeTransformationMethod
+android.text.method.KeyListener
+android.text.method.LinkMovementMethod
+android.text.method.MetaKeyKeyListener
+android.text.method.MovementMethod
+android.text.method.MultiTapKeyListener
+android.text.method.NumberKeyListener
+android.text.method.OffsetMapping
+android.text.method.PasswordTransformationMethod
+android.text.method.QwertyKeyListener
+android.text.method.ReplacementTransformationMethod
+android.text.method.ScrollingMovementMethod
+android.text.method.SingleLineTransformationMethod
+android.text.method.TextKeyListener
+android.text.method.TimeKeyListener
+android.text.method.Touch
+android.text.method.TransformationMethod
+android.text.method.TransformationMethod2
+android.text.method.TranslationTransformationMethod
+android.text.method.WordIterator
+android.text.style.AbsoluteSizeSpan
+android.text.style.AccessibilityClickableSpan
+android.text.style.AccessibilityReplacementSpan
+android.text.style.AccessibilityURLSpan
+android.text.style.AlignmentSpan
+android.text.style.BackgroundColorSpan
+android.text.style.BulletSpan
+android.text.style.CharacterStyle
+android.text.style.ClickableSpan
+android.text.style.ForegroundColorSpan
+android.text.style.IconMarginSpan
+android.text.style.LeadingMarginSpan
+android.text.style.LineBackgroundSpan
+android.text.style.LineBreakConfigSpan
+android.text.style.LineHeightSpan
+android.text.style.LocaleSpan
+android.text.style.MaskFilterSpan
+android.text.style.MetricAffectingSpan
+android.text.style.NoWritingToolsSpan
+android.text.style.ParagraphStyle
+android.text.style.QuoteSpan
+android.text.style.RasterizerSpan
+android.text.style.RelativeSizeSpan
+android.text.style.ReplacementSpan
+android.text.style.ScaleXSpan
+android.text.style.SpanUtils
+android.text.style.SpellCheckSpan
+android.text.style.StrikethroughSpan
+android.text.style.StyleSpan
+android.text.style.SubscriptSpan
+android.text.style.SuggestionRangeSpan
+android.text.style.SuggestionSpan
+android.text.style.SuperscriptSpan
+android.text.style.TabStopSpan
+android.text.style.TextAppearanceSpan
+android.text.style.TtsSpan
+android.text.style.TypefaceSpan
+android.text.style.URLSpan
+android.text.style.UnderlineSpan
+android.text.style.UpdateAppearance
+android.text.style.UpdateLayout
+android.text.style.WrapTogetherSpan
+android.text.util.Rfc822Token
+android.text.util.Rfc822Tokenizer
diff --git a/ravenwood/texts/ravenwood-build.prop b/ravenwood/texts/ravenwood-build.prop
index 7cc4454..37c50f1 100644
--- a/ravenwood/texts/ravenwood-build.prop
+++ b/ravenwood/texts/ravenwood-build.prop
@@ -8,7 +8,11 @@
ro.soc.model=Ravenwood
ro.debuggable=1
-# The ones starting with "ro.product" or "ro.bild" will be copied to all "partitions" too.
+# For the graphics stack
+ro.hwui.max_texture_allocation_size=104857600
+persist.sys.locale=en-US
+
+# The ones starting with "ro.product" or "ro.build" will be copied to all "partitions" too.
# See RavenwoodSystemProperties.
ro.product.brand=Android
ro.product.device=Ravenwood
diff --git a/ravenwood/texts/ravenwood-common-policies.txt b/ravenwood/texts/ravenwood-common-policies.txt
index fd4ea6c..f0f4b85 100644
--- a/ravenwood/texts/ravenwood-common-policies.txt
+++ b/ravenwood/texts/ravenwood-common-policies.txt
@@ -21,3 +21,7 @@
method setInt$ @com.android.ravenwood.RavenwoodJdkPatch.setInt$
class java.util.LinkedHashMap # no-pta
method eldest @com.android.ravenwood.RavenwoodJdkPatch.eldest
+
+# Always set flag UNICODE_CHARACTER_CLASS when compiling regex
+class java.util.regex.Pattern keep
+ method compile @com.android.ravenwood.RavenwoodJdkPatch.compilePattern
diff --git a/ravenwood/texts/ravenwood-framework-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt
index fff9e6a..0695316 100644
--- a/ravenwood/texts/ravenwood-framework-policies.txt
+++ b/ravenwood/texts/ravenwood-framework-policies.txt
@@ -63,3 +63,22 @@
# Just enough to allow ResourcesManager to run
class android.hardware.display.DisplayManagerGlobal keep # no-pta
method getInstance ()Landroid/hardware/display/DisplayManagerGlobal; ignore # no-pta
+
+# Bare minimum to support running ImageDecoderTest
+class android.graphics.drawable.Drawable$ConstantState keepclass # no-pta
+class android.graphics.drawable.BitmapDrawable$BitmapState keepclass # no-pta
+class android.graphics.drawable.BitmapDrawable keep # no-pta
+ method <init> (Landroid/content/res/Resources;Landroid/graphics/Bitmap;)V keep
+ method init * keep
+ method updateLocalState * keep
+ method computeBitmapSize * keep
+ method getIntrinsicWidth * keep
+ method getIntrinsicHeight * keep
+ method getBitmap * keep
+class android.graphics.drawable.Drawable keep # no-pta
+ method <init> ()V keep
+ method resolveDensity * keep
+ method updateBlendModeFilter * ignore
+
+class android.os.StrictMode keep # no-pta
+ method noteSlowCall (Ljava/lang/String;)V ignore
diff --git a/ravenwood/tools/hoststubgen/framework-policy-override.txt b/ravenwood/tools/hoststubgen/hoststubgen-test-policy-override.txt
similarity index 72%
rename from ravenwood/tools/hoststubgen/framework-policy-override.txt
rename to ravenwood/tools/hoststubgen/hoststubgen-test-policy-override.txt
index af3789e..000771a 100644
--- a/ravenwood/tools/hoststubgen/framework-policy-override.txt
+++ b/ravenwood/tools/hoststubgen/hoststubgen-test-policy-override.txt
@@ -1,30 +1,7 @@
-# --------------------------------------------------------------------------------------------------
-# This file contains rules to process `framework-all.jar` to generate the host side test "stub" and
-# "impl" jars, without using Java annotations.
-#
-# Useful when:
-# - The class is auto-generated and annotations can't be added.
-# (We need to figure out what to do on auto-generated classes.)
-# - Want to quickly change filter rules without having to rebuild framework.jar.
-#
-# Using this file, one can control the visibility of APIs on a per-class, per-field and per-method
-# basis, but in most cases, per-class directives would be sufficient. That is:
-#
-# - To put the entire class, including its members and nested classes, in the "stub" jar,
-# so that the test / target code can use the API, use `stubclass`.
-#
-# class package.class stubclass
-#
-# - To put the entire class, including its members and nested classes, in the "impl" jar,
-# but not in the "stub" jar, use `keepclass`. Use this when you don't want to expose an API to
-# tests/target directly, but it's still needed at runtime, because it's used by other "stub" APIs
-# directly or indirectly.
-#
-# class package.class keepclass
-#
-# All other classes will be removed from both the stub jar and impl jar.
-#
-# --------------------------------------------------------------------------------------------------
+# *************************************************************************************************
+# This file contains "policies" for HostStubGen used by its automated tests.
+# For the "real" Ravenwood policies, see the frameworks/base/ravenwood/texts/ directory.
+# *************************************************************************************************
# --------------------------------------------------------------------------------------------------
# Directions on auto-generated classes, where we can't use Java annotations (yet).
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 3340990..83a7069 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -29,7 +29,7 @@
import com.android.hoststubgen.filters.SanitizationFilter
import com.android.hoststubgen.filters.TextFileFilterPolicyBuilder
import com.android.hoststubgen.filters.printAsTextPolicy
-import com.android.hoststubgen.utils.ClassFilter
+import com.android.hoststubgen.utils.ClassPredicate
import com.android.hoststubgen.visitors.BaseAdapter
import com.android.hoststubgen.visitors.PackageRedirectRemapper
import java.io.BufferedInputStream
@@ -153,9 +153,9 @@
val annotationAllowedClassesFilter = options.annotationAllowedClassesFile.get.let { file ->
if (file == null) {
- ClassFilter.newNullFilter(true) // Allow all classes
+ ClassPredicate.newConstantPredicate(true) // Allow all classes
} else {
- ClassFilter.loadFromFile(file, false)
+ ClassPredicate.loadFromFile(file, false)
}
}
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
index 36adf06..9b5d602 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
@@ -31,7 +31,7 @@
import com.android.hoststubgen.asm.toHumanReadableMethodName
import com.android.hoststubgen.asm.toJvmClassName
import com.android.hoststubgen.log
-import com.android.hoststubgen.utils.ClassFilter
+import com.android.hoststubgen.utils.ClassPredicate
import org.objectweb.asm.tree.AnnotationNode
import org.objectweb.asm.tree.ClassNode
@@ -54,7 +54,7 @@
redirectionClassAnnotations_: Set<String>,
classLoadHookAnnotations_: Set<String>,
keepStaticInitializerAnnotations_: Set<String>,
- private val annotationAllowedClassesFilter: ClassFilter,
+ private val annotationAllowedClassesFilter: ClassPredicate,
fallback: OutputFilter,
) : DelegatingFilter(fallback) {
private val keepAnnotations = convertToInternalNames(keepAnnotations_)
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/utils/ClassPredicate.kt
similarity index 93%
rename from ravenwood/tools/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
rename to ravenwood/tools/hoststubgen/src/com/android/hoststubgen/utils/ClassPredicate.kt
index d6aa761..810dd71 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/utils/ClassPredicate.kt
@@ -24,7 +24,7 @@
/**
* General purpose filter for class names.
*/
-class ClassFilter private constructor(
+class ClassPredicate private constructor(
private val defaultResult: Boolean,
) {
private enum class MatchType {
@@ -81,14 +81,14 @@
companion object {
/**
- * Return a filter that alawys returns true or false.
+ * Return a filter that always returns true or false.
*/
- fun newNullFilter(defaultResult: Boolean): ClassFilter {
- return ClassFilter(defaultResult)
+ fun newConstantPredicate(defaultResult: Boolean): ClassPredicate {
+ return ClassPredicate(defaultResult)
}
/** Build a filter from a file. */
- fun loadFromFile(filename: String, defaultResult: Boolean): ClassFilter {
+ fun loadFromFile(filename: String, defaultResult: Boolean): ClassPredicate {
return buildFromString(File(filename).readText(), defaultResult, filename)
}
@@ -97,8 +97,8 @@
filterString: String,
defaultResult: Boolean,
filenameForErrorMessage: String
- ): ClassFilter {
- val ret = ClassFilter(defaultResult)
+ ): ClassPredicate {
+ val ret = ClassPredicate(defaultResult)
var lineNo = 0
filterString.split('\n').forEach { s ->
diff --git a/ravenwood/tools/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt b/ravenwood/tools/hoststubgen/test/com/android/hoststubgen/utils/ClassPredicateTest.kt
similarity index 89%
rename from ravenwood/tools/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
rename to ravenwood/tools/hoststubgen/test/com/android/hoststubgen/utils/ClassPredicateTest.kt
index d4e75d4..5a877e6 100644
--- a/ravenwood/tools/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
+++ b/ravenwood/tools/hoststubgen/test/com/android/hoststubgen/utils/ClassPredicateTest.kt
@@ -20,22 +20,22 @@
import org.junit.Assert.fail
import org.junit.Test
-class ClassFilterTest {
+class ClassPredicateTest {
@Test
fun testDefaultTrue() {
- val f = ClassFilter.newNullFilter(true)
+ val f = ClassPredicate.newConstantPredicate(true)
assertThat(f.matches("a/b/c")).isEqualTo(true)
}
@Test
fun testDefaultFalse() {
- val f = ClassFilter.newNullFilter(false)
+ val f = ClassPredicate.newConstantPredicate(false)
assertThat(f.matches("a/b/c")).isEqualTo(false)
}
@Test
fun testComplex1() {
- val f = ClassFilter.buildFromString("""
+ val f = ClassPredicate.buildFromString("""
# ** this is a comment **
a.b.c # allow
!a.b.d # disallow
@@ -57,7 +57,7 @@
@Test
fun testComplex2() {
- val f = ClassFilter.buildFromString("""
+ val f = ClassPredicate.buildFromString("""
a.b.c # allow
!a.* # disallow everything else in package "a".
!d.e.f # disallow d.e.f.
@@ -75,7 +75,7 @@
@Test
fun testNestedClass() {
- val f = ClassFilter.buildFromString("a.b.c\nm.n.o\$p\n", false, "X")
+ val f = ClassPredicate.buildFromString("a.b.c\nm.n.o\$p\n", false, "X")
assertThat(f.matches("a/b/c")).isEqualTo(true)
assertThat(f.matches("a/b/c\$d")).isEqualTo(true)
assertThat(f.matches("a/b/c\$d\$e")).isEqualTo(true)
@@ -88,7 +88,7 @@
@Test
fun testBadFilter1() {
try {
- ClassFilter.buildFromString("""
+ ClassPredicate.buildFromString("""
a*
""".trimIndent(), true, "FILENAME")
fail("ParseException didn't happen")
@@ -101,7 +101,7 @@
@Test
fun testSuffix() {
- val f = ClassFilter.buildFromString("""
+ val f = ClassPredicate.buildFromString("""
*.Abc # allow
!* # Disallow by default
""".trimIndent(), true, "X")
diff --git a/ravenwood/tools/ravenhelper/Android.bp b/ravenwood/tools/ravenhelper/Android.bp
index a7ee468..3da6dd8 100644
--- a/ravenwood/tools/ravenhelper/Android.bp
+++ b/ravenwood/tools/ravenhelper/Android.bp
@@ -24,3 +24,14 @@
],
visibility: ["//visibility:public"],
}
+
+java_test_host {
+ name: "ravenhelpertest",
+ srcs: ["test/**/*.kt"],
+ static_libs: [
+ "ravenhelper",
+ "truth",
+ ],
+ test_suites: ["general-tests"],
+ visibility: ["//visibility:private"],
+}
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
index 3657a90..b6089ea 100644
--- a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
@@ -24,7 +24,7 @@
import com.android.hoststubgen.filters.TextFileFilterPolicyParser
import com.android.hoststubgen.filters.TextFilePolicyMethodReplaceFilter
import com.android.hoststubgen.log
-import com.android.hoststubgen.utils.ClassFilter
+import com.android.hoststubgen.utils.ClassPredicate
import com.android.platform.test.ravenwood.ravenhelper.SubcommandHandler
import com.android.platform.test.ravenwood.ravenhelper.psi.createUastEnvironment
import com.android.platform.test.ravenwood.ravenhelper.sourcemap.AllClassInfo
@@ -66,11 +66,11 @@
val annotations: Annotations,
val dumpOperations: Boolean,
) {
- private val annotationAllowedClasses: ClassFilter = annotationAllowedClassesFile.let { file ->
+ private val annotationAllowedClasses: ClassPredicate = annotationAllowedClassesFile.let { file ->
if (file == null) {
- ClassFilter.newNullFilter(true) // Allow all classes
+ ClassPredicate.newConstantPredicate(true) // Allow all classes
} else {
- ClassFilter.loadFromFile(file, false)
+ ClassPredicate.loadFromFile(file, false)
}
}
diff --git a/ravenwood/tools/ravenhelper/test/com/android/platform/test/ravenwood/ravenhelper/RavenhelperTest.kt b/ravenwood/tools/ravenhelper/test/com/android/platform/test/ravenwood/ravenhelper/RavenhelperTest.kt
new file mode 100644
index 0000000..203fab1
--- /dev/null
+++ b/ravenwood/tools/ravenhelper/test/com/android/platform/test/ravenwood/ravenhelper/RavenhelperTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.platform.test.ravenwood.ravenhelper
+
+import com.android.platform.test.ravenwood.ravenhelper.psi.createUastEnvironment
+import org.junit.Test
+
+class RavenhelperTest {
+ @Test
+ fun testPsiInitialization() {
+ val env = createUastEnvironment()
+ env.dispose()
+ }
+}
\ No newline at end of file
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index bb0eacb..b52b3dab 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -11,6 +11,16 @@
}
flag {
+ name: "allow_secure_screenshots"
+ namespace: "accessibility"
+ description: "Allow certain AccessibilityServices to take screenshots of FLAG_SECURE screens"
+ bug: "373705911"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "always_allow_observing_touch_events"
namespace: "accessibility"
description: "Always allows InputFilter observing SOURCE_TOUCHSCREEN events, even if touch exploration is enabled."
@@ -135,16 +145,6 @@
}
flag {
- name: "enable_magnification_follows_mouse_bugfix"
- namespace: "accessibility"
- description: "Whether to enable mouse following for fullscreen magnification"
- bug: "354696546"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "enable_magnification_follows_mouse_with_pointer_motion_filter"
namespace: "accessibility"
description: "Whether to enable mouse following using pointer motion filter"
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 9ceca5d..4b04248 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -86,11 +86,13 @@
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityCache;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import android.view.accessibility.IWindowSurfaceInfoCallback;
import android.view.inputmethod.EditorInfo;
import android.window.ScreenCapture;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
@@ -343,6 +345,8 @@
SurfaceControl sc,
IAccessibilityInteractionConnectionCallback callback);
+ int performScreenCapture(ScreenCapture.LayerCaptureArgs captureArgs,
+ ScreenCapture.ScreenCaptureListener captureListener);
}
public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
@@ -1456,7 +1460,45 @@
AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_WINDOW, interactionId);
return;
}
- connection.getRemote().takeScreenshotOfWindow(interactionId, listener, callback);
+ if (Flags.allowSecureScreenshots()) {
+ IWindowSurfaceInfoCallback infoCallback = new IWindowSurfaceInfoCallback.Stub() {
+ @Override
+ public void provideWindowSurfaceInfo(int windowFlags, int processUid,
+ SurfaceControl surfaceControl) {
+ final boolean canCaptureSecureLayers = canCaptureSecureLayers();
+ if (!canCaptureSecureLayers
+ && (windowFlags & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+ try {
+ callback.sendTakeScreenshotOfWindowError(
+ AccessibilityService.ERROR_TAKE_SCREENSHOT_SECURE_WINDOW,
+ interactionId);
+ } catch (RemoteException e) {
+ // ignore - the other side will time out
+ }
+ return;
+ }
+
+ final ScreenCapture.LayerCaptureArgs captureArgs =
+ new ScreenCapture.LayerCaptureArgs.Builder(surfaceControl)
+ .setChildrenOnly(false)
+ .setUid(processUid)
+ .setCaptureSecureLayers(canCaptureSecureLayers)
+ .build();
+ if (mSystemSupport.performScreenCapture(captureArgs, listener) != 0) {
+ try {
+ callback.sendTakeScreenshotOfWindowError(
+ AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR,
+ interactionId);
+ } catch (RemoteException e) {
+ // ignore - the other side will time out
+ }
+ }
+ }
+ };
+ connection.getRemote().getWindowSurfaceInfo(infoCallback);
+ } else {
+ connection.getRemote().takeScreenshotOfWindow(interactionId, listener, callback);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1523,7 +1565,14 @@
}
}
);
- mWindowManagerService.captureDisplay(displayId, null, screenCaptureListener);
+ if (Flags.allowSecureScreenshots()) {
+ mWindowManagerService.captureDisplay(displayId,
+ new ScreenCapture.CaptureArgs.Builder<>()
+ .setCaptureSecureLayers(canCaptureSecureLayers()).build(),
+ screenCaptureListener);
+ } else {
+ mWindowManagerService.captureDisplay(displayId, null, screenCaptureListener);
+ }
} catch (Exception e) {
sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
callback);
@@ -1564,6 +1613,13 @@
}, null).recycleOnUse());
}
+ private boolean canCaptureSecureLayers() {
+ return Flags.allowSecureScreenshots()
+ && mAccessibilityServiceInfo.isAccessibilityTool()
+ && mAccessibilityServiceInfo.getResolveInfo().serviceInfo
+ .applicationInfo.isSystemApp();
+ }
+
@Override
@PermissionManuallyEnforced
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index e422fef..4e41808 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -53,7 +53,6 @@
import com.android.server.accessibility.magnification.FullScreenMagnificationVibrationHelper;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
import com.android.server.accessibility.magnification.MagnificationKeyHandler;
-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;
@@ -134,7 +133,7 @@
*/
static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 0x00000080;
-/**
+ /**
* Flag for enabling multi-finger gestures.
*
* @see #setUserAndEnabledFeatures(int, int)
@@ -190,8 +189,6 @@
private final AccessibilityManagerService mAms;
- private final InputManager mInputManager;
-
private final SparseArray<EventStreamTransformation> mEventHandler;
private final SparseArray<TouchExplorer> mTouchExplorer = new SparseArray<>(0);
@@ -294,7 +291,6 @@
mContext = context;
mAms = service;
mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mInputManager = context.getSystemService(InputManager.class);
mEventHandler = eventHandler;
}
@@ -902,8 +898,7 @@
triggerable,
new WindowMagnificationPromptController(displayContext, mUserId),
displayId,
- fullScreenMagnificationVibrationHelper,
- new MouseEventHandler(controller));
+ fullScreenMagnificationVibrationHelper);
}
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 67fdca4..9eb8442 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -173,6 +173,7 @@
import android.view.accessibility.IMagnificationConnection;
import android.view.accessibility.IUserInitializationCompleteCallback;
import android.view.inputmethod.EditorInfo;
+import android.window.ScreenCapture;
import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
@@ -6725,6 +6726,12 @@
callback));
}
+ @Override
+ public int performScreenCapture(ScreenCapture.LayerCaptureArgs captureArgs,
+ ScreenCapture.ScreenCaptureListener captureListener) {
+ return ScreenCapture.captureLayers(captureArgs, captureListener);
+ }
+
@VisibleForTesting
int getShortcutTypeForGenericShortcutCalls(int userId) {
int navigationMode = Settings.Secure.getIntForUser(
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
index 4fa0d50..aa82df4 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
@@ -101,8 +101,15 @@
}
@Override
- public void toggleAutoclickPause() {
- // TODO(b/388872274): allows users to pause the autoclick.
+ public void toggleAutoclickPause(boolean paused) {
+ if (paused) {
+ if (mClickScheduler != null) {
+ mClickScheduler.cancel();
+ }
+ if (mAutoclickIndicatorScheduler != null) {
+ mAutoclickIndicatorScheduler.cancel();
+ }
+ }
}
};
@@ -133,7 +140,9 @@
mAutoclickIndicatorScheduler);
}
- handleMouseMotion(event, policyFlags);
+ if (!isPaused()) {
+ handleMouseMotion(event, policyFlags);
+ }
} else if (mClickScheduler != null) {
mClickScheduler.cancel();
}
@@ -216,6 +225,11 @@
}
}
+ private boolean isPaused() {
+ // TODO (b/397460424): Unpause when hovering over panel.
+ return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isPaused();
+ }
+
/**
* Observes autoclick setting values, and updates ClickScheduler delay and indicator size
* whenever the setting value changes.
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickIndicatorView.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickIndicatorView.java
index 01f359f..6beb47a 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickIndicatorView.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickIndicatorView.java
@@ -123,6 +123,7 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Get the screen dimensions.
+ // TODO(b/397944891): Handle device rotation case.
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
index 614b228..342675a 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
@@ -25,6 +25,7 @@
import android.graphics.drawable.GradientDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -46,6 +47,21 @@
public static final int AUTOCLICK_TYPE_DRAG = 3;
public static final int AUTOCLICK_TYPE_SCROLL = 4;
+ public static final int CORNER_BOTTOM_RIGHT = 0;
+ public static final int CORNER_BOTTOM_LEFT = 1;
+ public static final int CORNER_TOP_LEFT = 2;
+ public static final int CORNER_TOP_RIGHT = 3;
+
+ // Distance between panel and screen edge.
+ // TODO(b/396402941): Finalize edge margin.
+ private static final int PANEL_EDGE_MARGIN = 15;
+
+ // Touch point when drag starts, it can be anywhere inside the panel.
+ private float mTouchStartX, mTouchStartY;
+ // Initial panel position in screen coordinates.
+ private int mPanelStartX, mPanelStartY;
+ private boolean mIsDragging = false;
+
// Types of click the AutoclickTypePanel supports.
@IntDef({
AUTOCLICK_TYPE_LEFT_CLICK,
@@ -56,14 +72,38 @@
})
public @interface AutoclickType {}
+ @IntDef({
+ CORNER_BOTTOM_RIGHT,
+ CORNER_BOTTOM_LEFT,
+ CORNER_TOP_LEFT,
+ CORNER_TOP_RIGHT
+ })
+ public @interface Corner {}
+
+ private static final @Corner int[] CORNER_ROTATION_ORDER = {
+ CORNER_BOTTOM_RIGHT,
+ CORNER_BOTTOM_LEFT,
+ CORNER_TOP_LEFT,
+ CORNER_TOP_RIGHT
+ };
+
// An interface exposed to {@link AutoclickController) to handle different actions on the panel,
// including changing autoclick type, pausing/resuming autoclick.
public interface ClickPanelControllerInterface {
- // Allows users to change a different autoclick type.
+ /**
+ * Allows users to change a different autoclick type.
+ *
+ * @param clickType The new autoclick type to use. Should be one of the values defined in
+ * {@link AutoclickType}.
+ */
void handleAutoclickTypeChange(@AutoclickType int clickType);
- // Allows users to pause/resume the autoclick.
- void toggleAutoclickPause();
+ /**
+ * Allows users to pause or resume autoclick.
+ *
+ * @param paused {@code true} to pause autoclick, {@code false} to resume.
+ */
+ void toggleAutoclickPause(boolean paused);
}
private final Context mContext;
@@ -72,19 +112,33 @@
private final WindowManager mWindowManager;
+ private WindowManager.LayoutParams mParams;
+
private final ClickPanelControllerInterface mClickPanelController;
// Whether the panel is expanded or not.
private boolean mExpanded = false;
+ // Whether autoclick is paused.
+ private boolean mPaused = false;
+ // Tracks the current corner position of the panel using an index into CORNER_ROTATION_ORDER
+ // array. This allows the panel to cycle through screen corners in a defined sequence when
+ // repositioned.
+ private int mCurrentCornerIndex = 0;
+
private final LinearLayout mLeftClickButton;
private final LinearLayout mRightClickButton;
private final LinearLayout mDoubleClickButton;
private final LinearLayout mDragButton;
private final LinearLayout mScrollButton;
+ private final LinearLayout mPauseButton;
+ private final LinearLayout mPositionButton;
private LinearLayout mSelectedButton;
+ private final Drawable mPauseButtonDrawable;
+ private final Drawable mResumeButtonDrawable;
+
public AutoclickTypePanel(
Context context,
WindowManager windowManager,
@@ -92,6 +146,12 @@
mContext = context;
mWindowManager = windowManager;
mClickPanelController = clickPanelController;
+ mParams = getDefaultLayoutParams();
+
+ mPauseButtonDrawable = mContext.getDrawable(
+ R.drawable.accessibility_autoclick_pause);
+ mResumeButtonDrawable = mContext.getDrawable(
+ R.drawable.accessibility_autoclick_resume);
mContentView =
LayoutInflater.from(context)
@@ -104,8 +164,95 @@
mContentView.findViewById(R.id.accessibility_autoclick_double_click_layout);
mScrollButton = mContentView.findViewById(R.id.accessibility_autoclick_scroll_layout);
mDragButton = mContentView.findViewById(R.id.accessibility_autoclick_drag_layout);
+ mPauseButton = mContentView.findViewById(R.id.accessibility_autoclick_pause_layout);
+ mPositionButton = mContentView.findViewById(R.id.accessibility_autoclick_position_layout);
initializeButtonState();
+
+ // Set up touch event handling for the panel to allow the user to drag and reposition the
+ // panel by touching and moving it.
+ mContentView.setOnTouchListener(this::onPanelTouch);
+ }
+
+ /**
+ * Handles touch events on the panel, enabling the user to drag and reposition it.
+ * This function supports the draggable panel feature, allowing users to move the panel
+ * to different screen locations for better usability and customization.
+ */
+ private boolean onPanelTouch(View v, MotionEvent event) {
+ // TODO(b/397681794): Make sure this works on multiple screens.
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ // Store initial touch positions.
+ mTouchStartX = event.getRawX();
+ mTouchStartY = event.getRawY();
+
+ // Store initial panel position relative to screen's top-left corner.
+ // getLocationOnScreen provides coordinates relative to the top-left corner of the
+ // screen's display. We are using this coordinate system to consistently track the
+ // panel's position during drag operations.
+ int[] location = new int[2];
+ v.getLocationOnScreen(location);
+ mPanelStartX = location[0];
+ mPanelStartY = location[1];
+ return true;
+ case MotionEvent.ACTION_MOVE:
+ mIsDragging = true;
+
+ // Set panel gravity to TOP|LEFT to match getLocationOnScreen's coordinate system
+ mParams.gravity = Gravity.LEFT | Gravity.TOP;
+
+ if (mIsDragging) {
+ // Calculate touch distance moved from start position.
+ float deltaX = event.getRawX() - mTouchStartX;
+ float deltaY = event.getRawY() - mTouchStartY;
+
+ // Update panel position, based on Top-Left absolute positioning.
+ mParams.x = mPanelStartX + (int) deltaX;
+ mParams.y = mPanelStartY + (int) deltaY;
+ mWindowManager.updateViewLayout(mContentView, mParams);
+ }
+ return true;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (mIsDragging) {
+ // When drag ends, snap panel to nearest edge.
+ snapToNearestEdge(mParams);
+ }
+ mIsDragging = false;
+ return true;
+ }
+ return false;
+ }
+
+ private void snapToNearestEdge(WindowManager.LayoutParams params) {
+ // Get screen width to determine which side to snap to.
+ // TODO(b/397944891): Handle device rotation case.
+ int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
+ int yPosition = params.y;
+
+ // Determine which half of the screen the panel is on.
+ boolean isOnLeftHalf = params.x < screenWidth / 2;
+
+ if (isOnLeftHalf) {
+ // Snap to left edge. Set params.gravity to make sure x, y offsets from correct anchor.
+ params.gravity = Gravity.START | Gravity.TOP;
+ // Set the current corner to be bottom-left to ensure that the subsequent reposition
+ // action rotates the panel clockwise from bottom-left towards top-left.
+ mCurrentCornerIndex = 1;
+ } else {
+ // Snap to right edge. Set params.gravity to make sure x, y offsets from correct anchor.
+ params.gravity = Gravity.END | Gravity.TOP;
+ // Set the current corner to be top-right to ensure that the subsequent reposition
+ // action rotates the panel clockwise from top-right towards bottom-right.
+ mCurrentCornerIndex = 3;
+ }
+
+ // Apply final position: set params.x to be edge margin, params.y to maintain vertical
+ // position.
+ params.x = PANEL_EDGE_MARGIN;
+ params.y = yPosition;
+ mWindowManager.updateViewLayout(mContentView, params);
}
private void initializeButtonState() {
@@ -115,11 +262,8 @@
v -> togglePanelExpansion(AUTOCLICK_TYPE_DOUBLE_CLICK));
mScrollButton.setOnClickListener(v -> togglePanelExpansion(AUTOCLICK_TYPE_SCROLL));
mDragButton.setOnClickListener(v -> togglePanelExpansion(AUTOCLICK_TYPE_DRAG));
-
- // TODO(b/388872274): registers listener for pause button and allows users to pause/resume
- // the autoclick.
- // TODO(b/388847771): registers listener for position button and allows users to move the
- // panel to a different position.
+ mPositionButton.setOnClickListener(v -> moveToNextCorner());
+ mPauseButton.setOnClickListener(v -> togglePause());
// Initializes panel as collapsed state and only displays the left click button.
hideAllClickTypeButtons();
@@ -164,7 +308,7 @@
}
public void show() {
- mWindowManager.addView(mContentView, getLayoutParams());
+ mWindowManager.addView(mContentView, mParams);
}
public void hide() {
@@ -175,6 +319,10 @@
mWindowManager.removeView(mContentView);
}
+ public boolean isPaused() {
+ return mPaused;
+ }
+
/** Toggles the panel expanded or collapsed state. */
private void togglePanelExpansion(@AutoclickType int clickType) {
final LinearLayout button = getButtonFromClickType(clickType);
@@ -196,6 +344,18 @@
mExpanded = !mExpanded;
}
+ private void togglePause() {
+ mPaused = !mPaused;
+ mClickPanelController.toggleAutoclickPause(mPaused);
+
+ ImageButton imageButton = (ImageButton) mPauseButton.getChildAt(/* index= */ 0);
+ if (mPaused) {
+ imageButton.setImageDrawable(mResumeButtonDrawable);
+ } else {
+ imageButton.setImageDrawable(mPauseButtonDrawable);
+ }
+ }
+
/** Hide all buttons on the panel except pause and position buttons. */
private void hideAllClickTypeButtons() {
mLeftClickButton.setVisibility(View.GONE);
@@ -225,6 +385,45 @@
};
}
+ /** Moves the panel to the next corner in clockwise direction. */
+ private void moveToNextCorner() {
+ @Corner int nextCornerIndex = (mCurrentCornerIndex + 1) % CORNER_ROTATION_ORDER.length;
+ mCurrentCornerIndex = nextCornerIndex;
+
+ setPanelPositionForCorner(mParams, mCurrentCornerIndex);
+ mWindowManager.updateViewLayout(mContentView, mParams);
+ }
+
+ private void setPanelPositionForCorner(WindowManager.LayoutParams params, @Corner int corner) {
+ // TODO(b/396402941): Replace hardcoded pixel values with proper dimension calculations,
+ // Current values are experimental and may not work correctly across different device
+ // resolutions and configurations.
+ switch (corner) {
+ case CORNER_BOTTOM_RIGHT:
+ params.gravity = Gravity.END | Gravity.BOTTOM;
+ params.x = PANEL_EDGE_MARGIN;
+ params.y = 90;
+ break;
+ case CORNER_BOTTOM_LEFT:
+ params.gravity = Gravity.START | Gravity.BOTTOM;
+ params.x = PANEL_EDGE_MARGIN;
+ params.y = 90;
+ break;
+ case CORNER_TOP_LEFT:
+ params.gravity = Gravity.START | Gravity.TOP;
+ params.x = PANEL_EDGE_MARGIN;
+ params.y = 30;
+ break;
+ case CORNER_TOP_RIGHT:
+ params.gravity = Gravity.END | Gravity.TOP;
+ params.x = PANEL_EDGE_MARGIN;
+ params.y = 30;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid corner: " + corner);
+ }
+ }
+
@VisibleForTesting
boolean getExpansionStateForTesting() {
return mExpanded;
@@ -236,12 +435,28 @@
return mContentView;
}
+ @VisibleForTesting
+ @Corner
+ int getCurrentCornerIndexForTesting() {
+ return mCurrentCornerIndex;
+ }
+
+ @VisibleForTesting
+ WindowManager.LayoutParams getLayoutParamsForTesting() {
+ return mParams;
+ }
+
+ @VisibleForTesting
+ boolean getIsDraggingForTesting() {
+ return mIsDragging;
+ }
+
/**
* Retrieves the layout params for AutoclickIndicatorView, used when it's added to the Window
* Manager.
*/
@NonNull
- private WindowManager.LayoutParams getLayoutParams() {
+ private WindowManager.LayoutParams getDefaultLayoutParams() {
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -254,11 +469,7 @@
mContext.getString(R.string.accessibility_autoclick_type_settings_panel_title);
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
- // TODO(b/388847771): Compute position based on user interaction.
- layoutParams.x = 15;
- layoutParams.y = 90;
- layoutParams.gravity = Gravity.END | Gravity.BOTTOM;
-
+ setPanelPositionForCorner(layoutParams, CORNER_BOTTOM_RIGHT);
return layoutParams;
}
}
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 d11ae0a..e0dd8b6 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -182,7 +182,7 @@
private final int mMinimumVelocity;
private final int mMaximumVelocity;
- private MouseEventHandler mMouseEventHandler;
+ private final MouseEventHandler mMouseEventHandler;
public FullScreenMagnificationGestureHandler(
@UiContext Context context,
@@ -194,8 +194,7 @@
boolean detectShortcutTrigger,
@NonNull WindowMagnificationPromptController promptController,
int displayId,
- FullScreenMagnificationVibrationHelper fullScreenMagnificationVibrationHelper,
- MouseEventHandler mouseEventHandler) {
+ FullScreenMagnificationVibrationHelper fullScreenMagnificationVibrationHelper) {
this(
context,
fullScreenMagnificationController,
@@ -210,8 +209,7 @@
/* magnificationLogger= */ null,
ViewConfiguration.get(context),
new OneFingerPanningSettingsProvider(
- context, Flags.enableMagnificationOneFingerPanningGesture()),
- mouseEventHandler);
+ context, Flags.enableMagnificationOneFingerPanningGesture()));
}
/** Constructor for tests. */
@@ -229,8 +227,7 @@
FullScreenMagnificationVibrationHelper fullScreenMagnificationVibrationHelper,
MagnificationLogger magnificationLogger,
ViewConfiguration viewConfiguration,
- OneFingerPanningSettingsProvider oneFingerPanningSettingsProvider,
- MouseEventHandler mouseEventHandler) {
+ OneFingerPanningSettingsProvider oneFingerPanningSettingsProvider) {
super(displayId, detectSingleFingerTripleTap, detectTwoFingerTripleTap,
detectShortcutTrigger, trace, callback);
if (DEBUG_ALL) {
@@ -316,7 +313,7 @@
mOverscrollEdgeSlop = context.getResources().getDimensionPixelSize(
R.dimen.accessibility_fullscreen_magnification_gesture_edge_slop);
mIsWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
- mMouseEventHandler = mouseEventHandler;
+ mMouseEventHandler = new MouseEventHandler(mFullScreenMagnificationController);
if (mDetectShortcutTrigger) {
mScreenStateReceiver = new ScreenStateReceiver(context, this);
@@ -340,15 +337,14 @@
@Override
void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- if (Flags.enableMagnificationFollowsMouseBugfix()) {
- 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.
-
- // Send through the mouse/stylus event handler.
- mMouseEventHandler.onEvent(event, mDisplayId);
- }
+ if (!mFullScreenMagnificationController.isActivated(mDisplayId)) {
+ return;
}
+ // TODO(b/354696546): Allow mouse/stylus to activate whichever display they are
+ // over, rather than only interacting with the current display.
+
+ // Send through the mouse/stylus event handler.
+ mMouseEventHandler.onEvent(event, mDisplayId);
}
private void handleTouchEventWith(
@@ -1170,8 +1166,7 @@
protected void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
- if (Flags.enableMagnificationFollowsMouseBugfix()
- && !event.isFromSource(SOURCE_TOUCHSCREEN)) {
+ if (!event.isFromSource(SOURCE_TOUCHSCREEN)) {
// Only touch events need to be cached and sent later.
return;
}
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 fa86ba3..6b39c98 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
@@ -146,8 +146,7 @@
} break;
case SOURCE_MOUSE:
case SOURCE_STYLUS: {
- if (magnificationShortcutExists()
- && Flags.enableMagnificationFollowsMouseBugfix()) {
+ if (magnificationShortcutExists()) {
handleMouseOrStylusEvent(event, rawEvent, policyFlags);
}
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
index d0ee7af..5191fb5 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
@@ -20,6 +20,8 @@
import static android.app.appfunctions.AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_NAMESPACE;
import static com.android.server.appfunctions.AppFunctionExecutors.THREAD_POOL_EXECUTOR;
+import static com.android.server.appfunctions.CallerValidator.CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_HAS_PERMISSION;
+import static com.android.server.appfunctions.CallerValidator.CAN_EXECUTE_APP_FUNCTIONS_DENIED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -236,30 +238,42 @@
requestInternal.getCallingPackage(),
targetPackageName,
requestInternal.getClientRequest().getFunctionIdentifier())
- .thenAccept(
- canExecute -> {
- if (!canExecute) {
- throw new SecurityException(
- "Caller does not have permission to execute the"
- + " appfunction");
- }
- })
.thenCompose(
- isEnabled ->
- isAppFunctionEnabled(
- requestInternal.getClientRequest().getFunctionIdentifier(),
- requestInternal.getClientRequest().getTargetPackageName(),
- getAppSearchManagerAsUser(requestInternal.getUserHandle()),
- THREAD_POOL_EXECUTOR))
- .thenAccept(
- isEnabled -> {
- if (!isEnabled) {
- throw new DisabledAppFunctionException(
- "The app function is disabled");
+ canExecuteResult -> {
+ if (canExecuteResult == CAN_EXECUTE_APP_FUNCTIONS_DENIED) {
+ return AndroidFuture.failedFuture(new SecurityException(
+ "Caller does not have permission to execute the"
+ + " appfunction"));
}
+ return isAppFunctionEnabled(
+ requestInternal
+ .getClientRequest()
+ .getFunctionIdentifier(),
+ requestInternal
+ .getClientRequest()
+ .getTargetPackageName(),
+ getAppSearchManagerAsUser(
+ requestInternal.getUserHandle()),
+ THREAD_POOL_EXECUTOR)
+ .thenApply(
+ isEnabled -> {
+ if (!isEnabled) {
+ throw new DisabledAppFunctionException(
+ "The app function is disabled");
+ }
+ return canExecuteResult;
+ });
})
.thenAccept(
- unused -> {
+ canExecuteResult -> {
+ int bindFlags = Context.BIND_AUTO_CREATE;
+ if (canExecuteResult
+ == CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_HAS_PERMISSION) {
+ // If the caller doesn't have the permission, do not use
+ // BIND_FOREGROUND_SERVICE to avoid it raising its process state by
+ // calling its own AppFunctions.
+ bindFlags |= Context.BIND_FOREGROUND_SERVICE;
+ }
Intent serviceIntent =
mInternalServiceHelper.resolveAppFunctionService(
targetPackageName, targetUser);
@@ -294,8 +308,7 @@
targetUser,
localCancelTransport,
safeExecuteAppFunctionCallback,
- /* bindFlags= */ Context.BIND_AUTO_CREATE
- | Context.BIND_FOREGROUND_SERVICE,
+ bindFlags,
callerBinder,
callingUid);
})
diff --git a/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java b/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java
index 98ef974..c8038a4 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java
@@ -17,12 +17,16 @@
package com.android.server.appfunctions;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.UserHandle;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Interface for validating that the caller has the correct privilege to call an AppFunctionManager
* API.
@@ -70,7 +74,8 @@
* @param functionId The id of the app function to execute.
* @return Whether the caller can execute the specified app function.
*/
- AndroidFuture<Boolean> verifyCallerCanExecuteAppFunction(
+ @CanExecuteAppFunctionResult
+ AndroidFuture<Integer> verifyCallerCanExecuteAppFunction(
int callingUid,
int callingPid,
@NonNull UserHandle targetUser,
@@ -78,6 +83,31 @@
@NonNull String targetPackageName,
@NonNull String functionId);
+ @IntDef(
+ prefix = {"CAN_EXECUTE_APP_FUNCTIONS_"},
+ value = {
+ CAN_EXECUTE_APP_FUNCTIONS_DENIED,
+ CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_SAME_PACKAGE,
+ CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_HAS_PERMISSION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface CanExecuteAppFunctionResult {}
+
+ /** Callers are not allowed to execute app functions. */
+ int CAN_EXECUTE_APP_FUNCTIONS_DENIED = 0;
+
+ /**
+ * Callers can execute app functions because they are calling app functions from the same
+ * package.
+ */
+ int CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_SAME_PACKAGE = 1;
+
+ /**
+ * Callers can execute app functions because they have the necessary permission.
+ * This case also applies when a caller with the permission invokes their own app functions.
+ */
+ int CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_HAS_PERMISSION = 2;
+
/**
* Checks if the app function policy is allowed.
*
diff --git a/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java b/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java
index fe163d7..3f8b2e3 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java
@@ -16,24 +16,12 @@
package com.android.server.appfunctions;
-import static android.app.appfunctions.AppFunctionStaticMetadataHelper.APP_FUNCTION_STATIC_METADATA_DB;
-import static android.app.appfunctions.AppFunctionStaticMetadataHelper.APP_FUNCTION_STATIC_NAMESPACE;
-import static android.app.appfunctions.AppFunctionStaticMetadataHelper.getDocumentIdForAppFunction;
-
-import static com.android.server.appfunctions.AppFunctionExecutors.THREAD_POOL_EXECUTOR;
-
import android.Manifest;
import android.annotation.BinderThread;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager.AppFunctionsPolicy;
-import android.app.appsearch.AppSearchBatchResult;
-import android.app.appsearch.AppSearchManager;
-import android.app.appsearch.AppSearchManager.SearchContext;
-import android.app.appsearch.AppSearchResult;
-import android.app.appsearch.GenericDocument;
-import android.app.appsearch.GetByDocumentIdRequest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -84,64 +72,25 @@
@Override
@RequiresPermission(Manifest.permission.EXECUTE_APP_FUNCTIONS)
- public AndroidFuture<Boolean> verifyCallerCanExecuteAppFunction(
+ @CanExecuteAppFunctionResult
+ public AndroidFuture<Integer> verifyCallerCanExecuteAppFunction(
int callingUid,
int callingPid,
@NonNull UserHandle targetUser,
@NonNull String callerPackageName,
@NonNull String targetPackageName,
@NonNull String functionId) {
- if (callerPackageName.equals(targetPackageName)) {
- return AndroidFuture.completedFuture(true);
- }
-
boolean hasExecutionPermission =
mContext.checkPermission(
- Manifest.permission.EXECUTE_APP_FUNCTIONS, callingPid, callingUid)
+ Manifest.permission.EXECUTE_APP_FUNCTIONS, callingPid, callingUid)
== PackageManager.PERMISSION_GRANTED;
-
- if (!hasExecutionPermission) {
- return AndroidFuture.completedFuture(false);
+ if (hasExecutionPermission) {
+ return AndroidFuture.completedFuture(CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_HAS_PERMISSION);
}
-
- FutureAppSearchSession futureAppSearchSession =
- new FutureAppSearchSessionImpl(
- Objects.requireNonNull(
- mContext.createContextAsUser(targetUser, 0)
- .getSystemService(AppSearchManager.class)),
- THREAD_POOL_EXECUTOR,
- new SearchContext.Builder(APP_FUNCTION_STATIC_METADATA_DB).build());
-
- String documentId = getDocumentIdForAppFunction(targetPackageName, functionId);
-
- return futureAppSearchSession
- .getByDocumentId(
- new GetByDocumentIdRequest.Builder(APP_FUNCTION_STATIC_NAMESPACE)
- .addIds(documentId)
- .build())
- .thenApply(
- batchResult -> getGenericDocumentFromBatchResult(batchResult, documentId))
- // At this point, already checked the app has the permission.
- .thenApply(document -> true)
- .whenComplete(
- (result, throwable) -> {
- futureAppSearchSession.close();
- });
- }
-
- private static GenericDocument getGenericDocumentFromBatchResult(
- AppSearchBatchResult<String, GenericDocument> result, String documentId) {
- if (result.isSuccess()) {
- return result.getSuccesses().get(documentId);
+ if (callerPackageName.equals(targetPackageName)) {
+ return AndroidFuture.completedFuture(CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_SAME_PACKAGE);
}
-
- AppSearchResult<GenericDocument> failedResult = result.getFailures().get(documentId);
- throw new AppSearchException(
- failedResult.getResultCode(),
- "Unable to retrieve document with id: "
- + documentId
- + " due to "
- + failedResult.getErrorMessage());
+ return AndroidFuture.completedFuture(CAN_EXECUTE_APP_FUNCTIONS_DENIED);
}
@Override
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
index 8119073..9548afe 100644
--- a/services/appwidget/Android.bp
+++ b/services/appwidget/Android.bp
@@ -17,6 +17,12 @@
java_library_static {
name: "services.appwidget",
defaults: ["platform_service_defaults"],
- srcs: [":services.appwidget-sources"],
- libs: ["services.core"],
+ srcs: [
+ ":services.appwidget-sources",
+ ":statslog-framework-java-gen",
+ ],
+ libs: [
+ "androidx.annotation_annotation",
+ "services.core",
+ ],
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index e0f2939..4441db7 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -50,6 +50,7 @@
import android.app.IServiceConnection;
import android.app.KeyguardManager;
import android.app.PendingIntent;
+import android.app.StatsManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
import android.app.usage.Flags;
@@ -124,6 +125,7 @@
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
+import android.util.StatsEvent;
import android.util.TypedValue;
import android.util.Xml;
import android.util.proto.ProtoInputStream;
@@ -145,6 +147,7 @@
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.IRemoteViewsFactory;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -433,6 +436,44 @@
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mAppOpsManagerInternal = LocalServices.getService(AppOpsManagerInternal.class);
mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
+ registerPullCallbacks();
+ }
+
+ /**
+ * Register callbacks for pull atoms.
+ */
+ private void registerPullCallbacks() {
+ final StatsManager manager = mContext.getSystemService(StatsManager.class);
+ manager.setPullAtomCallback(FrameworkStatsLog.WIDGET_MEMORY_STATS,
+ new StatsManager.PullAtomMetadata.Builder().build(),
+ new HandlerExecutor(mCallbackHandler), this::onPullAtom);
+ }
+
+ /**
+ * Callback from StatsManager to log events indicated by the atomTag. This function will add
+ * the relevant events to the data list.
+ *
+ * @return PULL_SUCCESS if the pull was successful and events should be used, else PULL_SKIP.
+ */
+ private int onPullAtom(int atomTag, @NonNull List<StatsEvent> data) {
+ if (atomTag == FrameworkStatsLog.WIDGET_MEMORY_STATS) {
+ synchronized (mLock) {
+ for (Widget widget : mWidgets) {
+ if (widget.views != null) {
+ final int uid = widget.provider.id.uid;
+ final int appWidgetId = widget.appWidgetId;
+ final long bitmapMemoryUsage =
+ widget.views.estimateTotalBitmapMemoryUsage();
+ StatsEvent event = FrameworkStatsLog.buildStatsEvent(
+ FrameworkStatsLog.WIDGET_MEMORY_STATS, uid, appWidgetId,
+ bitmapMemoryUsage);
+ data.add(event);
+ }
+ }
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+ return StatsManager.PULL_SKIP;
}
/**
@@ -5191,7 +5232,7 @@
}
}
return singleCategoryKeyedEntries;
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to load generated previews for " + provider, e);
return new SparseArray<>();
}
@@ -5220,7 +5261,7 @@
try {
provider.info.generatedPreviewCategories = readGeneratedPreviewCategoriesFromProto(
input);
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to read generated previews from file for " + provider, e);
previewsFile.delete();
provider.info.generatedPreviewCategories = 0;
@@ -5273,7 +5314,7 @@
scheduleNotifyGroupHostsForProvidersChangedLocked(provider.getUserId());
}
}
- } catch (IOException e) {
+ } catch (Exception e) {
if (file != null && stream != null) {
file.failWrite(stream);
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 05301fd..4f56483 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -31,6 +31,8 @@
import static com.android.internal.util.CollectionUtils.any;
import static com.android.internal.util.Preconditions.checkState;
+import static com.android.server.companion.association.DisassociationProcessor.REASON_API;
+import static com.android.server.companion.association.DisassociationProcessor.REASON_PKG_DATA_CLEARED;
import static com.android.server.companion.utils.PackageUtils.enforceUsesCompanionDeviceFeature;
import static com.android.server.companion.utils.PackageUtils.isRestrictedSettingsAllowed;
import static com.android.server.companion.utils.PermissionsUtils.enforceCallerCanManageAssociationsForPackage;
@@ -250,7 +252,7 @@
+ packageName + "]. Cleaning up CDM data...");
for (AssociationInfo association : associationsForPackage) {
- mDisassociationProcessor.disassociate(association.getId());
+ mDisassociationProcessor.disassociate(association.getId(), REASON_PKG_DATA_CLEARED);
}
mCompanionAppBinder.onPackageChanged(userId);
@@ -426,7 +428,7 @@
@Override
public void disassociate(int associationId) {
- mDisassociationProcessor.disassociate(associationId);
+ mDisassociationProcessor.disassociate(associationId, REASON_API);
}
@Override
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index e7d1460..c5ac7c3 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -18,6 +18,8 @@
import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC;
+import static com.android.server.companion.association.DisassociationProcessor.REASON_SHELL;
+
import android.companion.AssociationInfo;
import android.companion.ContextSyncMessage;
import android.companion.Flags;
@@ -122,7 +124,7 @@
if (association == null) {
out.println("Association doesn't exist.");
} else {
- mDisassociationProcessor.disassociate(association.getId());
+ mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL);
}
}
break;
@@ -132,7 +134,7 @@
final List<AssociationInfo> userAssociations =
mAssociationStore.getAssociationsByUser(userId);
for (AssociationInfo association : userAssociations) {
- mDisassociationProcessor.disassociate(association.getId());
+ mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL);
}
}
break;
diff --git a/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java b/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java
index f2d019b..ce7dcd0 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationDiskStore.java
@@ -58,6 +58,7 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@@ -164,6 +165,7 @@
private static final String FILE_NAME_LEGACY = "companion_device_manager_associations.xml";
private static final String FILE_NAME = "companion_device_manager.xml";
+ private static final String FILE_NAME_LAST_REMOVED_ASSOCIATION = "last_removed_association.txt";
private static final String XML_TAG_STATE = "state";
private static final String XML_TAG_ASSOCIATIONS = "associations";
@@ -268,6 +270,46 @@
}
}
+ /**
+ * Read the last removed association from disk.
+ */
+ public String readLastRemovedAssociation(@UserIdInt int userId) {
+ final AtomicFile file = createStorageFileForUser(
+ userId, FILE_NAME_LAST_REMOVED_ASSOCIATION);
+ StringBuilder sb = new StringBuilder();
+ int c;
+ try (FileInputStream fis = file.openRead()) {
+ while ((c = fis.read()) != -1) {
+ sb.append((char) c);
+ }
+ fis.close();
+ return sb.toString();
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "File " + file + " for user=" + userId + " doesn't exist.");
+ return null;
+ } catch (IOException e) {
+ Slog.e(TAG, "Can't read file " + file + " for user=" + userId);
+ return null;
+ }
+ }
+
+ /**
+ * Write the last removed association to disk.
+ */
+ public void writeLastRemovedAssociation(AssociationInfo association, String reason) {
+ Slog.i(TAG, "Writing last removed association=" + association.getId() + " to disk...");
+
+ final AtomicFile file = createStorageFileForUser(
+ association.getUserId(), FILE_NAME_LAST_REMOVED_ASSOCIATION);
+ writeToFileSafely(file, out -> {
+ out.write(String.valueOf(System.currentTimeMillis()).getBytes());
+ out.write(' ');
+ out.write(reason.getBytes());
+ out.write(' ');
+ out.write(association.toString().getBytes());
+ });
+ }
+
@NonNull
private static Associations readAssociationsFromFile(@UserIdInt int userId,
@NonNull AtomicFile file, @NonNull String rootTag) {
diff --git a/services/companion/java/com/android/server/companion/association/AssociationStore.java b/services/companion/java/com/android/server/companion/association/AssociationStore.java
index 757abd9..f70c434 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationStore.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationStore.java
@@ -276,7 +276,7 @@
/**
* Remove an association.
*/
- public void removeAssociation(int id) {
+ public void removeAssociation(int id, String reason) {
Slog.i(TAG, "Removing association id=[" + id + "]...");
final AssociationInfo association;
@@ -291,6 +291,8 @@
writeCacheToDisk(association.getUserId());
+ mDiskStore.writeLastRemovedAssociation(association, reason);
+
Slog.i(TAG, "Done removing association.");
}
@@ -525,6 +527,14 @@
out.append(" ").append(a.toString()).append('\n');
}
}
+
+ out.append("Last Removed Association:\n");
+ for (UserInfo user : mUserManager.getAliveUsers()) {
+ String lastRemovedAssociation = mDiskStore.readLastRemovedAssociation(user.id);
+ if (lastRemovedAssociation != null) {
+ out.append(" ").append(lastRemovedAssociation).append('\n');
+ }
+ }
}
private void broadcastChange(@ChangeType int changeType, AssociationInfo association) {
diff --git a/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java b/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java
index 150e8da..248056f3 100644
--- a/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java
+++ b/services/companion/java/com/android/server/companion/association/DisassociationProcessor.java
@@ -47,6 +47,13 @@
@SuppressLint("LongLogTag")
public class DisassociationProcessor {
+ public static final String REASON_REVOKED = "revoked";
+ public static final String REASON_SELF_IDLE = "self-idle";
+ public static final String REASON_SHELL = "shell";
+ public static final String REASON_LEGACY = "legacy";
+ public static final String REASON_API = "api";
+ public static final String REASON_PKG_DATA_CLEARED = "pkg-data-cleared";
+
private static final String TAG = "CDM_DisassociationProcessor";
private static final String SYS_PROP_DEBUG_REMOVAL_TIME_WINDOW =
@@ -94,7 +101,7 @@
* Disassociate an association by id.
*/
// TODO: also revoke notification access
- public void disassociate(int id) {
+ public void disassociate(int id, String reason) {
Slog.i(TAG, "Disassociating id=[" + id + "]...");
final AssociationInfo association = mAssociationStore.getAssociationWithCallerChecks(id);
@@ -126,7 +133,7 @@
// Association cleanup.
mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, id);
- mAssociationStore.removeAssociation(association.getId());
+ mAssociationStore.removeAssociation(association.getId(), reason);
// If role is not in use by other associations, revoke the role.
// Do not need to remove the system role since it was pre-granted by the system.
@@ -151,7 +158,7 @@
}
/**
- * @deprecated Use {@link #disassociate(int)} instead.
+ * @deprecated Use {@link #disassociate(int, String)} instead.
*/
@Deprecated
public void disassociate(int userId, String packageName, String macAddress) {
@@ -165,7 +172,7 @@
mAssociationStore.getAssociationWithCallerChecks(association.getId());
- disassociate(association.getId());
+ disassociate(association.getId(), REASON_LEGACY);
}
@SuppressLint("MissingPermission")
@@ -223,7 +230,7 @@
Slog.i(TAG, "Removing inactive self-managed association=[" + association.toShortString()
+ "].");
- disassociate(id);
+ disassociate(id, REASON_SELF_IDLE);
}
}
@@ -234,7 +241,7 @@
*
* Lastly remove the role holder for the revoked associations for the same packages.
*
- * @see #disassociate(int)
+ * @see #disassociate(int, String)
*/
private class OnPackageVisibilityChangeListener implements
ActivityManager.OnUidImportanceListener {
@@ -260,7 +267,7 @@
int userId = UserHandle.getUserId(uid);
for (AssociationInfo association : mAssociationStore.getRevokedAssociations(userId,
packageName)) {
- disassociate(association.getId());
+ disassociate(association.getId(), REASON_REVOKED);
}
if (mAssociationStore.getRevokedAssociations().isEmpty()) {
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 139bbae..93b4de8 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -891,6 +891,11 @@
}
@Override
+ public VirtualDevice getVirtualDevice(int deviceId) {
+ return mImpl.getVirtualDevice(deviceId);
+ }
+
+ @Override
public long getDimDurationMillisForDeviceId(int deviceId) {
VirtualDeviceImpl virtualDevice = getVirtualDeviceForId(deviceId);
return virtualDevice == null ? -1 : virtualDevice.getDimDurationMillis();
diff --git a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
index d8e10f8..7eb7072 100644
--- a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
+++ b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
@@ -365,7 +365,7 @@
}
}
final ScreenshotHardwareBuffer shb = mWmInternal.takeContextualSearchScreenshot(
- (Flags.contextualSearchWindowLayer() ? csUid : -1));
+ (Flags.contextualSearchPreventSelfCapture() ? csUid : -1));
final Bitmap bm = shb != null ? shb.asBitmap() : null;
// Now that everything is fetched, putting it in the launchIntent.
if (bm != null) {
@@ -549,7 +549,7 @@
Binder.withCleanCallingIdentity(() -> {
final ScreenshotHardwareBuffer shb =
mWmInternal.takeContextualSearchScreenshot(
- (Flags.contextualSearchWindowLayer() ? callingUid : -1));
+ (Flags.contextualSearchPreventSelfCapture() ? callingUid : -1));
final Bitmap bm = shb != null ? shb.asBitmap() : null;
if (bm != null) {
bundle.putParcelable(ContextualSearchManager.EXTRA_SCREENSHOT,
diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
index 04edb57..cd632e6 100644
--- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
+++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
@@ -31,6 +31,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -81,6 +83,8 @@
private PackageManagerInternal mPackageManagerInternal;
+ private RoleManager mRoleManager;
+
@Nullable
private WindowManagerInternal mWindowManager;
@@ -225,7 +229,8 @@
}
@Override
- public void onStart() {}
+ public void onStart() {
+ }
@Override
public void onBootPhase(int phase) {
@@ -237,6 +242,7 @@
init(getContext().getSystemService(MediaProjectionManager.class),
LocalServices.getService(WindowManagerInternal.class),
LocalServices.getService(PackageManagerInternal.class),
+ getContext().getSystemService(RoleManager.class),
getExemptedPackages()
);
if (sensitiveContentAppProtection()) {
@@ -247,7 +253,8 @@
@VisibleForTesting
void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager,
- PackageManagerInternal packageManagerInternal, ArraySet<String> exemptedPackages) {
+ PackageManagerInternal packageManagerInternal, RoleManager roleManager,
+ ArraySet<String> exemptedPackages) {
if (DEBUG) Log.d(TAG, "init");
Objects.requireNonNull(projectionManager);
@@ -256,6 +263,7 @@
mProjectionManager = projectionManager;
mWindowManager = windowManager;
mPackageManagerInternal = packageManagerInternal;
+ mRoleManager = roleManager;
mExemptedPackages = exemptedPackages;
// TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary
@@ -312,8 +320,10 @@
boolean isPackageExempted = (mExemptedPackages != null && mExemptedPackages.contains(
projectionInfo.getPackageName()))
|| canRecordSensitiveContent(projectionInfo.getPackageName())
+ || holdsAppStreamingRole(projectionInfo.getPackageName(),
+ projectionInfo.getUserHandle())
|| isAutofillServiceRecorderPackage(projectionInfo.getUserHandle().getIdentifier(),
- projectionInfo.getPackageName());
+ projectionInfo.getPackageName());
// TODO(b/324447419): move GlobalSettings lookup to background thread
boolean isFeatureDisabled = Settings.Global.getInt(getContext().getContentResolver(),
DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 0) != 0;
@@ -348,6 +358,11 @@
}
}
+ private boolean holdsAppStreamingRole(String packageName, UserHandle userHandle) {
+ return mRoleManager.getRoleHoldersAsUser(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING, userHandle).contains(packageName);
+ }
+
private void onProjectionEnd() {
synchronized (mSensitiveContentProtectionLock) {
mProjectionActive = false;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d2a5734..b6fe0ad 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -49,7 +49,6 @@
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
-import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -2443,6 +2442,7 @@
} catch (Installer.InstallerException e) {
Slog.e(TAG, "Failed unmount mirror data", e);
}
+ extendWatchdogTimeout("#unmount might be slow");
mVold.unmount(vol.getId());
mStorageSessionController.onVolumeUnmount(vol.getImmutableVolumeInfo());
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index cce2959..125824c 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -618,7 +618,7 @@
Slog.i(TAG, " Stopping fg for service " + r);
}
setServiceForegroundInnerLocked(r, 0, null, 0, 0,
- 0);
+ 0, /* systemRequestedTransition= */ true);
}
}
@@ -1839,7 +1839,7 @@
ServiceRecord r = findServiceLocked(className, token, userId);
if (r != null) {
setServiceForegroundInnerLocked(r, id, notification, flags, foregroundServiceType,
- callingUid);
+ callingUid, /* systemRequestedTransition= */ false);
}
} finally {
mAm.mInjector.restoreCallingIdentity(origId);
@@ -2155,7 +2155,7 @@
@GuardedBy("mAm")
private void setServiceForegroundInnerLocked(final ServiceRecord r, int id,
Notification notification, int flags, int foregroundServiceType,
- int callingUidIfStart) {
+ int callingUidIfStart, boolean systemRequestedTransition) {
if (id != 0) {
if (notification == null) {
throw new IllegalArgumentException("null notification");
@@ -2800,6 +2800,7 @@
// earlier.
r.foregroundServiceType = 0;
r.mFgsNotificationWasDeferred = false;
+ r.systemRequestedFgToBg = systemRequestedTransition;
signalForegroundServiceObserversLocked(r);
resetFgsRestrictionLocked(r);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
@@ -9339,14 +9340,22 @@
if (sr.foregroundServiceType
== ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE
&& sr.foregroundId == notificationId) {
- if (DEBUG_FOREGROUND_SERVICE) {
- Slog.d(TAG, "Moving media service to foreground for package "
- + packageName);
+ // check if service is explicitly requested by app to not be in foreground.
+ if (sr.systemRequestedFgToBg) {
+ Slog.d(TAG,
+ "System initiated service transition to foreground "
+ + "for package "
+ + packageName);
+ setServiceForegroundInnerLocked(sr, sr.foregroundId,
+ sr.foregroundNoti, /* flags */ 0,
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
+ /* callingUidStart */ 0, /* systemRequestedTransition */ true);
+ } else {
+ Slog.d(TAG,
+ "Ignoring system initiated foreground service transition for "
+ + "package"
+ + packageName);
}
- setServiceForegroundInnerLocked(sr, sr.foregroundId,
- sr.foregroundNoti, /* flags */ 0,
- ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
- /* callingUidStart */ 0);
}
}
}
@@ -9379,13 +9388,14 @@
if (sr.foregroundServiceType
== ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
&& sr.foregroundId == notificationId) {
- if (DEBUG_FOREGROUND_SERVICE) {
- Slog.d(TAG, "Forcing media foreground service to background for package "
- + packageName);
- }
+ Slog.d(TAG,
+ "System initiated transition of foreground service(type:media) to bg "
+ + "for package"
+ + packageName);
setServiceForegroundInnerLocked(sr, /* id */ 0,
/* notification */ null, /* flags */ 0,
- /* foregroundServiceType */ 0, /* callingUidStart */ 0);
+ /* foregroundServiceType */ 0, /* callingUidStart */ 0,
+ /* systemRequestedTransition */ true);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6e3d7bd..8b701f0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -198,6 +198,7 @@
import android.annotation.PermissionMethod;
import android.annotation.PermissionName;
import android.annotation.RequiresPermission;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityClient;
@@ -301,6 +302,7 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
+import android.content.pm.SystemFeaturesCache;
import android.content.pm.TestUtilityService;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
@@ -2559,9 +2561,20 @@
mTraceErrorLogger = new TraceErrorLogger();
mComponentAliasResolver = new ComponentAliasResolver(this);
sCreatorTokenCacheCleaner = new Handler(mHandlerThread.getLooper());
+
+ ApplicationSharedMemory applicationSharedMemory = ApplicationSharedMemory.getInstance();
+ if (android.content.pm.Flags.cacheSdkSystemFeatures()) {
+ // Install the cache into the process-wide singleton for in-proc queries, as well as
+ // shared memory. Apps will inflate the cache from shared memory in bindApplication.
+ SystemFeaturesCache systemFeaturesCache =
+ new SystemFeaturesCache(SystemConfig.getInstance().getAvailableFeatures());
+ SystemFeaturesCache.setInstance(systemFeaturesCache);
+ applicationSharedMemory.writeSystemFeaturesCache(
+ systemFeaturesCache.getSdkFeatureVersions());
+ }
try {
mApplicationSharedMemoryReadOnlyFd =
- ApplicationSharedMemory.getInstance().getReadOnlyFileDescriptor();
+ applicationSharedMemory.getReadOnlyFileDescriptor();
} catch (IOException e) {
Slog.e(TAG, "Failed to get read only fd for shared memory", e);
throw new RuntimeException(e);
@@ -3909,8 +3922,8 @@
* The pkg name and app id have to be specified.
*/
@Override
- public void killApplication(String pkg, int appId, int userId, String reason,
- int exitInfoReason) {
+ public void killApplication(String pkg, int appId, @CanBeALL @UserIdInt int userId,
+ String reason, int exitInfoReason) {
if (pkg == null) {
return;
}
@@ -4295,7 +4308,7 @@
final boolean forceStopPackageLocked(String packageName, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, boolean uninstalling, boolean packageStateStopped,
- int userId, String reasonString, int reason) {
+ @CanBeALL @UserIdInt int userId, String reasonString, int reason) {
return forceStopPackageInternalLocked(packageName, appId, callerWillRestart, purgeCache,
doit, evenPersistent, uninstalling, packageStateStopped, userId, reasonString,
reason, ProcessList.INVALID_ADJ);
@@ -4305,7 +4318,7 @@
private boolean forceStopPackageInternalLocked(String packageName, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, boolean uninstalling, boolean packageStateStopped,
- int userId, String reasonString, int reason, int minOomAdj) {
+ @CanBeALL @UserIdInt int userId, String reasonString, int reason, int minOomAdj) {
int i;
if (userId == UserHandle.USER_ALL && packageName == null) {
@@ -18081,7 +18094,7 @@
}
@Override
- public void killApplicationSync(String pkgName, int appId, int userId,
+ public void killApplicationSync(String pkgName, int appId, @CanBeALL @UserIdInt int userId,
String reason, int exitInfoReason) {
if (pkgName == null) {
return;
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index b677297..4bfee1d 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1464,7 +1464,10 @@
void onProcessFrozen(ProcessRecord frozenProc) {
if (useCompaction()) {
synchronized (mProcLock) {
- compactApp(frozenProc, CompactProfile.FULL, CompactSource.APP, false);
+ // only full-compact if process is cached
+ if (frozenProc.mState.getSetAdj() >= mCompactThrottleMinOomAdj) {
+ compactApp(frozenProc, CompactProfile.FULL, CompactSource.APP, false);
+ }
}
}
frozenProc.onProcessFrozen();
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index cc6fabc..4b6d6bc 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -68,7 +68,7 @@
per-file ActivityManager* = file:/ACTIVITY_SECURITY_OWNERS
# Aconfig Flags
-per-file flags.aconfig = yamasani@google.com, bills@google.com, nalini@google.com
+per-file flags.aconfig = yamasani@google.com, nalini@google.com
# Londoners
michaelwr@google.com #{LAST_RESORT_SUGGESTION}
@@ -77,4 +77,4 @@
# Default
yamasani@google.com
hackbod@google.com #{LAST_RESORT_SUGGESTION}
-omakoto@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
+omakoto@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 61c5501..13d367a 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -446,6 +446,8 @@
private static final int CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD =
Flags.raiseBoundUiServiceThreshold() ? SERVICE_ADJ : PERCEPTIBLE_APP_ADJ;
+ static final long PERCEPTIBLE_TASK_TIMEOUT_MILLIS = 5 * 60 * 1000;
+
@VisibleForTesting
public static class Injector {
boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -1847,7 +1849,7 @@
mHasVisibleActivities = false;
}
- void onOtherActivity() {
+ void onOtherActivity(long perceptibleTaskStoppedTimeMillis) {
if (procState > PROCESS_STATE_CACHED_ACTIVITY) {
procState = PROCESS_STATE_CACHED_ACTIVITY;
mAdjType = "cch-act";
@@ -1856,6 +1858,28 @@
"Raise procstate to cached activity: " + app);
}
}
+ if (Flags.perceptibleTasks() && adj > PERCEPTIBLE_MEDIUM_APP_ADJ) {
+ if (perceptibleTaskStoppedTimeMillis >= 0) {
+ final long now = mInjector.getUptimeMillis();
+ if (now - perceptibleTaskStoppedTimeMillis < PERCEPTIBLE_TASK_TIMEOUT_MILLIS) {
+ adj = PERCEPTIBLE_MEDIUM_APP_ADJ;
+ mAdjType = "perceptible-act";
+ if (procState > PROCESS_STATE_IMPORTANT_BACKGROUND) {
+ procState = PROCESS_STATE_IMPORTANT_BACKGROUND;
+ }
+
+ maybeSetProcessFollowUpUpdateLocked(app,
+ perceptibleTaskStoppedTimeMillis + PERCEPTIBLE_TASK_TIMEOUT_MILLIS,
+ now);
+ } else if (adj > PREVIOUS_APP_ADJ) {
+ adj = PREVIOUS_APP_ADJ;
+ mAdjType = "stale-perceptible-act";
+ if (procState > PROCESS_STATE_LAST_ACTIVITY) {
+ procState = PROCESS_STATE_LAST_ACTIVITY;
+ }
+ }
+ }
+ }
mHasVisibleActivities = false;
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b8babe6..a61368c 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -67,6 +67,8 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityThread;
@@ -2961,8 +2963,8 @@
}
@GuardedBy({"mService", "mProcLock"})
- boolean killPackageProcessesLSP(String packageName, int appId, int userId, int minOomAdj,
- int reasonCode, int subReason, String reason) {
+ boolean killPackageProcessesLSP(String packageName, int appId, @CanBeALL @UserIdInt int userId,
+ int minOomAdj, int reasonCode, int subReason, String reason) {
return killPackageProcessesLSP(packageName, appId, userId, minOomAdj,
false /* callerWillRestart */, true /* allowRestart */, true /* doit */,
false /* evenPersistent */, false /* setRemoved */, false /* uninstalling */,
@@ -2970,7 +2972,8 @@
}
@GuardedBy("mService")
- void killAppZygotesLocked(String packageName, int appId, int userId, boolean force) {
+ void killAppZygotesLocked(String packageName, int appId, @CanBeALL @UserIdInt int userId,
+ boolean force) {
// See if there are any app zygotes running for this packageName / UID combination,
// and kill it if so.
final ArrayList<AppZygote> zygotesToKill = new ArrayList<>();
@@ -3050,9 +3053,9 @@
@GuardedBy({"mService", "mProcLock"})
boolean killPackageProcessesLSP(String packageName, int appId,
- int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
- boolean doit, boolean evenPersistent, boolean setRemoved, boolean uninstalling,
- int reasonCode, int subReason, String reason) {
+ @CanBeALL @UserIdInt int userId, int minOomAdj, boolean callerWillRestart,
+ boolean allowRestart, boolean doit, boolean evenPersistent, boolean setRemoved,
+ boolean uninstalling, int reasonCode, int subReason, String reason) {
final PackageManagerInternal pm = mService.getPackageManagerInternal();
final ArrayList<Pair<ProcessRecord, Boolean>> procs = new ArrayList<>();
@@ -5220,7 +5223,7 @@
}
@GuardedBy("mService")
- void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
+ void sendPackageBroadcastLocked(int cmd, String[] packages, @CanBeALL @UserIdInt int userId) {
boolean foundProcess = false;
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index b0f808b..25175e6 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -1120,7 +1120,8 @@
} else if ((flags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) {
callback.onStoppingActivity((flags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0);
} else {
- callback.onOtherActivity();
+ final long ts = mApp.getWindowProcessController().getPerceptibleTaskStoppedTimeMillis();
+ callback.onOtherActivity(ts);
}
mCachedAdj = callback.adj;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index ca34a13..f443e44 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -158,6 +158,7 @@
boolean fgWaiting; // is a timeout for going foreground already scheduled?
boolean isNotAppComponentUsage; // is service binding not considered component/package usage?
boolean isForeground; // is service currently in foreground mode?
+ boolean systemRequestedFgToBg; // system requested service to transition to background.
boolean inSharedIsolatedProcess; // is the service in a shared isolated process
int foregroundId; // Notification ID of last foreground req.
Notification foregroundNoti; // Notification record of foreground state.
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index e0fbaf4..18f3500 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -4059,7 +4059,7 @@
synchronized (mUserSwitchingDialogLock) {
dismissUserSwitchingDialog(null);
mUserSwitchingDialog = new UserSwitchingDialog(mService.mContext, fromUser, toUser,
- switchingFromSystemUserMessage, switchingToSystemUserMessage);
+ mHandler, switchingFromSystemUserMessage, switchingToSystemUserMessage);
mUserSwitchingDialog.show(onShown);
}
}
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index d1fcb9d..223e0b7 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -34,7 +34,6 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.os.Looper;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
@@ -72,7 +71,7 @@
// Time to wait for the onAnimationEnd() callbacks before moving on
private static final int ANIMATION_TIMEOUT_MS = 1000;
- private final Handler mHandler = new Handler(Looper.myLooper());
+ private final Handler mHandler;
protected final UserInfo mOldUser;
protected final UserInfo mNewUser;
@@ -81,13 +80,14 @@
protected final Context mContext;
private final int mTraceCookie;
- UserSwitchingDialog(Context context, UserInfo oldUser, UserInfo newUser,
+ UserSwitchingDialog(Context context, UserInfo oldUser, UserInfo newUser, Handler handler,
String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
super(context, R.style.Theme_Material_NoActionBar_Fullscreen);
mContext = context;
mOldUser = oldUser;
mNewUser = newUser;
+ mHandler = handler;
mSwitchingFromSystemUserMessage = switchingFromSystemUserMessage;
mSwitchingToSystemUserMessage = switchingToSystemUserMessage;
mDisableAnimations = SystemProperties.getBoolean(
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 27c384a..c8fedf3 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -293,6 +293,13 @@
}
flag {
+ name: "perceptible_tasks"
+ namespace: "system_performance"
+ description: "Boost the oom_score_adj of activities in perceptible tasks"
+ bug: "370890207"
+}
+
+flag {
name: "expedite_activity_launch_on_cold_start"
namespace: "system_performance"
description: "Notify ActivityTaskManager of cold starts early to fix app launch behavior."
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 813e661..b85967f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -954,7 +954,8 @@
/**
* Stores information about a device using absolute volume behavior.
*/
- private static final class AbsoluteVolumeDeviceInfo {
+ private static final class AbsoluteVolumeDeviceInfo implements IBinder.DeathRecipient {
+ private final AudioService mParent;
private final AudioDeviceAttributes mDevice;
private final List<VolumeInfo> mVolumeInfos;
private final IAudioDeviceVolumeDispatcher mCallback;
@@ -962,16 +963,26 @@
private @AudioManager.AbsoluteDeviceVolumeBehavior int mDeviceVolumeBehavior;
private AbsoluteVolumeDeviceInfo(
+ AudioService parent,
AudioDeviceAttributes device,
List<VolumeInfo> volumeInfos,
IAudioDeviceVolumeDispatcher callback,
boolean handlesVolumeAdjustment,
@AudioManager.AbsoluteDeviceVolumeBehavior int behavior) {
+ this.mParent = parent;
this.mDevice = device;
this.mVolumeInfos = volumeInfos;
this.mCallback = callback;
this.mHandlesVolumeAdjustment = handlesVolumeAdjustment;
this.mDeviceVolumeBehavior = behavior;
+
+ try {
+ this.mCallback.asBinder().linkToDeath(this, 0);
+ } catch (RemoteException | NullPointerException e) {
+ // NPE can be raised when mocking the callback object
+ Slog.w(TAG, "Exception: " + e
+ + "\nCannot listen to callback binder death for device " + mDevice);
+ }
}
/**
@@ -991,6 +1002,25 @@
}
return null;
}
+
+ @Override
+ public void binderDied() {
+ if (mParent.removeAudioSystemDeviceOutFromAbsVolumeDevices(mDevice.getInternalType())
+ != null) {
+ mParent.dispatchDeviceVolumeBehavior(mDevice,
+ AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE);
+ }
+ }
+
+ public void unlinkToDeath() {
+ try {
+ mCallback.asBinder().unlinkToDeath(this, 0);
+ } catch (NullPointerException e) {
+ // NPE can be raised when mocking the callback object
+ Slog.w(TAG, "Exception: " + e
+ + "\nCannot unlink to death, null binder object for device " + mDevice);
+ }
+ }
}
// Devices for the which use the "absolute volume" concept (framework sends audio signal
@@ -8142,16 +8172,16 @@
int deviceOut = device.getInternalType();
if (register) {
- AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo(
+ AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo(this,
device, volumes, cb, handlesVolumeAdjustment, deviceVolumeBehavior);
final AbsoluteVolumeDeviceInfo oldInfo = getAbsoluteVolumeDeviceInfo(deviceOut);
+ addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info);
boolean volumeBehaviorChanged = (oldInfo == null)
|| (oldInfo.mDeviceVolumeBehavior != deviceVolumeBehavior);
if (volumeBehaviorChanged) {
removeAudioSystemDeviceOutFromFullVolumeDevices(deviceOut);
removeAudioSystemDeviceOutFromFixedVolumeDevices(deviceOut);
- addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info);
dispatchDeviceVolumeBehavior(device, deviceVolumeBehavior);
}
@@ -8177,8 +8207,10 @@
}
}
} else {
- boolean wasAbsVol = removeAudioSystemDeviceOutFromAbsVolumeDevices(deviceOut) != null;
- if (wasAbsVol) {
+ AbsoluteVolumeDeviceInfo deviceInfo = removeAudioSystemDeviceOutFromAbsVolumeDevices(
+ deviceOut);
+ if (deviceInfo != null) {
+ deviceInfo.unlinkToDeath();
dispatchDeviceVolumeBehavior(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE);
}
}
@@ -9718,72 +9750,78 @@
}
}
}
- }
- }
- if (changed) {
- // If associated to volume group, update group cache
- updateVolumeGroupIndex(device, /* forceMuteState= */ false);
+ if (changed) {
+ // If associated to volume group, update group cache
+ updateVolumeGroupIndex(device, /* forceMuteState= */ false);
- oldIndex = (oldIndex + 5) / 10;
- index = (index + 5) / 10;
- // log base stream changes to the event log
- if (sStreamVolumeAlias.get(mStreamType, /*valueIfKeyNotFound=*/-1) == mStreamType) {
- if (caller == null) {
- Log.w(TAG, "No caller for volume_changed event", new Throwable());
- }
- EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
- caller);
- }
- // fire changed intents for all streams, but only when the device it changed on
- // is the current device
- if ((index != oldIndex) && isCurrentDevice) {
- // for single volume devices, only send the volume change broadcast
- // on the alias stream
- final int streamAlias = sStreamVolumeAlias.get(
- mStreamType, /*valueIfKeyNotFound=*/-1);
- if (!mIsSingleVolume || streamAlias == mStreamType) {
- mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
- mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE,
- oldIndex);
- int extraStreamType = mStreamType;
- // TODO: remove this when deprecating STREAM_BLUETOOTH_SCO
- if (isStreamBluetoothSco(mStreamType)) {
- mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
- AudioSystem.STREAM_BLUETOOTH_SCO);
- extraStreamType = AudioSystem.STREAM_BLUETOOTH_SCO;
- } else {
- mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
- mStreamType);
- }
- mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
- streamAlias);
-
- if (mStreamType == streamAlias) {
- String aliasStreamIndexesString = "";
- if (!aliasStreamIndexes.isEmpty()) {
- aliasStreamIndexesString =
- " aliased streams: " + aliasStreamIndexes;
+ oldIndex = (oldIndex + 5) / 10;
+ index = (index + 5) / 10;
+ // log base stream changes to the event log
+ if (sStreamVolumeAlias.get(mStreamType, /*valueIfKeyNotFound=*/-1)
+ == mStreamType) {
+ if (caller == null) {
+ Log.w(TAG, "No caller for volume_changed event", new Throwable());
}
- AudioService.sVolumeLogger.enqueue(new VolChangedBroadcastEvent(
- extraStreamType, aliasStreamIndexesString, index, oldIndex));
- if (extraStreamType != mStreamType) {
- AudioService.sVolumeLogger.enqueue(new VolChangedBroadcastEvent(
- mStreamType, aliasStreamIndexesString, index, oldIndex));
+ EventLogTags.writeVolumeChanged(
+ mStreamType, oldIndex, index, mIndexMax / 10, caller);
+ }
+ // fire changed intents for all streams, but only when the device it changed
+ // on
+ // is the current device
+ if ((index != oldIndex) && isCurrentDevice) {
+ // for single volume devices, only send the volume change broadcast
+ // on the alias stream
+ final int streamAlias =
+ sStreamVolumeAlias.get(mStreamType, /*valueIfKeyNotFound=*/-1);
+ if (!mIsSingleVolume || streamAlias == mStreamType) {
+ mVolumeChanged.putExtra(
+ AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
+ mVolumeChanged.putExtra(
+ AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
+ int extraStreamType = mStreamType;
+ // TODO: remove this when deprecating STREAM_BLUETOOTH_SCO
+ if (isStreamBluetoothSco(mStreamType)) {
+ mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+ AudioSystem.STREAM_BLUETOOTH_SCO);
+ extraStreamType = AudioSystem.STREAM_BLUETOOTH_SCO;
+ } else {
+ mVolumeChanged.putExtra(
+ AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ }
+ mVolumeChanged.putExtra(
+ AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS, streamAlias);
+
+ if (mStreamType == streamAlias) {
+ String aliasStreamIndexesString = "";
+ if (!aliasStreamIndexes.isEmpty()) {
+ aliasStreamIndexesString =
+ " aliased streams: " + aliasStreamIndexes;
+ }
+ AudioService.sVolumeLogger.enqueue(
+ new VolChangedBroadcastEvent(extraStreamType,
+ aliasStreamIndexesString, index, oldIndex));
+ if (extraStreamType != mStreamType) {
+ AudioService.sVolumeLogger.enqueue(
+ new VolChangedBroadcastEvent(mStreamType,
+ aliasStreamIndexesString, index, oldIndex));
+ }
+ }
+ sendBroadcastToAll(mVolumeChanged, mVolumeChangedOptions);
+ if (extraStreamType != mStreamType) {
+ // send multiple intents in case we merged voice call and bt sco
+ // streams
+ mVolumeChanged.putExtra(
+ AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ // do not use the options in thid case which could discard
+ // the previous intent
+ sendBroadcastToAll(mVolumeChanged, null);
+ }
}
}
- sendBroadcastToAll(mVolumeChanged, mVolumeChangedOptions);
- if (extraStreamType != mStreamType) {
- // send multiple intents in case we merged voice call and bt sco streams
- mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
- mStreamType);
- // do not use the options in thid case which could discard
- // the previous intent
- sendBroadcastToAll(mVolumeChanged, null);
- }
}
+ return changed;
}
}
- return changed;
}
public int getIndex(int device) {
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index a5058dd..cf5fa96 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -540,9 +540,23 @@
DEFAULT_MANDATORY_BIOMETRICS_STATUS)
&& mMandatoryBiometricsRequirementsSatisfied.getOrDefault(userId,
DEFAULT_MANDATORY_BIOMETRICS_REQUIREMENTS_SATISFIED_STATUS)
- && getEnabledForApps(userId, TYPE_ANY_BIOMETRIC)
- && (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */)
- || mFaceEnrolledForUser.getOrDefault(userId, false /* default */));
+ && getBiometricStatusForIdentityCheck(userId);
+ }
+
+ private boolean getBiometricStatusForIdentityCheck(int userId) {
+ if (com.android.settings.flags.Flags.biometricsOnboardingEducation()) {
+ if (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */)
+ && getEnabledForApps(userId, TYPE_FINGERPRINT)) {
+ return true;
+ } else {
+ return mFaceEnrolledForUser.getOrDefault(userId, false /* default */)
+ && getEnabledForApps(userId, TYPE_FACE);
+ }
+ } else {
+ return (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */)
+ || mFaceEnrolledForUser.getOrDefault(userId, false /* default */))
+ && getEnabledForApps(userId, TYPE_ANY_BIOMETRIC);
+ }
}
void notifyEnabledOnKeyguardCallbacks(int userId, int modality) {
diff --git a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
index d412277..f5284a3 100644
--- a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
+++ b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
@@ -211,4 +211,20 @@
*/
public abstract @NonNull VirtualDeviceManager.VirtualDevice createVirtualDevice(
@NonNull VirtualDeviceParams params);
+
+ /**
+ * Returns the details of the virtual device with the given ID, if any.
+ *
+ * <p>The returned object is a read-only representation of the virtual device that expose its
+ * properties.</p>
+ *
+ * <p>Note that if the virtual device is closed and becomes invalid, the returned object will
+ * not be updated and may contain stale values. Use a {@link VirtualDeviceListener} for real
+ * time updates of the availability of virtual devices.</p>
+ *
+ * @return the virtual device with the requested ID, or {@code null} if no such device exists or
+ * it has already been closed.
+ */
+ @Nullable
+ public abstract VirtualDevice getVirtualDevice(int deviceId);
}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index c393e92..79af6ed 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -24,6 +24,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SpecialUsers.CanBeALL;
+import android.annotation.SpecialUsers.CanBeCURRENT;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManager.RestrictionLevel;
@@ -361,7 +363,8 @@
*/
@Override
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
- IContentObserver observer, int userHandle, int targetSdkVersion) {
+ IContentObserver observer, @CanBeALL @CanBeCURRENT @UserIdInt int userHandle,
+ int targetSdkVersion) {
if (observer == null || uri == null) {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
@@ -1398,8 +1401,8 @@
}
}
- private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, boolean allowNonFull,
- int userId) {
+ private @CanBeALL @UserIdInt int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags,
+ boolean allowNonFull, @CanBeALL @CanBeCURRENT @UserIdInt int userId) {
if (userId == UserHandle.USER_CURRENT) {
userId = ActivityManager.getCurrentUser();
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 88f5c81..c41b8db 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -333,7 +333,7 @@
int ambientLightHorizonLong, float userLux, float userNits,
DisplayManagerFlags displayManagerFlags) {
mInjector = injector;
- mClock = injector.createClock(displayManagerFlags.offloadControlsDozeAutoBrightness());
+ mClock = injector.createClock();
mContext = context;
mCallbacks = callbacks;
mSensorManager = sensorManager;
@@ -1402,8 +1402,7 @@
public void onSensorChanged(SensorEvent event) {
if (mLightSensorEnabled) {
// The time received from the sensor is in nano seconds, hence changing it to ms
- final long time = (mDisplayManagerFlags.offloadControlsDozeAutoBrightness())
- ? TimeUnit.NANOSECONDS.toMillis(event.timestamp) : mClock.uptimeMillis();
+ final long time = TimeUnit.NANOSECONDS.toMillis(event.timestamp);
final float lux = event.values[0];
handleLightSensorEvent(time, lux);
}
@@ -1616,20 +1615,13 @@
}
private static class RealClock implements Clock {
- private final boolean mOffloadControlsDozeBrightness;
-
- RealClock(boolean offloadControlsDozeBrightness) {
- mOffloadControlsDozeBrightness = offloadControlsDozeBrightness;
- }
-
@Override
public long uptimeMillis() {
return SystemClock.uptimeMillis();
}
public long getSensorEventScaleTime() {
- return (mOffloadControlsDozeBrightness)
- ? SystemClock.elapsedRealtime() : uptimeMillis();
+ return SystemClock.elapsedRealtime();
}
}
@@ -1638,8 +1630,8 @@
return BackgroundThread.getHandler();
}
- Clock createClock(boolean offloadControlsDozeBrightness) {
- return new RealClock(offloadControlsDozeBrightness);
+ Clock createClock() {
+ return new RealClock();
}
}
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 872f334..f4daf87 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -890,10 +890,12 @@
// still need to let WindowManager know so it can update its own internal state for
// things like display cutouts.
display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo);
- if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) {
- logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_BASIC_CHANGED
- | LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED;
+ if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo,
+ /* compareOnlyBasicChanges */ true)) {
+ logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_BASIC_CHANGED;
}
+ logicalDisplayEventMask
+ |= updateAndGetMaskForDisplayPropertyChanges(mTempNonOverrideDisplayInfo);
}
mLogicalDisplaysToUpdate.put(displayId, logicalDisplayEventMask);
mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_UPDATED);
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
index 2c6f374..6510441 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -291,8 +291,7 @@
void setAllowAutoBrightnessWhileDozing(
DisplayManagerInternal.DisplayOffloadSession displayOffloadSession) {
mAllowAutoBrightnessWhileDozing = mAllowAutoBrightnessWhileDozingConfig;
- if (mDisplayManagerFlags.offloadControlsDozeAutoBrightness()
- && mDisplayManagerFlags.isDisplayOffloadEnabled()
+ if (mDisplayManagerFlags.isDisplayOffloadEnabled()
&& displayOffloadSession != null) {
mAllowAutoBrightnessWhileDozing &= displayOffloadSession.allowAutoBrightnessInDoze();
}
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index e4b595a..7cc178d 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -156,11 +156,6 @@
Flags.FLAG_DOZE_BRIGHTNESS_FLOAT,
Flags::dozeBrightnessFloat);
- private final FlagState mOffloadControlsDozeAutoBrightness = new FlagState(
- Flags.FLAG_OFFLOAD_CONTROLS_DOZE_AUTO_BRIGHTNESS,
- Flags::offloadControlsDozeAutoBrightness
- );
-
private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState(
Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT,
Flags::enablePeakRefreshRatePhysicalLimit
@@ -285,6 +280,11 @@
Flags::committedStateSeparateEvent
);
+ private final FlagState mDelayImplicitRrRegistrationUntilRrAccessed = new FlagState(
+ Flags.FLAG_DELAY_IMPLICIT_RR_REGISTRATION_UNTIL_RR_ACCESSED,
+ Flags::delayImplicitRrRegistrationUntilRrAccessed
+ );
+
/**
* @return {@code true} if 'port' is allowed in display layout configuration file.
*/
@@ -440,13 +440,6 @@
return mDozeBrightnessFloat.isEnabled();
}
- /**
- * @return Whether DisplayOffload should control auto-brightness in doze
- */
- public boolean offloadControlsDozeAutoBrightness() {
- return mOffloadControlsDozeAutoBrightness.isEnabled();
- }
-
public boolean isPeakRefreshRatePhysicalLimitEnabled() {
return mPeakRefreshRatePhysicalLimit.isEnabled();
}
@@ -598,7 +591,6 @@
return mFramerateOverrideTriggersRrCallbacks.isEnabled();
}
-
/**
* @return {@code true} if the flag for sending refresh rate events only for the apps in
* foreground is enabled
@@ -616,6 +608,13 @@
}
/**
+ * @return {@code true} if the flag for only explicit subscription for RR changes is enabled
+ */
+ public boolean isDelayImplicitRrRegistrationUntilRrAccessedEnabled() {
+ return mDelayImplicitRrRegistrationUntilRrAccessed.isEnabled();
+ }
+
+ /**
* dumps all flagstates
* @param pw printWriter
*/
@@ -647,7 +646,6 @@
pw.println(" " + mResolutionBackupRestore);
pw.println(" " + mUseFusionProxSensor);
pw.println(" " + mDozeBrightnessFloat);
- pw.println(" " + mOffloadControlsDozeAutoBrightness);
pw.println(" " + mPeakRefreshRatePhysicalLimit);
pw.println(" " + mIgnoreAppPreferredRefreshRate);
pw.println(" " + mSynthetic60hzModes);
@@ -673,6 +671,7 @@
pw.println(" " + mFramerateOverrideTriggersRrCallbacks);
pw.println(" " + mRefreshRateEventForForegroundApps);
pw.println(" " + mCommittedStateSeparateEvent);
+ pw.println(" " + mDelayImplicitRrRegistrationUntilRrAccessed);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index acdc0e0..a0064a9 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -255,17 +255,6 @@
}
flag {
- name: "offload_controls_doze_auto_brightness"
- namespace: "display_manager"
- description: "Allows the registered DisplayOffloader to control if auto-brightness is used in doze"
- bug: "327392714"
- is_fixed_read_only: true
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "enable_peak_refresh_rate_physical_limit"
namespace: "display_manager"
description: "Flag for adding physical refresh rate limit if smooth display setting is on "
@@ -485,9 +474,9 @@
description: "Feature flag to trigger the RR callbacks when framerate overridding happens."
bug: "390113266"
is_fixed_read_only: true
- metadata {
- purpose: PURPOSE_BUGFIX
- }
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
@@ -519,3 +508,14 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "delay_implicit_rr_registration_until_rr_accessed"
+ namespace: "display_manager"
+ description: "Feature flag for clients to subscribe to RR changes by either explicitly subscribing for refresh rate changes or request for refresh rate data"
+ bug: "391828526"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 7e8bb28..2af74f6 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -569,7 +569,8 @@
}
private void requestDreamInternal() {
- if (isDreamingInternal() && !dreamIsFrontmost() && mController.bringDreamToFront()) {
+ if (isDreamingInternal() && !dreamIsFrontmost() && mController.bringDreamToFront()
+ && !isDozingInternal()) {
return;
}
diff --git a/services/core/java/com/android/server/input/InputGestureManager.java b/services/core/java/com/android/server/input/InputGestureManager.java
index 977c029..d71c8a1 100644
--- a/services/core/java/com/android/server/input/InputGestureManager.java
+++ b/services/core/java/com/android/server/input/InputGestureManager.java
@@ -146,11 +146,6 @@
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL
),
createKeyGesture(
- KeyEvent.KEYCODE_N,
- KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON,
- KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES
- ),
- createKeyGesture(
KeyEvent.KEYCODE_S,
KeyEvent.META_META_ON,
KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 0e37238..c2fecf2 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -143,6 +143,7 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.DisplayThread;
+import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
@@ -469,11 +470,13 @@
static class Injector {
private final Context mContext;
private final Looper mLooper;
+ private final Looper mIoLooper;
private final UEventManager mUEventManager;
- Injector(Context context, Looper looper, UEventManager uEventManager) {
+ Injector(Context context, Looper looper, Looper ioLooper, UEventManager uEventManager) {
mContext = context;
mLooper = looper;
+ mIoLooper = ioLooper;
mUEventManager = uEventManager;
}
@@ -485,6 +488,10 @@
return mLooper;
}
+ Looper getIoLooper() {
+ return mIoLooper;
+ }
+
UEventManager getUEventManager() {
return mUEventManager;
}
@@ -505,8 +512,8 @@
}
public InputManagerService(Context context) {
- this(new Injector(context, DisplayThread.get().getLooper(), new UEventManager() {}),
- context.getSystemService(PermissionEnforcer.class));
+ this(new Injector(context, DisplayThread.get().getLooper(), IoThread.get().getLooper(),
+ new UEventManager() {}), context.getSystemService(PermissionEnforcer.class));
}
@VisibleForTesting
@@ -532,7 +539,7 @@
mStickyModifierStateController = new StickyModifierStateController();
mInputDataStore = new InputDataStore();
mKeyGestureController = new KeyGestureController(mContext, injector.getLooper(),
- mInputDataStore);
+ injector.getIoLooper(), mInputDataStore);
mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(),
mNative);
mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java
index 5770a09..fba0b04 100644
--- a/services/core/java/com/android/server/input/KeyGestureController.java
+++ b/services/core/java/com/android/server/input/KeyGestureController.java
@@ -121,6 +121,7 @@
private final Context mContext;
private final Handler mHandler;
+ private final Handler mIoHandler;
private final int mSystemPid;
private final KeyCombinationManager mKeyCombinationManager;
private final SettingsObserver mSettingsObserver;
@@ -171,9 +172,11 @@
private final boolean mVisibleBackgroundUsersEnabled = isVisibleBackgroundUsersEnabled();
- KeyGestureController(Context context, Looper looper, InputDataStore inputDataStore) {
+ KeyGestureController(Context context, Looper looper, Looper ioLooper,
+ InputDataStore inputDataStore) {
mContext = context;
mHandler = new Handler(looper, this::handleMessage);
+ mIoHandler = new Handler(ioLooper, this::handleIoMessage);
mSystemPid = Process.myPid();
mKeyGestureHandlerRecords = new TreeMap<>((p1, p2) -> {
if (Objects.equals(p1, p2)) {
@@ -458,7 +461,7 @@
userId = mCurrentUserId;
}
// Load the system user's input gestures.
- mHandler.obtainMessage(MSG_LOAD_CUSTOM_GESTURES, userId).sendToTarget();
+ mIoHandler.obtainMessage(MSG_LOAD_CUSTOM_GESTURES, userId).sendToTarget();
}
public boolean interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
@@ -1032,7 +1035,7 @@
synchronized (mUserLock) {
mCurrentUserId = userId;
}
- mHandler.obtainMessage(MSG_LOAD_CUSTOM_GESTURES, userId).sendToTarget();
+ mIoHandler.obtainMessage(MSG_LOAD_CUSTOM_GESTURES, userId).sendToTarget();
}
@MainThread
@@ -1073,6 +1076,12 @@
AidlKeyGestureEvent event = (AidlKeyGestureEvent) msg.obj;
notifyKeyGestureEvent(event);
break;
+ }
+ return true;
+ }
+
+ private boolean handleIoMessage(Message msg) {
+ switch (msg.what) {
case MSG_PERSIST_CUSTOM_GESTURES: {
final int userId = (Integer) msg.obj;
persistInputGestures(userId);
@@ -1083,7 +1092,6 @@
loadInputGestures(userId);
break;
}
-
}
return true;
}
@@ -1144,7 +1152,7 @@
final int result = mInputGestureManager.addCustomInputGesture(userId,
new InputGestureData(inputGestureData));
if (result == InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS) {
- mHandler.obtainMessage(MSG_PERSIST_CUSTOM_GESTURES, userId).sendToTarget();
+ mIoHandler.obtainMessage(MSG_PERSIST_CUSTOM_GESTURES, userId).sendToTarget();
}
return result;
}
@@ -1156,7 +1164,7 @@
final int result = mInputGestureManager.removeCustomInputGesture(userId,
new InputGestureData(inputGestureData));
if (result == InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS) {
- mHandler.obtainMessage(MSG_PERSIST_CUSTOM_GESTURES, userId).sendToTarget();
+ mIoHandler.obtainMessage(MSG_PERSIST_CUSTOM_GESTURES, userId).sendToTarget();
}
return result;
}
@@ -1165,7 +1173,7 @@
public void removeAllCustomInputGestures(@UserIdInt int userId,
@Nullable InputGestureData.Filter filter) {
mInputGestureManager.removeAllCustomInputGestures(userId, filter);
- mHandler.obtainMessage(MSG_PERSIST_CUSTOM_GESTURES, userId).sendToTarget();
+ mIoHandler.obtainMessage(MSG_PERSIST_CUSTOM_GESTURES, userId).sendToTarget();
}
@BinderThread
diff --git a/services/core/java/com/android/server/inputmethod/ClientController.java b/services/core/java/com/android/server/inputmethod/ClientController.java
index 0381a31..d03c086 100644
--- a/services/core/java/com/android/server/inputmethod/ClientController.java
+++ b/services/core/java/com/android/server/inputmethod/ClientController.java
@@ -43,21 +43,23 @@
@GuardedBy("ImfLock.class")
private final List<ClientControllerCallback> mCallbacks = new ArrayList<>();
+ @NonNull
private final PackageManagerInternal mPackageManagerInternal;
interface ClientControllerCallback {
- void onClientRemoved(ClientState client);
+ void onClientRemoved(@NonNull ClientState client);
}
- ClientController(PackageManagerInternal packageManagerInternal) {
+ ClientController(@NonNull PackageManagerInternal packageManagerInternal) {
mPackageManagerInternal = packageManagerInternal;
}
@GuardedBy("ImfLock.class")
- ClientState addClient(IInputMethodClientInvoker clientInvoker,
- IRemoteInputConnection inputConnection, int selfReportedDisplayId, int callerUid,
- int callerPid) {
+ @NonNull
+ ClientState addClient(@NonNull IInputMethodClientInvoker clientInvoker,
+ @NonNull IRemoteInputConnection fallbackInputConnection, int selfReportedDisplayId,
+ int callerUid, int callerPid) {
final IBinder.DeathRecipient deathRecipient = () -> {
// Exceptionally holding ImfLock here since this is a internal lambda expression.
synchronized (ImfLock.class) {
@@ -90,15 +92,15 @@
// have the client crash. Thus we do not verify the display ID at all here. Instead we
// later check the display ID every time the client needs to interact with the specified
// display.
- final ClientState cs = new ClientState(clientInvoker, inputConnection,
- callerUid, callerPid, selfReportedDisplayId, deathRecipient);
+ final var cs = new ClientState(clientInvoker, fallbackInputConnection, callerUid, callerPid,
+ selfReportedDisplayId, deathRecipient);
mClients.put(clientInvoker.asBinder(), cs);
return cs;
}
@VisibleForTesting
@GuardedBy("ImfLock.class")
- boolean removeClient(IInputMethodClient client) {
+ boolean removeClient(@NonNull IInputMethodClient client) {
return removeClientAsBinder(client.asBinder());
}
@@ -116,7 +118,7 @@
}
@GuardedBy("ImfLock.class")
- void addClientControllerCallback(ClientControllerCallback callback) {
+ void addClientControllerCallback(@NonNull ClientControllerCallback callback) {
mCallbacks.add(callback);
}
@@ -127,15 +129,15 @@
}
@GuardedBy("ImfLock.class")
- void forAllClients(Consumer<ClientState> consumer) {
+ void forAllClients(@NonNull Consumer<ClientState> consumer) {
for (int i = 0; i < mClients.size(); i++) {
consumer.accept(mClients.valueAt(i));
}
}
@GuardedBy("ImfLock.class")
- boolean verifyClientAndPackageMatch(
- @NonNull IInputMethodClient client, @NonNull String packageName) {
+ boolean verifyClientAndPackageMatch(@NonNull IInputMethodClient client,
+ @NonNull String packageName) {
final ClientState cs = mClients.get(client.asBinder());
if (cs == null) {
throw new IllegalArgumentException("unknown client " + client.asBinder());
diff --git a/services/core/java/com/android/server/inputmethod/ClientState.java b/services/core/java/com/android/server/inputmethod/ClientState.java
index e98a5a7..ea80995 100644
--- a/services/core/java/com/android/server/inputmethod/ClientState.java
+++ b/services/core/java/com/android/server/inputmethod/ClientState.java
@@ -16,6 +16,8 @@
package com.android.server.inputmethod;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.IBinder;
import android.util.SparseArray;
import android.view.inputmethod.InputBinding;
@@ -24,12 +26,17 @@
import com.android.internal.inputmethod.IRemoteInputConnection;
final class ClientState {
+
+ @NonNull
final IInputMethodClientInvoker mClient;
+ @NonNull
final IRemoteInputConnection mFallbackInputConnection;
final int mUid;
final int mPid;
final int mSelfReportedDisplayId;
+ @NonNull
final InputBinding mBinding;
+ @NonNull
final IBinder.DeathRecipient mClientDeathRecipient;
@GuardedBy("ImfLock.class")
@@ -39,30 +46,31 @@
boolean mSessionRequestedForAccessibility;
@GuardedBy("ImfLock.class")
+ @Nullable
InputMethodManagerService.SessionState mCurSession;
@GuardedBy("ImfLock.class")
- SparseArray<InputMethodManagerService.AccessibilitySessionState> mAccessibilitySessions =
+ @NonNull
+ final SparseArray<InputMethodManagerService.AccessibilitySessionState> mAccessibilitySessions =
new SparseArray<>();
- @Override
- public String toString() {
- return "ClientState{" + Integer.toHexString(
- System.identityHashCode(this)) + " mUid=" + mUid
- + " mPid=" + mPid + " mSelfReportedDisplayId=" + mSelfReportedDisplayId + "}";
- }
-
- ClientState(IInputMethodClientInvoker client,
- IRemoteInputConnection fallbackInputConnection,
- int uid, int pid, int selfReportedDisplayId,
- IBinder.DeathRecipient clientDeathRecipient) {
+ ClientState(@NonNull IInputMethodClientInvoker client,
+ @NonNull IRemoteInputConnection fallbackInputConnection, int uid, int pid,
+ int selfReportedDisplayId, @NonNull IBinder.DeathRecipient clientDeathRecipient) {
mClient = client;
mFallbackInputConnection = fallbackInputConnection;
mUid = uid;
mPid = pid;
mSelfReportedDisplayId = selfReportedDisplayId;
- mBinding = new InputBinding(null /*conn*/, mFallbackInputConnection.asBinder(), mUid,
+ mBinding = new InputBinding(null /* conn */, fallbackInputConnection.asBinder(), mUid,
mPid);
mClientDeathRecipient = clientDeathRecipient;
}
+
+ @Override
+ public String toString() {
+ return "ClientState{" + Integer.toHexString(System.identityHashCode(this))
+ + " mUid=" + mUid + " mPid=" + mPid
+ + " mSelfReportedDisplayId=" + mSelfReportedDisplayId + "}";
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java
index 650ea60..9d88983 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodClientInvoker.java
@@ -58,23 +58,17 @@
private final Handler mHandler;
@AnyThread
- @Nullable
- static IInputMethodClientInvoker create(@Nullable IInputMethodClient inputMethodClient,
+ @NonNull
+ static IInputMethodClientInvoker create(@NonNull IInputMethodClient inputMethodClient,
@NonNull Handler handler) {
- if (inputMethodClient == null) {
- return null;
- }
final boolean isProxy = Binder.isProxy(inputMethodClient);
return new IInputMethodClientInvoker(inputMethodClient, isProxy, isProxy ? null : handler);
}
@AnyThread
- @Nullable
- static IInputMethodClientInvoker create$ravenwood(
- @Nullable IInputMethodClient inputMethodClient, @NonNull Handler handler) {
- if (inputMethodClient == null) {
- return null;
- }
+ @NonNull
+ static IInputMethodClientInvoker create$ravenwood(@NonNull IInputMethodClient inputMethodClient,
+ @NonNull Handler handler) {
return new IInputMethodClientInvoker(inputMethodClient, true, null);
}
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
index a8b61af..02987a9 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
@@ -89,8 +89,8 @@
@BinderThread
interface Callback {
- void addClient(IInputMethodClient client, IRemoteInputConnection inputConnection,
- int selfReportedDisplayId);
+ void addClient(@NonNull IInputMethodClient client,
+ @NonNull IRemoteInputConnection inputConnection, int selfReportedDisplayId);
InputMethodInfo getCurrentInputMethodInfoAsUser(@UserIdInt int userId);
@@ -242,9 +242,9 @@
}
@Override
- public void addClient(IInputMethodClient client, IRemoteInputConnection inputmethod,
- int untrustedDisplayId) {
- mCallback.addClient(client, inputmethod, untrustedDisplayId);
+ public void addClient(@NonNull IInputMethodClient client,
+ @NonNull IRemoteInputConnection fallbackInputConnection, int untrustedDisplayId) {
+ mCallback.addClient(client, fallbackInputConnection, untrustedDisplayId);
}
@Override
@@ -414,7 +414,7 @@
}
@Override
- public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
+ public void reportPerceptibleAsync(@NonNull IBinder windowToken, boolean perceptible) {
mCallback.reportPerceptibleAsync(windowToken, perceptible);
}
diff --git a/services/core/java/com/android/server/inputmethod/ImeBindingState.java b/services/core/java/com/android/server/inputmethod/ImeBindingState.java
index 5deed39..adfd991 100644
--- a/services/core/java/com/android/server/inputmethod/ImeBindingState.java
+++ b/services/core/java/com/android/server/inputmethod/ImeBindingState.java
@@ -43,9 +43,9 @@
final int mUserId;
/**
- * The last window token that we confirmed to be focused. This is always updated upon
- * reports from the input method client. If the window state is already changed before the
- * report is handled, this field just keeps the last value.
+ * The last window token that we confirmed to be focused. This is always updated upon reports
+ * from the input method client. If the window state is already changed before the report is
+ * handled, this field just keeps the last value.
*/
@Nullable
final IBinder mFocusedWindow;
@@ -59,11 +59,9 @@
final int mFocusedWindowSoftInputMode;
/**
- * The client by which {@link #mFocusedWindow} was reported. This gets updated whenever
- * an
- * IME-focusable window gained focus (without necessarily starting an input connection),
- * while {@link InputMethodManagerService#mClient} only gets updated when we actually start an
- * input connection.
+ * The client by which {@link #mFocusedWindow} was reported. This gets updated whenever an
+ * IME-focusable window gained focus (without necessarily starting an input connection), while
+ * {@link UserData#mCurClient} only gets updated when we actually start an input connection.
*
* @see #mFocusedWindow
*/
@@ -72,15 +70,16 @@
/**
* The editor info by which {@link #mFocusedWindow} was reported. This differs from
- * {@link InputMethodManagerService#mCurEditorInfo} the same way {@link #mFocusedWindowClient}
- * differs from {@link InputMethodManagerService#mCurClient}.
+ * {@link UserData#mCurEditorInfo} the same way {@link #mFocusedWindowClient} differs from
+ * {@link UserData#mCurClient}.
*
* @see #mFocusedWindow
*/
@Nullable
final EditorInfo mFocusedWindowEditorInfo;
- void dumpDebug(ProtoOutputStream proto, WindowManagerInternal windowManagerInternal) {
+ void dumpDebug(@NonNull ProtoOutputStream proto,
+ @NonNull WindowManagerInternal windowManagerInternal) {
proto.write(CUR_FOCUSED_WINDOW_NAME,
windowManagerInternal.getWindowName(mFocusedWindow));
proto.write(CUR_FOCUSED_WINDOW_SOFT_INPUT_MODE,
@@ -94,18 +93,14 @@
p.println(prefix + "mFocusedWindowClient=" + mFocusedWindowClient);
}
+ @NonNull
static ImeBindingState newEmptyState() {
- return new ImeBindingState(
- /*userId=*/ UserHandle.USER_NULL,
- /*focusedWindow=*/ null,
- /*focusedWindowSoftInputMode=*/ SOFT_INPUT_STATE_UNSPECIFIED,
- /*focusedWindowClient=*/ null,
- /*focusedWindowEditorInfo=*/ null
- );
+ return new ImeBindingState(UserHandle.USER_NULL /* userId */, null /* focusedWindow */,
+ SOFT_INPUT_STATE_UNSPECIFIED /* focusedWindowSoftInputMode */,
+ null /* focusedWindowClient */, null /* focusedWindowEditorInfo */);
}
- ImeBindingState(@UserIdInt int userId,
- @Nullable IBinder focusedWindow,
+ ImeBindingState(@UserIdInt int userId, @Nullable IBinder focusedWindow,
@SoftInputModeFlags int focusedWindowSoftInputMode,
@Nullable ClientState focusedWindowClient,
@Nullable EditorInfo focusedWindowEditorInfo) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 508bc2f..395d85e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -482,10 +482,15 @@
};
static class SessionState {
+
+ @NonNull
final ClientState mClient;
+ @NonNull
final IInputMethodInvoker mMethod;
+ @Nullable
IInputMethodSession mSession;
+ @Nullable
InputChannel mChannel;
@UserIdInt
@@ -496,14 +501,13 @@
return "SessionState{uid=" + mClient.mUid + " pid=" + mClient.mPid
+ " method=" + Integer.toHexString(
IInputMethodInvoker.getBinderIdentityHashCode(mMethod))
- + " session=" + Integer.toHexString(
- System.identityHashCode(mSession))
+ + " session=" + Integer.toHexString(System.identityHashCode(mSession))
+ " channel=" + mChannel
+ " userId=" + mUserId
+ "}";
}
- SessionState(ClientState client, IInputMethodInvoker method,
+ SessionState(@NonNull ClientState client, @NonNull IInputMethodInvoker method,
IInputMethodSession session, InputChannel channel, @UserIdInt int userId) {
mClient = client;
mMethod = method;
@@ -517,22 +521,24 @@
* Record session state for an accessibility service.
*/
static class AccessibilitySessionState {
+
+ @NonNull
final ClientState mClient;
// Id of the accessibility service.
final int mId;
- public IAccessibilityInputMethodSession mSession;
+ @Nullable
+ IAccessibilityInputMethodSession mSession;
@Override
public String toString() {
return "AccessibilitySessionState{uid=" + mClient.mUid + " pid=" + mClient.mPid
+ " id=" + Integer.toHexString(mId)
- + " session=" + Integer.toHexString(
- System.identityHashCode(mSession))
+ + " session=" + Integer.toHexString(System.identityHashCode(mSession))
+ "}";
}
- AccessibilitySessionState(ClientState client, int id,
+ AccessibilitySessionState(@NonNull ClientState client, int id,
IAccessibilityInputMethodSession session) {
mClient = client;
mId = id;
@@ -544,6 +550,7 @@
* Manages the IME clients.
*/
@SharedByAllUsersField
+ @NonNull
private final ClientController mClientController;
/**
@@ -1770,19 +1777,21 @@
* <p>As a general principle, IPCs from the application process that take
* {@link IInputMethodClient} will be rejected without this step.</p>
*
- * @param client {@link android.os.Binder} proxy that is associated with the
- * singleton instance of
- * {@link android.view.inputmethod.InputMethodManager} that runs
- * on the client process
- * @param inputConnection communication channel for the fallback {@link InputConnection}
- * @param selfReportedDisplayId self-reported display ID to which the client is associated.
- * Whether the client is still allowed to access to this display
- * or not needs to be evaluated every time the client interacts
- * with the display
+ * @param client {@link android.os.Binder} proxy that is associated with the
+ * singleton instance of
+ * {@link android.view.inputmethod.InputMethodManager} that runs
+ * on the client process
+ * @param fallbackInputConnection communication channel for the fallback {@link InputConnection}
+ * @param selfReportedDisplayId self-reported display ID to which the client is associated.
+ * Whether the client is still allowed to access to this display
+ * or not needs to be evaluated every time the client interacts
+ * with the display
*/
@Override
- public void addClient(IInputMethodClient client, IRemoteInputConnection inputConnection,
- int selfReportedDisplayId) {
+ public void addClient(@NonNull IInputMethodClient client,
+ @NonNull IRemoteInputConnection fallbackInputConnection, int selfReportedDisplayId) {
+ Objects.requireNonNull(client, "client must not be null");
+ Objects.requireNonNull(fallbackInputConnection, "fallbackInputConnection must not be null");
// Here there are two scenarios where this method is called:
// A. IMM is being instantiated in a different process and this is an IPC from that process
// B. IMM is being instantiated in the same process but Binder.clearCallingIdentity() is
@@ -1791,16 +1800,15 @@
// actually running.
final int callerUid = Binder.getCallingUid();
final int callerPid = Binder.getCallingPid();
- final IInputMethodClientInvoker clientInvoker =
- IInputMethodClientInvoker.create(client, mHandler);
+ final var clientInvoker = IInputMethodClientInvoker.create(client, mHandler);
synchronized (ImfLock.class) {
- mClientController.addClient(clientInvoker, inputConnection, selfReportedDisplayId,
- callerUid, callerPid);
+ mClientController.addClient(clientInvoker, fallbackInputConnection,
+ selfReportedDisplayId, callerUid, callerPid);
}
}
@GuardedBy("ImfLock.class")
- private void onClientRemoved(ClientState client) {
+ private void onClientRemoved(@NonNull ClientState client) {
clearClientSessionLocked(client);
clearClientSessionForAccessibilityLocked(client);
// TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
@@ -1814,7 +1822,8 @@
*/
// TODO(b/325515685): Move this method to InputMethodBindingController
@GuardedBy("ImfLock.class")
- private void onClientRemovedInternalLocked(ClientState client, @NonNull UserData userData) {
+ private void onClientRemovedInternalLocked(@NonNull ClientState client,
+ @NonNull UserData userData) {
final int userId = userData.mUserId;
if (userData.mCurClient == client) {
hideCurrentInputLocked(userData.mImeBindingState.mFocusedWindow, 0 /* flags */,
@@ -1962,7 +1971,7 @@
session.mMethod.startInput(startInputToken, userData.mCurInputConnection,
userData.mCurEditorInfo, restarting, navButtonFlags, userData.mCurImeDispatcher);
if (Flags.refactorInsetsController()) {
- if (isShowRequestedForCurrentWindow(userId) && userData.mImeBindingState != null
+ if (isShowRequestedForCurrentWindow(userId)
&& userData.mImeBindingState.mFocusedWindow != null) {
// Re-use current statsToken, if it exists.
final var statsToken = userData.mCurStatsToken != null ? userData.mCurStatsToken
@@ -2028,15 +2037,14 @@
}
}
+ @NonNull
private SparseArray<IAccessibilityInputMethodSession> createAccessibilityInputMethodSessions(
- SparseArray<AccessibilitySessionState> accessibilitySessions) {
- final SparseArray<IAccessibilityInputMethodSession> accessibilityInputMethodSessions =
- new SparseArray<>();
- if (accessibilitySessions != null) {
- for (int i = 0; i < accessibilitySessions.size(); i++) {
- accessibilityInputMethodSessions.append(accessibilitySessions.keyAt(i),
- accessibilitySessions.valueAt(i).mSession);
- }
+ @NonNull SparseArray<AccessibilitySessionState> accessibilitySessions) {
+ final var accessibilityInputMethodSessions =
+ new SparseArray<IAccessibilityInputMethodSession>();
+ for (int i = 0; i < accessibilitySessions.size(); i++) {
+ accessibilityInputMethodSessions.append(accessibilitySessions.keyAt(i),
+ accessibilitySessions.valueAt(i).mSession);
}
return accessibilityInputMethodSessions;
}
@@ -2547,14 +2555,14 @@
}
@GuardedBy("ImfLock.class")
- void clearClientSessionLocked(ClientState cs) {
+ void clearClientSessionLocked(@NonNull ClientState cs) {
finishSessionLocked(cs.mCurSession);
cs.mCurSession = null;
cs.mSessionRequested = false;
}
@GuardedBy("ImfLock.class")
- void clearClientSessionForAccessibilityLocked(ClientState cs) {
+ void clearClientSessionForAccessibilityLocked(@NonNull ClientState cs) {
for (int i = 0; i < cs.mAccessibilitySessions.size(); i++) {
finishSessionForAccessibilityLocked(cs.mAccessibilitySessions.valueAt(i));
}
@@ -2563,7 +2571,7 @@
}
@GuardedBy("ImfLock.class")
- void clearClientSessionForAccessibilityLocked(ClientState cs, int id) {
+ void clearClientSessionForAccessibilityLocked(@NonNull ClientState cs, int id) {
AccessibilitySessionState session = cs.mAccessibilitySessions.get(id);
if (session != null) {
finishSessionForAccessibilityLocked(session);
@@ -2572,7 +2580,7 @@
}
@GuardedBy("ImfLock.class")
- private void finishSessionLocked(SessionState sessionState) {
+ private void finishSessionLocked(@Nullable SessionState sessionState) {
if (sessionState != null) {
if (sessionState.mSession != null) {
try {
@@ -2885,8 +2893,7 @@
ProtoLog.v(IMMS_DEBUG, "IME window vis: %s active: %s visible: %s displayId: %s", vis,
(vis & InputMethodService.IME_ACTIVE), (vis & InputMethodService.IME_VISIBLE),
curTokenDisplayId);
- final IBinder focusedWindowToken = userData.mImeBindingState != null
- ? userData.mImeBindingState.mFocusedWindow : null;
+ final IBinder focusedWindowToken = userData.mImeBindingState.mFocusedWindow;
final Boolean windowPerceptible = focusedWindowToken != null
? mFocusedWindowPerceptible.get(focusedWindowToken) : null;
@@ -3474,7 +3481,7 @@
@BinderThread
@Override
- public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
+ public void reportPerceptibleAsync(@NonNull IBinder windowToken, boolean perceptible) {
Binder.withCleanCallingIdentity(() -> {
Objects.requireNonNull(windowToken, "windowToken must not be null");
synchronized (ImfLock.class) {
@@ -3485,7 +3492,7 @@
|| (windowPerceptible != null && windowPerceptible == perceptible)) {
return;
}
- mFocusedWindowPerceptible.put(windowToken, windowPerceptible);
+ mFocusedWindowPerceptible.put(windowToken, perceptible);
updateSystemUiLocked(userId);
}
});
@@ -4868,7 +4875,7 @@
@GuardedBy("ImfLock.class")
void setEnabledSessionForAccessibilityLocked(
- SparseArray<AccessibilitySessionState> accessibilitySessions,
+ @NonNull SparseArray<AccessibilitySessionState> accessibilitySessions,
@NonNull UserData userData) {
// mEnabledAccessibilitySessions could the same object as accessibilitySessions.
SparseArray<IAccessibilityInputMethodSession> disabledSessions = new SparseArray<>();
@@ -5156,7 +5163,7 @@
interactive ? bindingController.getImeWindowVis() : 0,
bindingController.getBackDisposition(), userId);
// Inform the current client of the change in active status
- if (userData.mCurClient == null || userData.mCurClient.mClient == null) {
+ if (userData.mCurClient == null) {
return;
}
if (mImePlatformCompatUtils.shouldUseSetInteractiveProtocol(
@@ -5920,9 +5927,8 @@
// from all clients.
if (bindingController.getCurMethod() != null) {
// TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
- @SuppressWarnings("GuardedBy") Consumer<ClientState> clearClientSession =
- c -> clearClientSessionForAccessibilityLocked(c,
- accessibilityConnectionId);
+ @SuppressWarnings("GuardedBy") Consumer<ClientState> clearClientSession = c ->
+ clearClientSessionForAccessibilityLocked(c, accessibilityConnectionId);
mClientController.forAllClients(clearClientSession);
AccessibilitySessionState session = userData.mEnabledAccessibilitySessions.get(
@@ -5998,7 +6004,7 @@
@BinderThread
@GuardedBy("ImfLock.class")
private void reportFullscreenModeLocked(boolean fullscreen, @NonNull UserData userData) {
- if (userData.mCurClient != null && userData.mCurClient.mClient != null) {
+ if (userData.mCurClient != null) {
userData.mInFullscreenMode = fullscreen;
userData.mCurClient.mClient.reportFullscreenMode(fullscreen);
}
@@ -6732,9 +6738,7 @@
boolean setImeVisibilityOnFocusedWindowClient(boolean visible, UserData userData,
@NonNull ImeTracker.Token statsToken) {
if (Flags.refactorInsetsController()) {
- if (userData.mImeBindingState != null
- && userData.mImeBindingState.mFocusedWindowClient != null
- && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
+ if (userData.mImeBindingState.mFocusedWindowClient != null) {
userData.mImeBindingState.mFocusedWindowClient.mClient.setImeVisibility(visible,
statsToken);
return true;
diff --git a/services/core/java/com/android/server/inputmethod/UserData.java b/services/core/java/com/android/server/inputmethod/UserData.java
index 96da17e..7377908a 100644
--- a/services/core/java/com/android/server/inputmethod/UserData.java
+++ b/services/core/java/com/android/server/inputmethod/UserData.java
@@ -140,9 +140,9 @@
InputMethodManagerService.SessionState mEnabledSession;
@GuardedBy("ImfLock.class")
- @Nullable
- SparseArray<InputMethodManagerService.AccessibilitySessionState>
- mEnabledAccessibilitySessions = new SparseArray<>();
+ @NonNull
+ SparseArray<InputMethodManagerService.AccessibilitySessionState> mEnabledAccessibilitySessions =
+ new SparseArray<>();
/**
* A per-user cache of {@link InputMethodSettings#getEnabledInputMethodsStr()}.
diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
index b863c96..7252925 100644
--- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
+++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
@@ -128,9 +128,9 @@
}
@Override
- public void addClient(IInputMethodClient client, IRemoteInputConnection inputConnection,
- int selfReportedDisplayId) {
- offload(() -> mInner.addClient(client, inputConnection, selfReportedDisplayId));
+ public void addClient(@NonNull IInputMethodClient client,
+ @NonNull IRemoteInputConnection fallbackInputConnection, int selfReportedDisplayId) {
+ offload(() -> mInner.addClient(client, fallbackInputConnection, selfReportedDisplayId));
}
@Override
@@ -331,7 +331,7 @@
}
@Override
- public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
+ public void reportPerceptibleAsync(@NonNull IBinder windowToken, boolean perceptible) {
// Already async TODO(b/293640003): ordering issues?
mInner.reportPerceptibleAsync(windowToken, perceptible);
}
@@ -468,7 +468,7 @@
IInputMethodClient client, InputBindResult res, int startInputSeq) {
synchronized (ImfLock.class) {
final ClientState cs = mInner.getClientStateLocked(client);
- if (cs != null && cs.mClient != null) {
+ if (cs != null) {
cs.mClient.onStartInputResult(res, startInputSeq);
} else {
// client is unbound.
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
index 2ea6117..940bcb4 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
@@ -16,6 +16,7 @@
package com.android.server.location.contexthub;
+import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
import android.hardware.contexthub.EndpointInfo;
@@ -64,7 +65,7 @@
* Internal interface used to invoke client callbacks.
*/
interface CallbackConsumer {
- void accept(IContextHubEndpointCallback callback) throws RemoteException;
+ void accept(@NonNull IContextHubEndpointCallback callback) throws RemoteException;
}
/** The context of the service. */
@@ -86,7 +87,7 @@
private final EndpointInfo mHalEndpointInfo;
/** The remote callback interface for this endpoint. */
- private final IContextHubEndpointCallback mContextHubEndpointCallback;
+ @NonNull private final IContextHubEndpointCallback mContextHubEndpointCallback;
/** True if this endpoint is registered with the service/HAL. */
@GuardedBy("mRegistrationLock")
@@ -158,7 +159,7 @@
IEndpointCommunication hubInterface,
ContextHubEndpointManager endpointManager,
EndpointInfo halEndpointInfo,
- IContextHubEndpointCallback callback,
+ @NonNull IContextHubEndpointCallback callback,
String packageName,
String attributionTag,
ContextHubTransactionManager transactionManager) {
@@ -374,6 +375,34 @@
}
}
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(mEndpointInfo).append(", ");
+ sb.append("package: ").append(mPackageName).append(", ");
+ synchronized (mWakeLock) {
+ sb.append("wakelock: ").append(mWakeLock);
+ }
+ synchronized (mOpenSessionLock) {
+ if (mSessionInfoMap.size() != 0) {
+ sb.append(System.lineSeparator());
+ sb.append(" sessions: ");
+ sb.append(System.lineSeparator());
+ }
+ for (int i = 0; i < mSessionInfoMap.size(); i++) {
+ int id = mSessionInfoMap.keyAt(i);
+ int count = i + 1;
+ sb.append(
+ " " + count + ". id="
+ + id
+ + ", remote:"
+ + mSessionInfoMap.get(id).getRemoteEndpointInfo());
+ sb.append(System.lineSeparator());
+ }
+ }
+ return sb.toString();
+ }
+
/**
* Registers this endpoints with the Context Hub HAL.
*
@@ -391,9 +420,7 @@
}
/* package */ void attachDeathRecipient() throws RemoteException {
- if (mContextHubEndpointCallback != null) {
- mContextHubEndpointCallback.asBinder().linkToDeath(this, 0 /* flags */);
- }
+ mContextHubEndpointCallback.asBinder().linkToDeath(this, 0 /* flags */);
}
/* package */ void onEndpointSessionOpenRequest(
@@ -636,15 +663,13 @@
* @return false if the callback threw a RemoteException
*/
private boolean invokeCallback(CallbackConsumer consumer) {
- if (mContextHubEndpointCallback != null) {
- acquireWakeLock();
- try {
- consumer.accept(mContextHubEndpointCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException while calling endpoint callback", e);
- releaseWakeLock();
- return false;
- }
+ acquireWakeLock();
+ try {
+ consumer.accept(mContextHubEndpointCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException while calling endpoint callback", e);
+ releaseWakeLock();
+ return false;
}
return true;
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java
index 06aeb62..8ab581e 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java
@@ -16,6 +16,8 @@
package com.android.server.location.contexthub;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.content.Context;
import android.hardware.contexthub.ContextHubInfo;
import android.hardware.contexthub.EndpointInfo;
@@ -34,8 +36,11 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -105,6 +110,48 @@
/** The interface for endpoint communication (retrieved from HAL in init()) */
private IEndpointCommunication mHubInterface = null;
+ /*
+ * The list of previous registration records.
+ */
+ private static final int NUM_CLIENT_RECORDS = 20;
+ private final ConcurrentLinkedEvictingDeque<RegistrationRecord> mRegistrationRecordDeque =
+ new ConcurrentLinkedEvictingDeque<>(NUM_CLIENT_RECORDS);
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = {"ACTION_"},
+ value = {
+ ACTION_REGISTERED,
+ ACTION_UNREGISTERED,
+ })
+ public @interface Action {}
+
+ public static final int ACTION_REGISTERED = 0;
+ public static final int ACTION_UNREGISTERED = 1;
+
+ /** A container class to store a record of ContextHubEndpointBroker registrations. */
+ private class RegistrationRecord {
+ private final String mBroker;
+ private final int mAction;
+ private final long mTimestamp;
+
+ RegistrationRecord(String broker, @Action int action) {
+ mBroker = broker;
+ mAction = action;
+ mTimestamp = System.currentTimeMillis();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(ContextHubServiceUtil.formatDateFromTimestamp(mTimestamp));
+ sb.append(" ");
+ sb.append(mAction == ACTION_REGISTERED ? "+ " : "- ");
+ sb.append(mBroker);
+ return sb.toString();
+ }
+ }
+
/* package */ ContextHubEndpointManager(
Context context,
IContextHubWrapper contextHubProxy,
@@ -194,7 +241,7 @@
*/
/* package */ IContextHubEndpoint registerEndpoint(
HubEndpointInfo pendingEndpointInfo,
- IContextHubEndpointCallback callback,
+ @NonNull IContextHubEndpointCallback callback,
String packageName,
String attributionTag)
throws RemoteException {
@@ -228,6 +275,7 @@
return null;
}
+ mRegistrationRecordDeque.add(new RegistrationRecord(broker.toString(), ACTION_REGISTERED));
Log.d(TAG, "Registered endpoint with ID = " + endpointId);
return IContextHubEndpoint.Stub.asInterface(broker);
}
@@ -274,7 +322,11 @@
* @param endpointId The ID of the endpoint to unregister.
*/
/* package */ void unregisterEndpoint(long endpointId) {
- mEndpointMap.remove(endpointId);
+ ContextHubEndpointBroker broker = mEndpointMap.remove(endpointId);
+ if (broker != null) {
+ mRegistrationRecordDeque.add(
+ new RegistrationRecord(broker.toString(), ACTION_UNREGISTERED));
+ }
}
/** Invoked by the service when the Context Hub HAL restarts. */
@@ -366,6 +418,27 @@
}
}
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ int count = 1;
+ for (ContextHubEndpointBroker broker : mEndpointMap.values()) {
+ sb.append(count + ". " + broker);
+ sb.append(System.lineSeparator());
+ count++;
+ }
+
+ sb.append(System.lineSeparator());
+ sb.append("Registration History:");
+ sb.append(System.lineSeparator());
+ Iterator<RegistrationRecord> it = mRegistrationRecordDeque.descendingIterator();
+ while (it.hasNext()) {
+ sb.append(it.next());
+ sb.append(System.lineSeparator());
+ }
+ return sb.toString();
+ }
+
/**
* Invokes a callback for a session with matching ID.
*
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 502a7ae..2c0c55b 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -792,6 +792,10 @@
Log.e(TAG, "Endpoint manager failed to initialize");
throw new UnsupportedOperationException("Endpoint registration is not supported");
}
+ if (callback == null) {
+ Log.e(TAG, "Endpoint callback is invalid");
+ throw new IllegalArgumentException("registerEndpoint must have a non-null callback");
+ }
return mEndpointManager.registerEndpoint(
pendingHubEndpointInfo, callback, packageName, attributionTag);
}
@@ -1579,6 +1583,12 @@
pw.println("=================== CLIENTS ====================");
pw.println(mClientManager);
+ if (mEndpointManager != null) {
+ pw.println("");
+ pw.println("=================== ENDPOINTS ====================");
+ pw.println(mEndpointManager);
+ }
+
pw.println("");
pw.println("=================== TRANSACTIONS ====================");
pw.println(mTransactionManager);
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 177eefb..3f75b11 100644
--- a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
+++ b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
@@ -29,7 +29,6 @@
import android.util.Log;
import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.flags.Flags;
import com.android.server.FgThread;
import java.util.Objects;
@@ -107,26 +106,19 @@
boolean isInExtensionTime = mEmergencyCallEndRealtimeMs != Long.MIN_VALUE
&& (SystemClock.elapsedRealtime() - mEmergencyCallEndRealtimeMs) < extensionTimeMs;
- if (!Flags.enforceTelephonyFeatureMapping()) {
- return mIsInEmergencyCall
- || isInExtensionTime
- || mTelephonyManager.getEmergencyCallbackMode()
- || mTelephonyManager.isInEmergencySmsMode();
- } else {
- boolean emergencyCallbackMode = false;
- boolean emergencySmsMode = false;
- PackageManager pm = mContext.getPackageManager();
- if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)) {
- emergencyCallbackMode = mTelephonyManager.getEmergencyCallbackMode();
- }
- if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)) {
- emergencySmsMode = mTelephonyManager.isInEmergencySmsMode();
- }
- return mIsInEmergencyCall
- || isInExtensionTime
- || emergencyCallbackMode
- || emergencySmsMode;
+ boolean emergencyCallbackMode = false;
+ boolean emergencySmsMode = false;
+ PackageManager pm = mContext.getPackageManager();
+ if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)) {
+ emergencyCallbackMode = mTelephonyManager.getEmergencyCallbackMode();
}
+ if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)) {
+ emergencySmsMode = mTelephonyManager.isInEmergencySmsMode();
+ }
+ return mIsInEmergencyCall
+ || isInExtensionTime
+ || emergencyCallbackMode
+ || emergencySmsMode;
}
private class EmergencyCallTelephonyCallback extends TelephonyCallback implements
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/OWNERS b/services/core/java/com/android/server/locksettings/recoverablekeystore/OWNERS
index bb487fb..ebf7e6b 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/OWNERS
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/OWNERS
@@ -1,4 +1,3 @@
aseemk@google.com
bozhu@google.com
dementyev@google.com
-robertberry@google.com
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 0fc182f..fff812c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -42,6 +42,7 @@
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
+import static com.android.server.notification.PreferencesHelper.LockableAppFields.USER_LOCKED_BUBBLE;
import static com.android.server.notification.PreferencesHelper.LockableAppFields.USER_LOCKED_PROMOTABLE;
import android.annotation.FlaggedApi;
@@ -286,7 +287,7 @@
if (!TAG_RANKING.equals(tag)) return;
final int xmlVersion = parser.getAttributeInt(null, ATT_VERSION, -1);
- boolean upgradeForBubbles = xmlVersion == XML_VERSION_BUBBLES_UPGRADE;
+ boolean upgradeForBubbles = xmlVersion >= XML_VERSION_BUBBLES_UPGRADE;
boolean migrateToPermission = (xmlVersion < XML_VERSION_NOTIF_PERMISSION);
if (mShowReviewPermissionsNotification
&& (xmlVersion < XML_VERSION_REVIEW_PERMISSIONS_NOTIFICATION)) {
@@ -337,15 +338,19 @@
}
boolean skipWarningLogged = false;
boolean skipGroupWarningLogged = false;
- boolean hasSAWPermission = false;
- if (upgradeForBubbles && uid != UNKNOWN_UID) {
- hasSAWPermission = mAppOps.noteOpNoThrow(
- OP_SYSTEM_ALERT_WINDOW, uid, name, null,
- "check-notif-bubble") == AppOpsManager.MODE_ALLOWED;
+ int bubblePref = parser.getAttributeInt(null, ATT_ALLOW_BUBBLE,
+ DEFAULT_BUBBLE_PREFERENCE);
+ boolean bubbleLocked = (parser.getAttributeInt(null,
+ ATT_APP_USER_LOCKED_FIELDS, DEFAULT_LOCKED_APP_FIELDS) & USER_LOCKED_BUBBLE)
+ != 0;
+ if (!bubbleLocked
+ && upgradeForBubbles
+ && uid != UNKNOWN_UID
+ && mAppOps.noteOpNoThrow(OP_SYSTEM_ALERT_WINDOW, uid, name, null,
+ "check-notif-bubble") == AppOpsManager.MODE_ALLOWED) {
+ // User hasn't changed bubble pref & the app has SAW, so allow all bubbles.
+ bubblePref = BUBBLE_PREFERENCE_ALL;
}
- int bubblePref = hasSAWPermission
- ? BUBBLE_PREFERENCE_ALL
- : parser.getAttributeInt(null, ATT_ALLOW_BUBBLE, DEFAULT_BUBBLE_PREFERENCE);
int appImportance = parser.getAttributeInt(null, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
// when data is loaded from disk it's loaded as USER_ALL, but restored data that
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index 29f8243..ae41519 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -24,6 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.os.CreateAppDataArgs;
@@ -548,7 +549,7 @@
return prepareAppDataFuture;
}
- void clearAppDataLIF(AndroidPackage pkg, int userId, int flags) {
+ void clearAppDataLIF(AndroidPackage pkg, @CanBeALL @UserIdInt int userId, int flags) {
if (pkg == null) {
return;
}
@@ -559,7 +560,8 @@
}
}
- void clearAppDataLeafLIF(String packageName, String volumeUuid, int userId, int flags) {
+ void clearAppDataLeafLIF(String packageName, String volumeUuid, @CanBeALL @UserIdInt int userId,
+ int flags) {
final Computer snapshot = mPm.snapshotComputer();
final PackageStateInternal packageStateInternal =
snapshot.getPackageStateInternal(packageName);
diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
index c3af578..463989a 100644
--- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
+++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
@@ -332,7 +332,8 @@
userId)
!= PERMISSION_GRANTED) {
if(Build.IS_DEBUGGABLE) {
- Slog.d(TAG, "handlePackageAdd " + packageName + ": installer doesn't "
+ Slog.d(TAG, "handlePackageAdd " + packageName + ": installer ("
+ + installerPackageName + ") doesn't "
+ "have INSTALL_PACKAGES permission, skipping");
}
return;
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 90adb66..6bec34e 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -35,6 +35,8 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
+import android.annotation.UserIdInt;
import android.app.ApplicationExitInfo;
import android.app.ApplicationPackageManager;
import android.content.Intent;
@@ -562,7 +564,7 @@
}
@GuardedBy("mPm.mInstallLock")
- private void deleteInstalledPackageLIF(PackageSetting ps, int userId,
+ private void deleteInstalledPackageLIF(PackageSetting ps, @CanBeALL @UserIdInt int userId,
boolean deleteCodeAndResources, int flags, @NonNull int[] allUserHandles,
@NonNull PackageRemovedInfo outInfo, boolean writeSettings) {
synchronized (mPm.mLock) {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 15688c0..2811747 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -204,6 +204,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -1023,6 +1024,7 @@
*/
void installPackagesTraced(List<InstallRequest> requests, MoveInfo moveInfo) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
+ boolean pendingForDexopt = false;
boolean success = false;
final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size());
@@ -1036,17 +1038,41 @@
if (reconciledPackages == null) {
return;
}
+
if (renameAndUpdatePaths(requests)) {
// rename before dexopt because art will encoded the path in the odex/vdex file
if (Flags.improveInstallFreeze()) {
- prepPerformDexoptIfNeeded(reconciledPackages);
- }
- if (commitInstallPackages(reconciledPackages)) {
- success = true;
+ pendingForDexopt = true;
+ final Runnable actionsAfterDexopt = () ->
+ doPostDexopt(reconciledPackages, requests,
+ createdAppId, moveInfo, acquireTime);
+ prepPerformDexoptIfNeeded(reconciledPackages, actionsAfterDexopt);
+ } else {
+ if (commitInstallPackages(reconciledPackages)) {
+ success = true;
+ }
}
}
}
} finally {
+ if (!pendingForDexopt) {
+ completeInstallProcess(requests, createdAppId, success);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ doPostInstall(requests, moveInfo);
+ releaseWakeLock(acquireTime, requests.size());
+ }
+ }
+ }
+
+ void doPostDexopt(List<ReconciledPackage> reconciledPackages,
+ List<InstallRequest> requests, Map<String, Boolean> createdAppId,
+ MoveInfo moveInfo, long acquireTime) {
+ boolean success = false;
+ try {
+ if (commitInstallPackages(reconciledPackages)) {
+ success = true;
+ }
+ } finally {
completeInstallProcess(requests, createdAppId, success);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
doPostInstall(requests, moveInfo);
@@ -1123,7 +1149,7 @@
throws PackageManagerException {
final int userId = installRequest.getUserId();
if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT
- && !mPm.mUserManager.exists(userId)) {
+ && !ArrayUtils.contains(allUsers, userId)) {
throw new PackageManagerException(PackageManagerException.INTERNAL_ERROR_MISSING_USER,
"User " + userId + " doesn't exist or has been removed");
}
@@ -1155,7 +1181,9 @@
}
}
- private void prepPerformDexoptIfNeeded(List<ReconciledPackage> reconciledPackages) {
+ private void prepPerformDexoptIfNeeded(List<ReconciledPackage> reconciledPackages,
+ Runnable actionsAfterDexopt) {
+ List<CompletableFuture<Void>> completableFutures = new ArrayList<>();
for (ReconciledPackage reconciledPkg : reconciledPackages) {
final InstallRequest request = reconciledPkg.mInstallRequest;
// prepare profiles
@@ -1171,6 +1199,7 @@
mSharedLibraries.executeSharedLibrariesUpdate(request.getParsedPackage(), ps,
null, null, reconciledPkg.mCollectedSharedLibraryInfos, allUsers);
}
+
try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
final int[] newUsers = getNewUsers(request, allUsers);
// Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
@@ -1182,11 +1211,22 @@
}
} catch (PackageManagerException e) {
request.setError(e.error, e.getMessage());
- return;
+ break;
}
request.setKeepArtProfile(true);
- // TODO(b/388159696): Use performDexoptIfNeededAsync.
- DexOptHelper.performDexoptIfNeeded(request, mDexManager, null /* installLock */);
+
+ CompletableFuture<Void> future =
+ DexOptHelper.performDexoptIfNeededAsync(request, mDexManager);
+ completableFutures.add(future);
+ }
+
+ if (!completableFutures.isEmpty()) {
+ CompletableFuture<Void> allFutures =
+ CompletableFuture.allOf(
+ completableFutures.toArray(CompletableFuture[]::new));
+ var unused = allFutures.thenRun(() -> mPm.mHandler.post(actionsAfterDexopt));
+ } else {
+ actionsAfterDexopt.run();
}
}
@@ -2759,6 +2799,7 @@
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
+ // run synchronous dexopt if the freeze improvement is not supported
DexOptHelper.performDexoptIfNeeded(
installRequest, mDexManager, mPm.mInstallLock.getRawLock());
}
diff --git a/services/core/java/com/android/server/pm/PackageFreezer.java b/services/core/java/com/android/server/pm/PackageFreezer.java
index 11f2059..d66eb81 100644
--- a/services/core/java/com/android/server/pm/PackageFreezer.java
+++ b/services/core/java/com/android/server/pm/PackageFreezer.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
+import android.annotation.UserIdInt;
import android.content.pm.Flags;
import android.content.pm.PackageManager;
@@ -60,12 +62,12 @@
}
}
- PackageFreezer(String packageName, int userId, String killReason,
+ PackageFreezer(String packageName, @CanBeALL @UserIdInt int userId, String killReason,
PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request) {
this(packageName, userId, killReason, pm, exitInfoReason, request, false);
}
- PackageFreezer(String packageName, int userId, String killReason,
+ PackageFreezer(String packageName, @CanBeALL @UserIdInt int userId, String killReason,
PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request,
boolean waitAppKilled) {
mPm = pm;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index e1fcc66..2d0bb25 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -805,22 +805,20 @@
}
}
- if (Flags.recoverabilityDetection()) {
- if (params.rollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH
- || params.rollbackImpactLevel
- == PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) {
- if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
- throw new IllegalArgumentException(
- "Can't set rollbackImpactLevel when rollback is not enabled");
- }
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "Setting rollbackImpactLevel requires the MANAGE_ROLLBACKS permission");
- }
- } else if (params.rollbackImpactLevel < 0) {
- throw new IllegalArgumentException("rollbackImpactLevel can't be negative.");
+ if (params.rollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH
+ || params.rollbackImpactLevel
+ == PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) {
+ if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
+ throw new IllegalArgumentException(
+ "Can't set rollbackImpactLevel when rollback is not enabled");
}
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Setting rollbackImpactLevel requires the MANAGE_ROLLBACKS permission");
+ }
+ } else if (params.rollbackImpactLevel < 0) {
+ throw new IllegalArgumentException("rollbackImpactLevel can't be negative.");
}
boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 352985d..136cb12 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -948,6 +948,7 @@
break;
case MSG_ON_NATIVE_LIBS_EXTRACTED:
handleOnNativeLibsExtracted();
+ break;
}
return true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2464a29..91a1c9c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -50,6 +50,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
@@ -1590,7 +1591,7 @@
scheduleWritePackageRestrictions(userId);
}
- void scheduleWritePackageRestrictions(int userId) {
+ void scheduleWritePackageRestrictions(@CanBeALL @UserIdInt int userId) {
invalidatePackageInfoCache();
if (userId == UserHandle.USER_ALL) {
synchronized (mDirtyUsers) {
@@ -3074,7 +3075,7 @@
}
@NonNull
- int[] resolveUserIds(int userId) {
+ int[] resolveUserIds(@CanBeALL @UserIdInt int userId) {
return (userId == UserHandle.USER_ALL) ? mUserManager.getUserIds() : new int[] { userId };
}
@@ -3112,7 +3113,7 @@
}
void killApplication(String pkgName, @AppIdInt int appId,
- @UserIdInt int userId, String reason, int exitInfoReason) {
+ @CanBeALL @UserIdInt int userId, String reason, int exitInfoReason) {
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
@@ -3131,7 +3132,7 @@
}
void killApplicationSync(String pkgName, @AppIdInt int appId,
- @UserIdInt int userId, String reason, int exitInfoReason) {
+ @CanBeALL @UserIdInt int userId, String reason, int exitInfoReason) {
ActivityManagerInternal mAmi = LocalServices.getService(ActivityManagerInternal.class);
if (Thread.holdsLock(mLock) || mAmi == null) {
// holds PM's lock, go back killApplication to avoid it run into watchdog reset.
@@ -3385,7 +3386,7 @@
}
// TODO(b/261957226): centralise this logic in DPM
- boolean isPackageDeviceAdmin(String packageName, int userId) {
+ boolean isPackageDeviceAdmin(String packageName, @CanBeALL @UserIdInt int userId) {
final IDevicePolicyManager dpm = getDevicePolicyManager();
final DevicePolicyManagerInternal dpmi =
mInjector.getLocalService(DevicePolicyManagerInternal.class);
@@ -3555,7 +3556,7 @@
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
@GuardedBy("mLock")
void clearPackagePreferredActivitiesLPw(String packageName,
- @NonNull SparseBooleanArray outUserChanged, int userId) {
+ @NonNull SparseBooleanArray outUserChanged, @CanBeALL @UserIdInt int userId) {
mSettings.clearPackagePreferredActivities(packageName, outUserChanged, userId);
}
@@ -4388,14 +4389,14 @@
}
}
- public PackageFreezer freezePackage(String packageName, int userId, String killReason,
- int exitInfoReason, InstallRequest request) {
+ public PackageFreezer freezePackage(String packageName, @CanBeALL @UserIdInt int userId,
+ String killReason, int exitInfoReason, InstallRequest request) {
return freezePackage(packageName, userId, killReason, exitInfoReason, request,
/* waitAppKilled= */ false);
}
- private PackageFreezer freezePackage(String packageName, int userId, String killReason,
- int exitInfoReason, InstallRequest request, boolean waitAppKilled) {
+ private PackageFreezer freezePackage(String packageName, @CanBeALL @UserIdInt int userId,
+ String killReason, int exitInfoReason, InstallRequest request, boolean waitAppKilled) {
return new PackageFreezer(packageName, userId, killReason, this, exitInfoReason, request,
waitAppKilled);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index aa235c2..cf598e8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3561,9 +3561,6 @@
sessionParams.setEnableRollback(true, rollbackStrategy);
break;
case "--rollback-impact-level":
- if (!Flags.recoverabilityDetection()) {
- throw new IllegalArgumentException("Unknown option " + opt);
- }
int rollbackImpactLevel = Integer.parseInt(peekNextArg());
if (rollbackImpactLevel < PackageManager.ROLLBACK_USER_IMPACT_LOW
|| rollbackImpactLevel
@@ -4775,11 +4772,9 @@
pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
pw.println(" --enable-rollback: enable rollbacks for the upgrade.");
pw.println(" 0=restore (default), 1=wipe, 2=retain");
- if (Flags.recoverabilityDetection()) {
- pw.println(
- " --rollback-impact-level: set device impact required for rollback.");
- pw.println(" 0=low (default), 1=high, 2=manual only");
- }
+ pw.println(
+ " --rollback-impact-level: set device impact required for rollback.");
+ pw.println(" 0=low (default), 1=high, 2=manual only");
pw.println(" --install-location: force the install location:");
pw.println(" 0=auto, 1=internal only, 2=prefer external");
pw.println(" --install-reason: indicates why the app is being installed:");
diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
index 41d2aeb..fa56596 100644
--- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java
+++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
@@ -25,6 +25,7 @@
import static com.android.server.pm.PackageManagerService.TAG;
import android.annotation.NonNull;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
@@ -115,7 +116,8 @@
}
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
- public void clearPackagePreferredActivities(String packageName, int userId) {
+ public void clearPackagePreferredActivities(String packageName,
+ @CanBeALL @UserIdInt int userId) {
final SparseBooleanArray changedUsers = new SparseBooleanArray();
synchronized (mPm.mLock) {
mPm.clearPackagePreferredActivitiesLPw(packageName, changedUsers, userId);
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index f01a74e..22b4ec7 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -30,6 +30,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
+import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.pm.parsing.PackageLite;
@@ -256,7 +258,8 @@
* Make sure this flag is set for partially installed apps. If not it's meaningless to
* delete a partially installed application.
*/
- public void clearPackageStateForUserLIF(PackageSetting ps, int userId, int flags) {
+ public void clearPackageStateForUserLIF(PackageSetting ps, @CanBeALL @UserIdInt int userId,
+ int flags) {
final String packageName = ps.getPackageName();
// Step 1: always destroy app profiles except when explicitly preserved
if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
@@ -370,13 +373,13 @@
* This method deletes the package from internal data structures such as mPackages / mSettings.
*
* @param targetUserId indicates the target user of the deletion. It equals to
- * {@link UserHandle.USER_ALL} if the deletion was initiated for all users,
+ * {@link UserHandle#USER_ALL} if the deletion was initiated for all users,
* otherwise it equals to the specific user id that the deletion was meant
* for.
*/
@GuardedBy("mPm.mInstallLock")
- public void removePackageDataLIF(final PackageSetting deletedPs, int targetUserId,
- @NonNull int[] allUserHandles,
+ public void removePackageDataLIF(final PackageSetting deletedPs,
+ @CanBeALL @UserIdInt int targetUserId, @NonNull int[] allUserHandles,
@NonNull PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
String packageName = deletedPs.getPackageName();
if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs);
@@ -482,7 +485,8 @@
}
}
- private static boolean shouldDeletePackageSetting(PackageSetting deletedPs, int userId,
+ private static boolean shouldDeletePackageSetting(PackageSetting deletedPs,
+ @CanBeALL @UserIdInt int userId,
int[] allUserHandles, int flags) {
if ((flags & PackageManager.DELETE_KEEP_DATA) != 0) {
return false;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 485a280..92257f1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -35,6 +35,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.app.compat.ChangeIdStateCache;
import android.content.ComponentName;
@@ -6639,7 +6640,7 @@
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
void clearPackagePreferredActivities(String packageName,
- @NonNull SparseBooleanArray outUserChanged, int userId) {
+ @NonNull SparseBooleanArray outUserChanged, @CanBeALL @UserIdInt int userId) {
boolean changed = false;
ArrayList<PreferredActivity> removed = null;
for (int i = 0; i < mPreferredActivities.size(); i++) {
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index 045d4db..346327d 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -453,7 +453,7 @@
@Override
protected File getShortcutPackageItemFile() {
final File path = new File(mShortcutUser.mService.injectUserDataPath(
- mShortcutUser.getUserId()), ShortcutUser.DIRECTORY_LUANCHERS);
+ mShortcutUser.getUserId()), ShortcutUser.DIRECTORY_LAUNCHERS);
// Package user id and owner id can have different values for ShortcutLaunchers. Adding
// user Id to the file name to create a unique path. Owner id is used in the root path.
final String fileName = getPackageName() + getPackageUserId() + ".xml";
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 373c1ed..d351305 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -16,7 +16,9 @@
package com.android.server.pm;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
-import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
+
+import static com.android.server.pm.ShortcutUser.DIRECTORY_LAUNCHERS;
+import static com.android.server.pm.ShortcutUser.DIRECTORY_PACKAGES;
import android.Manifest.permission;
import android.annotation.IntDef;
@@ -94,7 +96,6 @@
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
-import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.text.format.TimeMigrationUtils;
import android.util.ArraySet;
@@ -112,7 +113,6 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
@@ -155,7 +155,6 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
/**
* TODO:
@@ -171,7 +170,7 @@
static final boolean DEBUG = false; // STOPSHIP if true
static final boolean DEBUG_LOAD = false; // STOPSHIP if true
static final boolean DEBUG_PROCSTATE = false; // STOPSHIP if true
- static final boolean DEBUG_REBOOT = Build.IS_DEBUGGABLE;
+ static final boolean DEBUG_REBOOT = false; // STOPSHIP if true
@VisibleForTesting
static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day
@@ -292,7 +291,8 @@
final Context mContext;
- private final Object mServiceLock = new Object();
+ @VisibleForTesting
+ final Object mServiceLock = new Object();
private final Object mNonPersistentUsersLock = new Object();
private final Object mWtfLock = new Object();
@@ -982,7 +982,7 @@
}
@VisibleForTesting
- void saveBaseState() {
+ void injectSaveBaseState() {
try (ResilientAtomicFile file = getBaseStateFile()) {
if (DEBUG || DEBUG_REBOOT) {
Slog.d(TAG, "Saving to " + file.getBaseFile());
@@ -994,18 +994,7 @@
outs = file.startWrite();
}
- // Write to XML
- TypedXmlSerializer out = Xml.resolveSerializer(outs);
- out.startDocument(null, true);
- out.startTag(null, TAG_ROOT);
-
- // Body.
- // No locking required. Ok to add lock later if we save more data.
- writeTagValue(out, TAG_LAST_RESET_TIME, mRawLastResetTime.get());
-
- // Epilogue.
- out.endTag(null, TAG_ROOT);
- out.endDocument();
+ saveBaseStateAsXml(outs);
// Close.
injectFinishWrite(file, outs);
@@ -1016,10 +1005,32 @@
}
}
+ @VisibleForTesting
+ protected void saveBaseStateAsXml(OutputStream outs) throws IOException {
+ // Write to XML
+ TypedXmlSerializer out = Xml.resolveSerializer(outs);
+ out.startDocument(null, true);
+ out.startTag(null, TAG_ROOT);
+
+ // Body.
+ // No locking required. Ok to add lock later if we save more data.
+ writeTagValue(out, TAG_LAST_RESET_TIME, mRawLastResetTime.get());
+
+ // Epilogue.
+ out.endTag(null, TAG_ROOT);
+ out.endDocument();
+ }
+
@GuardedBy("mServiceLock")
private void loadBaseStateLocked() {
mRawLastResetTime.set(0);
+ injectLoadBaseState();
+ // Adjust the last reset time.
+ getLastResetTimeLocked();
+ }
+ @VisibleForTesting
+ protected void injectLoadBaseState() {
try (ResilientAtomicFile file = getBaseStateFile()) {
if (DEBUG || DEBUG_REBOOT) {
Slog.d(TAG, "Loading from " + file.getBaseFile());
@@ -1030,34 +1041,7 @@
if (in == null) {
throw new FileNotFoundException(file.getBaseFile().getAbsolutePath());
}
-
- TypedXmlPullParser parser = Xml.resolvePullParser(in);
-
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- final int depth = parser.getDepth();
- // Check the root tag
- final String tag = parser.getName();
- if (depth == 1) {
- if (!TAG_ROOT.equals(tag)) {
- Slog.v(TAG, "Invalid root tag: " + tag);
- return;
- }
- continue;
- }
- // Assume depth == 2
- switch (tag) {
- case TAG_LAST_RESET_TIME:
- mRawLastResetTime.set(parseLongAttribute(parser, ATTR_VALUE));
- break;
- default:
- Slog.v(TAG, "Invalid tag: " + tag);
- break;
- }
- }
+ loadBaseStateAsXml(in);
} catch (FileNotFoundException e) {
// Use the default
} catch (IOException | XmlPullParserException e) {
@@ -1067,8 +1051,38 @@
return;
}
}
- // Adjust the last reset time.
- getLastResetTimeLocked();
+ }
+
+ @VisibleForTesting
+ protected void loadBaseStateAsXml(InputStream in)
+ throws IOException, XmlPullParserException {
+ TypedXmlPullParser parser = Xml.resolvePullParser(in);
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ final int depth = parser.getDepth();
+ // Check the root tag
+ final String tag = parser.getName();
+ if (depth == 1) {
+ if (!TAG_ROOT.equals(tag)) {
+ Slog.v(TAG, "Invalid root tag: " + tag);
+ return;
+ }
+ continue;
+ }
+ // Assume depth == 2
+ switch (tag) {
+ case TAG_LAST_RESET_TIME:
+ mRawLastResetTime.set(parseLongAttribute(parser, ATTR_VALUE));
+ break;
+ default:
+ Slog.v(TAG, "Invalid tag: " + tag);
+ break;
+ }
+ }
}
@VisibleForTesting
@@ -1083,7 +1097,8 @@
"user shortcut", null);
}
- private void saveUser(@UserIdInt int userId) {
+ @VisibleForTesting
+ protected void injectSaveUser(@UserIdInt int userId) {
try (ResilientAtomicFile file = getUserFile(userId)) {
FileOutputStream os = null;
try {
@@ -1092,8 +1107,14 @@
}
synchronized (mServiceLock) {
+ // Since we are not handling package deletion yet, or any single package
+ // changes, just clean the directory and rewrite all the ShortcutPackageItems.
+ final File root = injectUserDataPath(userId);
+ FileUtils.deleteContents(new File(root, DIRECTORY_PACKAGES));
+ FileUtils.deleteContents(new File(root, DIRECTORY_LAUNCHERS));
os = file.startWrite();
saveUserInternalLocked(userId, os, /* forBackup= */ false);
+ getUserShortcutsLocked(userId).scheduleSaveAllLaunchersAndPackages();
}
injectFinishWrite(file, os);
@@ -1109,8 +1130,9 @@
getUserShortcutsLocked(userId).logSharingShortcutStats(mMetricsLogger);
}
+ @VisibleForTesting
@GuardedBy("mServiceLock")
- private void saveUserInternalLocked(@UserIdInt int userId, OutputStream os,
+ protected void saveUserInternalLocked(@UserIdInt int userId, OutputStream os,
boolean forBackup) throws IOException, XmlPullParserException {
// Write to XML
@@ -1138,8 +1160,9 @@
Slog.w(TAG, String.format("Invalid tag '%s' found at depth %d", tag, depth));
}
+ @VisibleForTesting
@Nullable
- private ShortcutUser loadUserLocked(@UserIdInt int userId) {
+ protected ShortcutUser injectLoadUserLocked(@UserIdInt int userId) {
try (ResilientAtomicFile file = getUserFile(userId)) {
FileInputStream in = null;
try {
@@ -1157,12 +1180,13 @@
} catch (Exception e) {
// Remove corrupted file and retry.
file.failRead(in, e);
- return loadUserLocked(userId);
+ return injectLoadUserLocked(userId);
}
}
}
- private ShortcutUser loadUserInternal(@UserIdInt int userId, InputStream is,
+ @VisibleForTesting
+ protected ShortcutUser loadUserInternal(@UserIdInt int userId, InputStream is,
boolean fromBackup) throws XmlPullParserException, IOException,
InvalidFileFormatException {
@@ -1240,9 +1264,9 @@
for (int i = dirtyUserIds.size() - 1; i >= 0; i--) {
final int userId = dirtyUserIds.get(i);
if (userId == UserHandle.USER_NULL) { // USER_NULL for base state.
- saveBaseState();
+ injectSaveBaseState();
} else {
- saveUser(userId);
+ injectSaveUser(userId);
}
}
} catch (Exception e) {
@@ -1349,7 +1373,7 @@
ShortcutUser userPackages = mUsers.get(userId);
if (userPackages == null) {
- userPackages = loadUserLocked(userId);
+ userPackages = injectLoadUserLocked(userId);
if (userPackages == null) {
userPackages = new ShortcutUser(this, userId);
}
@@ -1430,8 +1454,9 @@
* {@link ShortcutBitmapSaver#waitForAllSavesLocked()} to make sure there's no pending bitmap
* saves are going on.
*/
+ @VisibleForTesting
@GuardedBy("mServiceLock")
- private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) {
+ void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) {
if (DEBUG) {
Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId);
}
@@ -2755,7 +2780,7 @@
getPackageShortcutsLocked(packageName, userId)
.resetRateLimitingForCommandLineNoSaving();
}
- saveUser(userId);
+ injectSaveUser(userId);
}
// We override this method in unit tests to do a simpler check.
@@ -4407,7 +4432,7 @@
pw.println();
});
}
- saveUser(userId);
+ injectSaveUser(userId);
}
// === Dump ===
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index bc8cc7b..632fd16 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -21,16 +21,12 @@
import android.content.pm.ShortcutManager;
import android.content.pm.UserPackage;
import android.metrics.LogMaker;
-import android.os.Binder;
-import android.os.FileUtils;
-import android.os.UserHandle;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -49,8 +45,6 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -63,7 +57,7 @@
private static final String TAG = ShortcutService.TAG;
static final String DIRECTORY_PACKAGES = "packages";
- static final String DIRECTORY_LUANCHERS = "launchers";
+ static final String DIRECTORY_LAUNCHERS = "launchers";
static final String TAG_ROOT = "user";
private static final String TAG_LAUNCHER = "launcher";
@@ -322,41 +316,43 @@
mService.injectBuildFingerprint());
}
- if (!forBackup) {
- // Since we are not handling package deletion yet, or any single package changes, just
- // clean the directory and rewrite all the ShortcutPackageItems.
- final File root = mService.injectUserDataPath(mUserId);
- FileUtils.deleteContents(new File(root, DIRECTORY_PACKAGES));
- FileUtils.deleteContents(new File(root, DIRECTORY_LUANCHERS));
- }
// Can't use forEachPackageItem due to the checked exceptions.
- {
- final int size = mLaunchers.size();
+ if (forBackup) {
+ int size = mLaunchers.size();
for (int i = 0; i < size; i++) {
- saveShortcutPackageItem(out, mLaunchers.valueAt(i), forBackup);
+ saveShortcutPackageItem(out, mLaunchers.valueAt(i));
}
- }
- {
- final int size = mPackages.size();
+ size = mPackages.size();
for (int i = 0; i < size; i++) {
- saveShortcutPackageItem(out, mPackages.valueAt(i), forBackup);
+ saveShortcutPackageItem(out, mPackages.valueAt(i));
}
}
out.endTag(null, TAG_ROOT);
}
- private void saveShortcutPackageItem(TypedXmlSerializer out, ShortcutPackageItem spi,
- boolean forBackup) throws IOException, XmlPullParserException {
- if (forBackup) {
- if (spi.getPackageUserId() != spi.getOwnerUserId()) {
- return; // Don't save cross-user information.
+ void scheduleSaveAllLaunchersAndPackages() {
+ {
+ final int size = mLaunchers.size();
+ for (int i = 0; i < size; i++) {
+ mLaunchers.valueAt(i).scheduleSave();
}
- spi.waitForBitmapSaves();
- spi.saveToXml(out, forBackup);
- } else {
- spi.scheduleSave();
}
+ {
+ final int size = mPackages.size();
+ for (int i = 0; i < size; i++) {
+ mPackages.valueAt(i).scheduleSave();
+ }
+ }
+ }
+
+ private void saveShortcutPackageItem(TypedXmlSerializer out, ShortcutPackageItem spi)
+ throws IOException, XmlPullParserException {
+ if (spi.getPackageUserId() != spi.getOwnerUserId()) {
+ return; // Don't save cross-user information.
+ }
+ spi.waitForBitmapSaves();
+ spi.saveToXml(out, true /* forBackup */);
}
public static ShortcutUser loadFromXml(ShortcutService s, TypedXmlPullParser parser, int userId,
@@ -429,7 +425,7 @@
}
});
- forMainFilesIn(new File(root, DIRECTORY_LUANCHERS), (File f) -> {
+ forMainFilesIn(new File(root, DIRECTORY_LAUNCHERS), (File f) -> {
final ShortcutLauncher sl =
ShortcutLauncher.loadFromFile(f, ret, userId, fromBackup);
if (sl != null) {
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index dd60a15..8510ee7 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -179,8 +179,7 @@
// Perform package verification and enable rollback (unless we are simply moving the
// package).
if (!mOriginInfo.mExisting) {
- final boolean verifyForRollback = Flags.recoverabilityDetection()
- ? !isARollback() : true;
+ final boolean verifyForRollback = !isARollback();
if (!isApex() && !isArchivedInstallation() && verifyForRollback) {
// TODO(b/182426975): treat APEX as APK when APK verification is concerned
sendApkVerificationRequest(pkgLite);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 5c5a9c1..ac19ea1 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -37,6 +37,7 @@
import android.annotation.AppIdInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -765,7 +766,7 @@
@Override
public void onPackageUninstalled(@NonNull String packageName, int appId,
@NonNull PackageState packageState, @Nullable AndroidPackage pkg,
- @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId) {
+ @NonNull List<AndroidPackage> sharedUserPkgs, @CanBeALL @UserIdInt int userId) {
if (userId != UserHandle.USER_ALL) {
final int[] userIds = getAllUserIds();
if (!ArrayUtils.contains(userIds, userId)) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index e51ec04..33d57d5 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -65,6 +65,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -5284,7 +5285,7 @@
@Override
public void onPackageUninstalled(@NonNull String packageName, int appId,
@NonNull PackageState packageState, @Nullable AndroidPackage pkg,
- @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId) {
+ @NonNull List<AndroidPackage> sharedUserPkgs, @CanBeALL @UserIdInt int userId) {
Objects.requireNonNull(packageState, "packageState");
Objects.requireNonNull(packageName, "packageName");
Objects.requireNonNull(sharedUserPkgs, "sharedUserPkgs");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index 3d295f7..f2491d9 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -19,6 +19,7 @@
import android.annotation.AppIdInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -662,5 +663,5 @@
*/
void onPackageUninstalled(@NonNull String packageName, int appId,
@NonNull PackageState packageState, @Nullable AndroidPackage pkg,
- @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId);
+ @NonNull List<AndroidPackage> sharedUserPkgs, @CanBeALL @UserIdInt int userId);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index a5c1284..ad765c8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.pm.PackageInstaller.SessionParams;
@@ -325,7 +326,7 @@
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
void onPackageUninstalled(@NonNull String packageName, int appId,
@Nullable PackageState packageState, @Nullable AndroidPackage pkg,
- @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId);
+ @NonNull List<AndroidPackage> sharedUserPkgs, @CanBeALL @UserIdInt int userId);
/**
* The permission-related parameters passed in for package installation.
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 44d787f..c31c287 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -82,12 +82,10 @@
import android.util.Slog;
import android.util.SparseBooleanArray;
-import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.infra.AndroidFuture;
-import com.android.internal.policy.AttributeCache;
import com.android.internal.util.IntPair;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
@@ -167,6 +165,7 @@
private Context mContext;
private PackageManagerInternal mPackageManagerInternal;
private PermissionManagerServiceInternal mPermissionManagerInternal;
+ private ActivityTaskManagerInternal mActivityTaskManagerInternal;
private NotificationManagerInternal mNotificationManager;
private TelephonyManager mTelephonyManager;
private final KeyguardManager mKeyguardManager;
@@ -189,6 +188,7 @@
PackageManagerInternal.class);
mPermissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class);
+ mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
@@ -1154,7 +1154,7 @@
activityInfo.packageName, info.getCallingPackage(),
info.getIntent(), info.getCheckedOptions(), activityInfo.name,
true)
- || isNoDisplayActivity(activityInfo)) {
+ || isNoDisplayActivity(activityInfo, info.getUserId())) {
return;
}
UserHandle user = UserHandle.of(taskInfo.userId);
@@ -1170,9 +1170,7 @@
};
private void onActivityManagerReady() {
- ActivityTaskManagerInternal atm =
- LocalServices.getService(ActivityTaskManagerInternal.class);
- atm.registerActivityStartInterceptor(
+ mActivityTaskManagerInternal.registerActivityStartInterceptor(
ActivityInterceptorCallback.PERMISSION_POLICY_ORDERED_ID,
mActivityInterceptorCallback);
}
@@ -1227,20 +1225,14 @@
null, activityName, false);
}
- private boolean isNoDisplayActivity(@NonNull ActivityInfo aInfo) {
+ private boolean isNoDisplayActivity(@NonNull ActivityInfo aInfo, int userId) {
final int themeResource = aInfo.getThemeResource();
if (themeResource == Resources.ID_NULL) {
return false;
}
- boolean noDisplay = false;
- final AttributeCache.Entry ent = AttributeCache.instance()
- .get(aInfo.packageName, themeResource, R.styleable.Window, 0);
- if (ent != null) {
- noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
- }
-
- return noDisplay;
+ return mActivityTaskManagerInternal.isNoDisplay(aInfo.packageName, themeResource,
+ userId);
}
/**
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 76c5240..980fb155 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1163,6 +1163,15 @@
}
}
+ private boolean shouldShowHub() {
+ final boolean hubEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(), Settings.Secure.GLANCEABLE_HUB_ENABLED,
+ 1, mCurrentUserId) == 1;
+
+ return mUserManagerInternal != null && mUserManagerInternal.isUserUnlocked(mCurrentUserId)
+ && hubEnabled && mDreamManagerInternal.dreamConditionActive();
+ }
+
@VisibleForTesting
void powerPress(long eventTime, int count, int displayId) {
// SideFPS still needs to know about suppressed power buttons, in case it needs to block
@@ -1251,7 +1260,8 @@
mContext.getContentResolver(), Settings.Secure.GLANCEABLE_HUB_ENABLED,
1, mCurrentUserId) == 1;
- if (mDreamManagerInternal.isDreaming() || isKeyguardShowing()) {
+ if ((mDreamManagerInternal != null && mDreamManagerInternal.isDreaming())
+ || isKeyguardShowing()) {
// If the device is already dreaming or on keyguard, go to sleep.
sleepDefaultDisplayFromPowerButton(eventTime, 0);
break;
@@ -1261,9 +1271,10 @@
// show hub.
boolean keyguardAvailable = !mLockPatternUtils.isLockScreenDisabled(
mCurrentUserId);
- if (mUserManagerInternal.isUserUnlocked(mCurrentUserId) && hubEnabled
- && keyguardAvailable && mDreamManagerInternal.dreamConditionActive()) {
- // If the hub can be launched, send a message to keyguard.
+ if (shouldShowHub() && keyguardAvailable) {
+ // If the hub can be launched, send a message to keyguard. We do not know if
+ // the hub is already running or not, keyguard handles turning screen off if
+ // it is.
Bundle options = new Bundle();
options.putBoolean(EXTRA_TRIGGER_HUB, true);
lockNow(options);
@@ -1324,14 +1335,14 @@
* @param isScreenOn Whether the screen is currently on.
* @param noDreamAction The action to perform if dreaming is not possible.
*/
- private void attemptToDreamFromShortPowerButtonPress(
+ private boolean attemptToDreamFromShortPowerButtonPress(
boolean isScreenOn, Runnable noDreamAction) {
if (mShortPressOnPowerBehavior != SHORT_PRESS_POWER_DREAM_OR_SLEEP
&& mShortPressOnPowerBehavior != SHORT_PRESS_POWER_HUB_OR_DREAM_OR_SLEEP) {
// If the power button behavior isn't one that should be able to trigger the dream, give
// up.
noDreamAction.run();
- return;
+ return false;
}
final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
@@ -1339,7 +1350,7 @@
Slog.d(TAG, "Can't start dreaming when attempting to dream from short power"
+ " press (isScreenOn=" + isScreenOn + ")");
noDreamAction.run();
- return;
+ return false;
}
synchronized (mLock) {
@@ -1350,6 +1361,8 @@
}
dreamManagerInternal.requestDream();
+
+ return true;
}
/**
@@ -2327,6 +2340,10 @@
WindowWakeUpPolicy getWindowWakeUpPolicy() {
return new WindowWakeUpPolicy(mContext);
}
+
+ DreamManagerInternal getDreamManagerInternal() {
+ return LocalServices.getService(DreamManagerInternal.class);
+ }
}
/** {@inheritDoc} */
@@ -2345,7 +2362,7 @@
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mInputManager = mContext.getSystemService(InputManager.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
- mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
+ mDreamManagerInternal = injector.getDreamManagerInternal();
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mSensorPrivacyManager = mContext.getSystemService(SensorPrivacyManager.class);
@@ -3701,15 +3718,9 @@
break;
case KeyEvent.KEYCODE_N:
if (firstDown && event.isMetaPressed()) {
- if (event.isCtrlPressed()) {
- sendSystemKeyToStatusBarAsync(event);
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES);
- } else {
- toggleNotificationPanel();
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
- }
+ toggleNotificationPanel();
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
return true;
}
break;
@@ -6398,6 +6409,17 @@
event.getDisplayId(), event.getKeyCode(), "wakeUpFromWakeKey")) {
return;
}
+
+ if (!shouldShowHub()
+ && mShortPressOnPowerBehavior == SHORT_PRESS_POWER_HUB_OR_DREAM_OR_SLEEP
+ && event.getKeyCode() == KEYCODE_POWER
+ && attemptToDreamFromShortPowerButtonPress(false, () -> {})) {
+ // In the case that we should wake to dream and successfully initiate dreaming, do not
+ // continue waking up. Doing so will exit the dream state and cause UI to react
+ // accordingly.
+ return;
+ }
+
wakeUpFromWakeKey(
event.getEventTime(),
event.getKeyCode(),
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 1d62087..2cf6b7e 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -2911,19 +2911,7 @@
return false;
}
- mCounter.getCounts(counts, procState);
-
- // Return counts only if at least one of the elements is non-zero.
- for (int i = counts.length - 1; i >= 0; --i) {
- if (counts[i] != 0) {
- return true;
- }
- }
- return false;
- }
-
- public void logState(Printer pw, String prefix) {
- pw.println(prefix + "mCounter=" + mCounter);
+ return mCounter.getCounts(counts, procState);
}
/**
diff --git a/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
index 6f6a7ff..ca22375 100644
--- a/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
@@ -29,7 +29,8 @@
public class ScreenPowerStatsLayout extends PowerStatsLayout {
private static final String EXTRA_DEVICE_SCREEN_COUNT = "dsc";
private static final String EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION = "dsd";
- private static final String EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS = "dbd";
+ private static final String EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS = "dbds";
+ private static final String EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS_COMPAT = "dbd";
private static final String EXTRA_DEVICE_DOZE_DURATION_POSITION = "ddd";
private static final String EXTRA_DEVICE_DOZE_POWER_POSITION = "ddp";
private static final String EXTRA_UID_FOREGROUND_DURATION = "uf";
@@ -55,8 +56,14 @@
PersistableBundle extras = descriptor.extras;
mDisplayCount = extras.getInt(EXTRA_DEVICE_SCREEN_COUNT, 1);
mDeviceScreenOnDurationPosition = extras.getInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION);
- mDeviceBrightnessDurationPositions = extras.getIntArray(
+ mDeviceBrightnessDurationPositions = getIntArray(extras,
EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS);
+ if (mDeviceBrightnessDurationPositions == null) {
+ // We should never put arrays in PowerStats.Descriptor because of the performance of
+ // .equals
+ mDeviceBrightnessDurationPositions = extras.getIntArray(
+ EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS_COMPAT);
+ }
mDeviceScreenDozeDurationPosition = extras.getInt(EXTRA_DEVICE_DOZE_DURATION_POSITION);
mDeviceScreenDozePowerPosition = extras.getInt(EXTRA_DEVICE_DOZE_POWER_POSITION);
mUidTopActivityTimePosition = extras.getInt(EXTRA_UID_FOREGROUND_DURATION);
@@ -67,7 +74,7 @@
super.toExtras(extras);
extras.putInt(EXTRA_DEVICE_SCREEN_COUNT, mDisplayCount);
extras.putInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION, mDeviceScreenOnDurationPosition);
- extras.putIntArray(EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
+ putIntArray(extras, EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
mDeviceBrightnessDurationPositions);
extras.putInt(EXTRA_DEVICE_DOZE_DURATION_POSITION, mDeviceScreenDozeDurationPosition);
extras.putInt(EXTRA_DEVICE_DOZE_POWER_POSITION, mDeviceScreenDozePowerPosition);
diff --git a/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
index e8df3dd..c382534 100644
--- a/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
@@ -27,8 +27,10 @@
public class SensorPowerStatsLayout extends PowerStatsLayout {
private static final String TAG = "SensorPowerStatsLayout";
- private static final String EXTRA_DEVICE_SENSOR_HANDLES = "dsh";
+ private static final String EXTRA_DEVICE_SENSOR_HANDLES = "dshs";
+ private static final String EXTRA_DEVICE_SENSOR_HANDLES_COMPAT = "dsh";
private static final String EXTRA_UID_SENSOR_POSITIONS = "usp";
+ private static final String EXTRA_UID_SENSOR_POSITIONS_COMPAT = "usps";
private final SparseIntArray mSensorPositions = new SparseIntArray();
@@ -47,8 +49,14 @@
super(descriptor);
PersistableBundle extras = descriptor.extras;
- int[] handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES);
- int[] uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS);
+ int[] handlers = getIntArray(extras, EXTRA_DEVICE_SENSOR_HANDLES);
+ if (handlers == null) {
+ handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES_COMPAT);
+ }
+ int[] uidDurationPositions = getIntArray(extras, EXTRA_UID_SENSOR_POSITIONS);
+ if (uidDurationPositions == null) {
+ uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS_COMPAT);
+ }
if (handlers != null && uidDurationPositions != null) {
for (int i = 0; i < handlers.length; i++) {
@@ -69,8 +77,8 @@
uidDurationPositions[i] = mSensorPositions.valueAt(i);
}
- extras.putIntArray(EXTRA_DEVICE_SENSOR_HANDLES, handlers);
- extras.putIntArray(EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
+ putIntArray(extras, EXTRA_DEVICE_SENSOR_HANDLES, handlers);
+ putIntArray(extras, EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
}
private void addUidSensorSection(int handle, String label) {
diff --git a/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
index a783d54..53894a1 100644
--- a/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
@@ -25,6 +25,7 @@
import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.IndentingPrintWriter;
+import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -347,7 +348,10 @@
Set<Integer> uids = new HashSet<>();
for (int i = 0; i < mPowerComponentStats.size(); i++) {
- mPowerComponentStats.valueAt(i).collectUids(uids);
+ IntArray activeUids = mPowerComponentStats.valueAt(i).getActiveUids();
+ for (int j = activeUids.size() - 1; j >= 0; j--) {
+ uids.add(activeUids.get(j));
+ }
}
Integer[] allUids = uids.toArray(new Integer[uids.size()]);
diff --git a/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
index 5f93bdf..a550f2d 100644
--- a/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
@@ -68,11 +68,15 @@
// processor. All that remains to be done is copy the estimates over.
MultiStateStats.States.forEachTrackedStateCombination(deviceStateConfig,
states -> {
- screenStats.getDeviceStats(mTmpScreenStats, states);
+ if (!screenStats.getDeviceStats(mTmpScreenStats, states)) {
+ return;
+ }
double power =
mScreenPowerStatsLayout.getScreenDozePowerEstimate(mTmpScreenStats);
- mStatsLayout.setDevicePowerEstimate(mTmpDeviceStats, power);
- stats.setDeviceStats(states, mTmpDeviceStats);
+ if (power != 0) {
+ mStatsLayout.setDevicePowerEstimate(mTmpDeviceStats, power);
+ stats.setDeviceStats(states, mTmpDeviceStats);
+ }
});
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/BasePowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BasePowerStatsProcessor.java
index d24ea83..1d35933 100644
--- a/services/core/java/com/android/server/power/stats/processor/BasePowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BasePowerStatsProcessor.java
@@ -24,13 +24,12 @@
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
+import android.util.IntArray;
import com.android.internal.os.PowerStats;
import com.android.server.power.stats.format.BasePowerStatsLayout;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
import java.util.function.DoubleSupplier;
class BasePowerStatsProcessor extends PowerStatsProcessor {
@@ -125,11 +124,12 @@
mCumulativeDischargeUah = 0;
mCumulativeDischargeDurationMs = 0;
- List<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
-
- long durationMs = timestampMs - mStartTimestamp;
- if (!uids.isEmpty()) {
+ // Note that we are calling `getUids` rather than `getActiveUids`, because this Processor
+ // deals with duration rather than power estimation, so it needs to process *all* known
+ // UIDs, not just the ones that contributed PowerStats
+ IntArray uids = stats.getUids();
+ if (uids.size() != 0) {
+ long durationMs = timestampMs - mStartTimestamp;
for (int i = uids.size() - 1; i >= 0; i--) {
long[] uidStats = new long[sStatsLayout.getUidStatsArrayLength()];
sStatsLayout.setUidUsageDuration(uidStats, durationMs);
diff --git a/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
index 9fe7f3e..c89dddf 100644
--- a/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
@@ -20,6 +20,7 @@
import android.os.BatteryStats;
import android.os.PersistableBundle;
import android.os.Process;
+import android.util.IntArray;
import com.android.internal.os.PowerStats;
import com.android.server.power.stats.UsageBasedPowerEstimator;
@@ -27,7 +28,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -190,13 +190,13 @@
}
computeDevicePowerEstimates(stats, mPlan, mEnergyConsumerSupported);
- combineDevicePowerEstimates(stats);
- List<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
-
- computeUidActivityTotals(stats, uids);
- computeUidPowerEstimates(stats, uids);
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
+ combineDevicePowerEstimates(stats);
+ computeUidActivityTotals(stats, uids);
+ computeUidPowerEstimates(stats, uids);
+ }
}
protected void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats,
@@ -239,8 +239,7 @@
}
}
- private void computeUidActivityTotals(PowerComponentAggregatedPowerStats stats,
- List<Integer> uids) {
+ private void computeUidActivityTotals(PowerComponentAggregatedPowerStats stats, IntArray uids) {
for (int i = mPlan.uidStateEstimates.size() - 1; i >= 0; i--) {
UidStateEstimate uidStateEstimate = mPlan.uidStateEstimates.get(i);
Intermediates intermediates =
@@ -259,8 +258,7 @@
}
}
- private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats,
- List<Integer> uids) {
+ private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats, IntArray uids) {
for (int i = mPlan.uidStateEstimates.size() - 1; i >= 0; i--) {
UidStateEstimate uidStateEstimate = mPlan.uidStateEstimates.get(i);
Intermediates intermediates =
@@ -276,12 +274,13 @@
int uid = uids.get(k);
if (stats.getUidStats(mTmpUidStatsArray, uid,
proportionalEstimate.stateValues)) {
- double power = intermediates.power
- * mStatsLayout.getUidUsageDuration(mTmpUidStatsArray)
- / intermediates.duration;
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues,
- mTmpUidStatsArray);
+ long duration = mStatsLayout.getUidUsageDuration(mTmpUidStatsArray);
+ if (duration != 0) {
+ double power = intermediates.power * duration / intermediates.duration;
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues,
+ mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
index 4c1a0db..c1cd3ac 100644
--- a/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
@@ -16,12 +16,13 @@
package com.android.server.power.stats.processor;
+import android.util.IntArray;
+
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
import com.android.server.power.stats.UsageBasedPowerEstimator;
import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
-import java.util.ArrayList;
import java.util.List;
class BluetoothPowerStatsProcessor extends PowerStatsProcessor {
@@ -118,18 +119,19 @@
combineDeviceStateEstimates();
- ArrayList<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
- if (!uids.isEmpty()) {
- for (int uid : uids) {
- for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
- computeUidActivityTotals(stats, uid, mPlan.uidStateEstimates.get(i));
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
+ for (int j = 0; j < mPlan.uidStateEstimates.size(); j++) {
+ computeUidActivityTotals(stats, uid, mPlan.uidStateEstimates.get(j));
}
}
- for (int uid : uids) {
- for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
- computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(i));
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
+ for (int j = 0; j < mPlan.uidStateEstimates.size(); j++) {
+ computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(j));
}
}
}
@@ -297,8 +299,10 @@
/ intermediates.txBytes;
}
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
index 17ceca6..98280be 100644
--- a/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.os.BatteryConsumer;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.Log;
import com.android.internal.os.CpuScalingPolicies;
@@ -27,7 +28,6 @@
import com.android.server.power.stats.format.CpuPowerStatsLayout;
import com.android.server.power.stats.format.WakelockPowerStatsLayout;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -119,6 +119,8 @@
mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
mWakelockDescriptor = null;
+
+ initEnergyConsumerToPowerBracketMaps();
}
/**
@@ -157,9 +159,6 @@
if (mPlan == null) {
mPlan = new PowerEstimationPlan(stats.getConfig());
- if (mStatsLayout.getEnergyConsumerCount() != 0) {
- initEnergyConsumerToPowerBracketMaps();
- }
}
Intermediates intermediates = new Intermediates();
@@ -189,12 +188,12 @@
estimatePowerByDeviceState(stats, intermediates, wakelockStats);
combineDeviceStateEstimates();
- ArrayList<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
- if (!uids.isEmpty()) {
- for (int uid : uids) {
- for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
- estimateUidPowerConsumption(stats, uid, mPlan.uidStateEstimates.get(i),
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
+ for (int j = 0; j < mPlan.uidStateEstimates.size(); j++) {
+ estimateUidPowerConsumption(stats, uid, mPlan.uidStateEstimates.get(j),
wakelockStats);
}
}
@@ -255,6 +254,10 @@
*/
private void initEnergyConsumerToPowerBracketMaps() {
int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
+ if (energyConsumerCount == 0) {
+ return;
+ }
+
int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
mEnergyConsumerToCombinedEnergyConsumerMap = new int[energyConsumerCount];
@@ -404,7 +407,10 @@
deviceStatsIntermediates.timeByBracket = new long[powerBracketCount];
deviceStatsIntermediates.powerByBracket = new double[powerBracketCount];
- stats.getDeviceStats(mTmpDeviceStatsArray, deviceStateEstimation.stateValues);
+ if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStateEstimation.stateValues)) {
+ continue;
+ }
+
for (int step = 0; step < cpuScalingStepCount; step++) {
if (intermediates.timeByScalingStep[step] == 0) {
continue;
@@ -429,16 +435,19 @@
}
if (wakelockStats != null) {
- wakelockStats.getDeviceStats(mTmpWakelockDeviceStats,
- deviceStateEstimation.stateValues);
- double wakelockPowerEstimate = mWakelockPowerStatsLayout.getDevicePowerEstimate(
- mTmpWakelockDeviceStats);
- power = Math.max(0, power - wakelockPowerEstimate);
+ if (wakelockStats.getDeviceStats(mTmpWakelockDeviceStats,
+ deviceStateEstimation.stateValues)) {
+ double wakelockPowerEstimate = mWakelockPowerStatsLayout.getDevicePowerEstimate(
+ mTmpWakelockDeviceStats);
+ power = Math.max(0, power - wakelockPowerEstimate);
+ }
}
- deviceStatsIntermediates.power = power;
- mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, power);
- stats.setDeviceStats(deviceStateEstimation.stateValues, mTmpDeviceStatsArray);
+ if (power != 0) {
+ deviceStatsIntermediates.power = power;
+ mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, power);
+ stats.setDeviceStats(deviceStateEstimation.stateValues, mTmpDeviceStatsArray);
+ }
}
}
@@ -538,15 +547,18 @@
}
if (wakelockStats != null) {
- wakelockStats.getUidStats(mTmpWakelockUidStats, uid,
- proportionalEstimate.stateValues);
- double wakelockPowerEstimate = mWakelockPowerStatsLayout.getUidPowerEstimate(
- mTmpWakelockUidStats);
- power = Math.max(0, power - wakelockPowerEstimate);
+ if (wakelockStats.getUidStats(mTmpWakelockUidStats, uid,
+ proportionalEstimate.stateValues)) {
+ double wakelockPowerEstimate = mWakelockPowerStatsLayout.getUidPowerEstimate(
+ mTmpWakelockUidStats);
+ power = Math.max(0, power - wakelockPowerEstimate);
+ }
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
index 76adc47..76ea7e8 100644
--- a/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
@@ -16,10 +16,11 @@
package com.android.server.power.stats.processor;
+import android.util.IntArray;
+
import com.android.internal.os.PowerStats;
import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
-import java.util.ArrayList;
import java.util.List;
class CustomEnergyConsumerPowerStatsProcessor extends PowerStatsProcessor {
@@ -40,10 +41,8 @@
computeDevicePowerEstimates(stats);
- List<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
-
- if (!uids.isEmpty()) {
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
computeUidPowerEstimates(stats, uids);
}
}
@@ -62,7 +61,7 @@
}
private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats,
- List<Integer> uids) {
+ IntArray uids) {
for (int i = mPlan.uidStateEstimates.size() - 1; i >= 0; i--) {
UidStateEstimate uidStateEstimate = mPlan.uidStateEstimates.get(i);
List<UidStateProportionalEstimate> proportionalEstimates =
@@ -73,9 +72,12 @@
int uid = uids.get(k);
if (stats.getUidStats(mTmpUidStatsArray, uid,
proportionalEstimate.stateValues)) {
- sLayout.setUidPowerEstimate(mTmpUidStatsArray,
- uCtoMah(sLayout.getUidConsumedEnergy(mTmpUidStatsArray, 0)));
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ double power = uCtoMah(sLayout.getUidConsumedEnergy(mTmpUidStatsArray, 0));
+ if (power != 0) {
+ sLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues,
+ mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
index b4c40de8..58835053 100644
--- a/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
@@ -19,6 +19,7 @@
import android.telephony.CellSignalStrength;
import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
+import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -29,7 +30,6 @@
import com.android.server.power.stats.UsageBasedPowerEstimator;
import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -198,18 +198,19 @@
combineDeviceStateEstimates();
- ArrayList<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
- if (!uids.isEmpty()) {
- for (int uid : uids) {
- for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
- computeUidRxTxTotals(stats, uid, mPlan.uidStateEstimates.get(i));
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
+ for (int j = 0; j < mPlan.uidStateEstimates.size(); j++) {
+ computeUidRxTxTotals(stats, uid, mPlan.uidStateEstimates.get(j));
}
}
- for (int uid : uids) {
- for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
- computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(i));
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
+ for (int j = 0; j < mPlan.uidStateEstimates.size(); j++) {
+ computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(j));
}
}
}
@@ -258,7 +259,9 @@
stats.forEachStateStatsKey(key -> {
RxTxPowerEstimators estimators = mRxTxPowerEstimators.get(key);
- stats.getStateStats(mTmpStateStatsArray, key, deviceStates);
+ if (!stats.getStateStats(mTmpStateStatsArray, key, deviceStates)) {
+ return;
+ }
long rxTime = mStatsLayout.getStateRxTime(mTmpStateStatsArray);
intermediates.rxPower += estimators.mRxPowerEstimator.calculatePower(rxTime);
for (int txLevel = 0; txLevel < ModemActivityInfo.getNumTxPowerLevels(); txLevel++) {
@@ -382,8 +385,10 @@
/ intermediates.txPackets;
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
if (DEBUG) {
Slog.d(TAG, "UID: " + uid
diff --git a/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
index 28474a5..0038943 100644
--- a/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
@@ -16,6 +16,8 @@
package com.android.server.power.stats.processor;
+import android.annotation.CheckResult;
+import android.annotation.Nullable;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -333,18 +335,20 @@
/**
* Adds the delta to the metrics. The number of values must correspond to the dimension count
- * supplied to the Factory constructor
+ * supplied to the Factory constructor. Null values is equivalent to an array of zeros.
*/
- void increment(long[] values, long timestampMs) {
+ void increment(@Nullable long[] values, long timestampMs) {
mCounter.incrementValues(values, timestampMs);
mTracking = true;
}
/**
- * Returns accumulated stats for the specified composite state.
+ * Returns accumulated stats for the specified composite state or false if the results are
+ * all zeros.
*/
- void getStats(long[] outValues, int[] states) {
- mCounter.getCounts(outValues, mFactory.getSerialState(states));
+ @CheckResult
+ boolean getStats(long[] outValues, int[] states) {
+ return mCounter.getCounts(outValues, mFactory.getSerialState(states));
}
/**
@@ -388,15 +392,7 @@
private void writeXmlForStates(TypedXmlSerializer serializer, int[] states, long[] values)
throws IOException {
- mCounter.getCounts(values, mFactory.getSerialState(states));
- boolean nonZero = false;
- for (long value : values) {
- if (value != 0) {
- nonZero = true;
- break;
- }
- }
- if (!nonZero) {
+ if (!mCounter.getCounts(values, mFactory.getSerialState(states))) {
return;
}
@@ -469,15 +465,7 @@
StringBuilder sb = new StringBuilder();
long[] values = new long[mCounter.getArrayLength()];
States.forEachTrackedStateCombination(mFactory.mStates, states -> {
- mCounter.getCounts(values, mFactory.getSerialState(states));
- boolean nonZero = false;
- for (long value : values) {
- if (value != 0) {
- nonZero = true;
- break;
- }
- }
- if (!nonZero) {
+ if (!mCounter.getCounts(values, mFactory.getSerialState(states))) {
return;
}
diff --git a/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
index 3957ae0..ad628e4 100644
--- a/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
@@ -69,12 +69,15 @@
// processor. All that remains to be done is copy the estimates over.
MultiStateStats.States.forEachTrackedStateCombination(deviceStateConfig,
states -> {
- mobileRadioStats.getDeviceStats(mTmpMobileRadioDeviceStats, states);
- double callPowerEstimate =
- mMobileRadioStatsLayout.getDeviceCallPowerEstimate(
- mTmpMobileRadioDeviceStats);
- mStatsLayout.setDevicePowerEstimate(mTmpDeviceStats, callPowerEstimate);
- stats.setDeviceStats(states, mTmpDeviceStats);
+ if (!mobileRadioStats.getDeviceStats(mTmpMobileRadioDeviceStats, states)) {
+ return;
+ }
+ double callPowerEstimate = mMobileRadioStatsLayout.getDeviceCallPowerEstimate(
+ mTmpMobileRadioDeviceStats);
+ if (callPowerEstimate != 0) {
+ mStatsLayout.setDevicePowerEstimate(mTmpDeviceStats, callPowerEstimate);
+ stats.setDeviceStats(states, mTmpDeviceStats);
+ }
});
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
index d4f8fd9..d285a59 100644
--- a/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
@@ -16,11 +16,13 @@
package com.android.server.power.stats.processor;
+import android.annotation.CheckResult;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.BatteryStats;
import android.os.UserHandle;
import android.util.IndentingPrintWriter;
+import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -34,7 +36,6 @@
import java.io.IOException;
import java.io.StringWriter;
import java.util.Arrays;
-import java.util.Collection;
import java.util.function.IntConsumer;
/**
@@ -72,11 +73,11 @@
private MultiStateStats mDeviceStats;
private final SparseArray<MultiStateStats> mStateStats = new SparseArray<>();
private final SparseArray<UidStats> mUidStats = new SparseArray<>();
- private long[] mZeroArray;
private static class UidStats {
public int[] states;
public MultiStateStats stats;
+ public boolean hasPowerStats;
public boolean updated;
}
@@ -200,6 +201,7 @@
if (uidStats.stats == null) {
createUidStats(uidStats, mPowerStatsTimestamp);
}
+ uidStats.hasPowerStats = true;
uidStats.stats.setStats(states, values);
}
@@ -240,6 +242,7 @@
}
uidStats.stats.increment(powerStats.uidStats.valueAt(i), timestampMs);
uidStats.updated = true;
+ uidStats.hasPowerStats = true;
}
// For UIDs not mentioned in the PowerStats object, we must assume a 0 increment.
@@ -248,11 +251,8 @@
for (int i = mUidStats.size() - 1; i >= 0; i--) {
PowerComponentAggregatedPowerStats.UidStats uidStats = mUidStats.valueAt(i);
if (!uidStats.updated && uidStats.stats != null) {
- if (mZeroArray == null
- || mZeroArray.length != mPowerStatsDescriptor.uidStatsArrayLength) {
- mZeroArray = new long[mPowerStatsDescriptor.uidStatsArrayLength];
- }
- uidStats.stats.increment(mZeroArray, timestampMs);
+ // Null stands for an array of zeros
+ uidStats.stats.increment(null, timestampMs);
}
uidStats.updated = false;
}
@@ -267,6 +267,7 @@
mStateStats.clear();
for (int i = mUidStats.size() - 1; i >= 0; i--) {
mUidStats.valueAt(i).stats = null;
+ mUidStats.valueAt(i).hasPowerStats = false;
}
}
@@ -290,14 +291,33 @@
return uidStats;
}
- void collectUids(Collection<Integer> uids) {
+ IntArray getUids() {
+ IntArray uids = new IntArray(mUidStats.size());
for (int i = mUidStats.size() - 1; i >= 0; i--) {
- if (mUidStats.valueAt(i).stats != null) {
+ UidStats uidStats = mUidStats.valueAt(i);
+ if (uidStats.stats != null) {
uids.add(mUidStats.keyAt(i));
}
}
+ return uids;
}
+ IntArray getActiveUids() {
+ IntArray uids = new IntArray(mUidStats.size());
+ for (int i = mUidStats.size() - 1; i >= 0; i--) {
+ UidStats uidStats = mUidStats.valueAt(i);
+ if (uidStats.hasPowerStats) {
+ uids.add(mUidStats.keyAt(i));
+ }
+ }
+ return uids;
+ }
+
+ /**
+ * Populates outValues with the stats for the specified states. If the stats are all 0,
+ * returns false, leaving outValues unchanged.
+ */
+ @CheckResult
boolean getDeviceStats(long[] outValues, int[] deviceStates) {
if (deviceStates.length != mDeviceStateConfig.length) {
throw new IllegalArgumentException(
@@ -305,12 +325,16 @@
+ " expected: " + mDeviceStateConfig.length);
}
if (mDeviceStats != null) {
- mDeviceStats.getStats(outValues, deviceStates);
- return true;
+ return mDeviceStats.getStats(outValues, deviceStates);
}
return false;
}
+ /**
+ * Populates outValues with the stats for the specified key and device states. If the stats
+ * are all 0, returns false, leaving outValues unchanged.
+ */
+ @CheckResult
boolean getStateStats(long[] outValues, int key, int[] deviceStates) {
if (deviceStates.length != mDeviceStateConfig.length) {
throw new IllegalArgumentException(
@@ -319,8 +343,7 @@
}
MultiStateStats stateStats = mStateStats.get(key);
if (stateStats != null) {
- stateStats.getStats(outValues, deviceStates);
- return true;
+ return stateStats.getStats(outValues, deviceStates);
}
return false;
}
@@ -331,6 +354,11 @@
}
}
+ /**
+ * Populates outValues with the stats for the specified UID and UID states. If the stats are
+ * all 0, returns false, leaving outValues unchanged.
+ */
+ @CheckResult
boolean getUidStats(long[] outValues, int uid, int[] uidStates) {
if (uidStates.length != mUidStateConfig.length) {
throw new IllegalArgumentException(
@@ -339,8 +367,7 @@
}
UidStats uidStats = mUidStats.get(uid);
if (uidStats != null && uidStats.stats != null) {
- uidStats.stats.getStats(outValues, uidStates);
- return true;
+ return uidStats.stats.getStats(outValues, uidStates);
}
return false;
}
@@ -516,6 +543,7 @@
if (uidStats.stats == null) {
createUidStats(uidStats, UNKNOWN);
}
+ uidStats.hasPowerStats = true;
if (!uidStats.stats.readFromXml(parser)) {
return false;
}
@@ -563,15 +591,7 @@
long[] values = new long[stats.getDimensionCount()];
MultiStateStats.States[] stateInfo = stats.getStates();
MultiStateStats.States.forEachTrackedStateCombination(stateInfo, states -> {
- stats.getStats(values, states);
- boolean nonZero = false;
- for (long value : values) {
- if (value != 0) {
- nonZero = true;
- break;
- }
- }
- if (!nonZero) {
+ if (!stats.getStats(values, states)) {
return;
}
diff --git a/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
index 177d129..634415e 100644
--- a/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
@@ -21,6 +21,7 @@
import android.os.BatteryConsumer;
import android.os.BatteryUsageStats;
import android.os.UidBatteryConsumer;
+import android.util.IntArray;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -31,7 +32,6 @@
import com.android.server.power.stats.format.BasePowerStatsLayout;
import com.android.server.power.stats.format.PowerStatsLayout;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -180,8 +180,7 @@
}
}
if (layout.isUidPowerAttributionSupported()) {
- populateBatteryConsumers(batteryUsageStatsBuilder,
- powerComponentStats, layout);
+ populateBatteryConsumers(batteryUsageStatsBuilder, powerComponentStats, layout);
}
populateBatteryLevelInfo(batteryUsageStatsBuilder, batteryLevelInfo);
@@ -258,6 +257,11 @@
BatteryUsageStats.Builder batteryUsageStatsBuilder,
PowerComponentAggregatedPowerStats powerComponentStats,
PowerStatsLayout layout) {
+ IntArray uids = powerComponentStats.getUids();
+ if (uids.size() == 0) {
+ return;
+ }
+
AggregatedPowerStatsConfig.PowerComponent powerComponent = powerComponentStats.getConfig();
PowerStats.Descriptor descriptor = powerComponentStats.getPowerStatsDescriptor();
long[] uidStats = new long[descriptor.uidStatsArrayLength];
@@ -273,8 +277,6 @@
breakDownByProcState = false;
}
- ArrayList<Integer> uids = new ArrayList<>();
- powerComponentStats.collectUids(uids);
for (int screenState = 0; screenState < BatteryConsumer.SCREEN_STATE_COUNT; screenState++) {
if (batteryUsageStatsBuilder.isScreenStateDataNeeded()) {
if (screenState == BatteryConsumer.SCREEN_STATE_UNSPECIFIED) {
@@ -303,7 +305,7 @@
private void populateUidBatteryConsumers(
BatteryUsageStats.Builder batteryUsageStatsBuilder,
PowerComponentAggregatedPowerStats powerComponentStats, PowerStatsLayout layout,
- List<Integer> uids, AggregatedPowerStatsConfig.PowerComponent powerComponent,
+ IntArray uids, AggregatedPowerStatsConfig.PowerComponent powerComponent,
long[] uidStats, boolean breakDownByProcState,
@BatteryConsumer.ScreenState int screenState,
@BatteryConsumer.PowerState int powerState) {
@@ -319,7 +321,8 @@
long[] durationByProcState =
new long[breakDownByProcState ? BatteryConsumer.PROCESS_STATE_COUNT : 1];
double powerAllApps = 0;
- for (int uid : uids) {
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
UidBatteryConsumer.Builder builder =
batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(uid);
diff --git a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
index 8e7498f..9df3d7e 100644
--- a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
@@ -27,6 +27,7 @@
import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import android.os.BatteryStats;
+import android.util.IntArray;
import android.util.Slog;
import com.android.internal.os.PowerProfile;
@@ -34,7 +35,6 @@
import com.android.server.power.stats.UsageBasedPowerEstimator;
import com.android.server.power.stats.format.ScreenPowerStatsLayout;
-import java.util.ArrayList;
import java.util.List;
class ScreenPowerStatsProcessor extends PowerStatsProcessor {
@@ -116,10 +116,8 @@
computeDevicePowerEstimates(stats);
combineDeviceStateEstimates();
- List<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
-
- if (!uids.isEmpty()) {
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
computeUidPowerEstimates(stats, uids);
}
mPlan.resetIntermediates();
@@ -197,7 +195,7 @@
}
private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats,
- List<Integer> uids) {
+ IntArray uids) {
int[] uidStateValues = new int[stats.getConfig().getUidStateConfig().length];
uidStateValues[STATE_SCREEN] = SCREEN_STATE_ON;
uidStateValues[STATE_PROCESS_STATE] = PROCESS_STATE_UNSPECIFIED;
@@ -232,9 +230,11 @@
int uid = uids.get(j);
if (stats.getUidStats(mTmpUidStatsArray, uid, uidStateValues)) {
long duration = mStatsLayout.getUidTopActivityDuration(mTmpUidStatsArray);
- double power = intermediates.power * duration / totalTopActivityDuration;
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, uidStateValues, mTmpUidStatsArray);
+ if (duration != 0) {
+ double power = intermediates.power * duration / totalTopActivityDuration;
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, uidStateValues, mTmpUidStatsArray);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
index 0bb028b..284e6a9 100644
--- a/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
@@ -21,6 +21,7 @@
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.PersistableBundle;
+import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -28,7 +29,6 @@
import com.android.server.power.stats.format.PowerStatsLayout;
import com.android.server.power.stats.format.SensorPowerStatsLayout;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
@@ -207,11 +207,11 @@
mPlan = new PowerEstimationPlan(stats.getConfig());
}
- List<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
-
- computeUidPowerEstimates(stats, uids);
- computeDevicePowerEstimates(stats);
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
+ computeUidPowerEstimates(stats, uids);
+ computeDevicePowerEstimates(stats);
+ }
mPlan.resetIntermediates();
}
@@ -239,9 +239,7 @@
mLastUpdateTimestamp = timestamp;
}
- private void computeUidPowerEstimates(
- PowerComponentAggregatedPowerStats stats,
- List<Integer> uids) {
+ private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats, IntArray uids) {
List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
int[] uidSensorDurationPositions = new int[sensorList.size()];
double[] sensorPower = new double[sensorList.size()];
@@ -292,8 +290,7 @@
}
}
- private void computeDevicePowerEstimates(
- PowerComponentAggregatedPowerStats stats) {
+ private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats) {
for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
CombinedDeviceStateEstimate estimation =
mPlan.combinedDeviceStateEstimations.get(i);
@@ -301,12 +298,16 @@
continue;
}
- if (!stats.getDeviceStats(mTmpDeviceStatsArray, estimation.stateValues)) {
+ double power = ((Intermediates) estimation.intermediates).power;
+ if (power == 0) {
continue;
}
- mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray,
- ((Intermediates) estimation.intermediates).power);
+ if (!stats.getDeviceStats(mTmpDeviceStatsArray, estimation.stateValues)) {
+ Arrays.fill(mTmpDeviceStatsArray, 0);
+ }
+
+ mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, power);
stats.setDeviceStats(estimation.stateValues, mTmpDeviceStatsArray);
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
index 0df01cf..8cc0b6e 100644
--- a/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
@@ -16,6 +16,7 @@
package com.android.server.power.stats.processor;
+import android.util.IntArray;
import android.util.Slog;
import com.android.internal.os.PowerProfile;
@@ -23,7 +24,6 @@
import com.android.server.power.stats.UsageBasedPowerEstimator;
import com.android.server.power.stats.format.WifiPowerStatsLayout;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -148,18 +148,19 @@
combineDeviceStateEstimates();
- ArrayList<Integer> uids = new ArrayList<>();
- stats.collectUids(uids);
- if (!uids.isEmpty()) {
- for (int uid : uids) {
- for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
- computeUidActivityTotals(stats, uid, mPlan.uidStateEstimates.get(i));
+ IntArray uids = stats.getActiveUids();
+ if (uids.size() != 0) {
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
+ for (int j = 0; j < mPlan.uidStateEstimates.size(); j++) {
+ computeUidActivityTotals(stats, uid, mPlan.uidStateEstimates.get(j));
}
}
- for (int uid : uids) {
- for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
- computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(i));
+ for (int i = uids.size() - 1; i >= 0; i--) {
+ int uid = uids.get(i);
+ for (int j = 0; j < mPlan.uidStateEstimates.size(); j++) {
+ computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(j));
}
}
}
@@ -374,8 +375,10 @@
/ intermediates.batchedScanDuration;
}
}
- mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
- stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ if (power != 0) {
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+ }
if (DEBUG) {
Slog.d(TAG, "UID: " + uid
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index ab756f2..5347ca4 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -29,7 +29,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
-import android.content.pm.Flags;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
@@ -965,9 +964,7 @@
ipw.println("-stateDescription: " + mStateDescription);
ipw.println("-timestamp: " + getTimestamp());
ipw.println("-rollbackLifetimeMillis: " + getRollbackLifetimeMillis());
- if (Flags.recoverabilityDetection()) {
- ipw.println("-rollbackImpactLevel: " + info.getRollbackImpactLevel());
- }
+ ipw.println("-rollbackImpactLevel: " + info.getRollbackImpactLevel());
ipw.println("-isStaged: " + isStaged());
ipw.println("-originalSessionId: " + getOriginalSessionId());
ipw.println("-packages:");
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 2e6be5b..9ed52d8 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1244,17 +1244,12 @@
rollback.makeAvailable();
mPackageHealthObserver.notifyRollbackAvailable(rollback.info);
- if (Flags.recoverabilityDetection()) {
- if (rollback.info.getRollbackImpactLevel() == PackageManager.ROLLBACK_USER_IMPACT_LOW) {
- // TODO(zezeozue): Provide API to explicitly start observing instead
- // of doing this for all rollbacks. If we do this for all rollbacks,
- // should document in PackageInstaller.SessionParams#setEnableRollback
- // After enabling and committing any rollback, observe packages and
- // prepare to rollback if packages crashes too frequently.
- mPackageWatchdog.startExplicitHealthCheck(rollback.getPackageNames(),
- mRollbackLifetimeDurationInMillis, mPackageHealthObserver);
- }
- } else {
+ if (rollback.info.getRollbackImpactLevel() == PackageManager.ROLLBACK_USER_IMPACT_LOW) {
+ // TODO(zezeozue): Provide API to explicitly start observing instead
+ // of doing this for all rollbacks. If we do this for all rollbacks,
+ // should document in PackageInstaller.SessionParams#setEnableRollback
+ // After enabling and committing any rollback, observe packages and
+ // prepare to rollback if packages crashes too frequently.
mPackageWatchdog.startExplicitHealthCheck(rollback.getPackageNames(),
mRollbackLifetimeDurationInMillis, mPackageHealthObserver);
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 50db1e4..6dc4032 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -197,9 +197,7 @@
json.put("isStaged", rollback.isStaged());
json.put("causePackages", versionedPackagesToJson(rollback.getCausePackages()));
json.put("committedSessionId", rollback.getCommittedSessionId());
- if (Flags.recoverabilityDetection()) {
- json.put("rollbackImpactLevel", rollback.getRollbackImpactLevel());
- }
+ json.put("rollbackImpactLevel", rollback.getRollbackImpactLevel());
return json;
}
@@ -211,11 +209,9 @@
versionedPackagesFromJson(json.getJSONArray("causePackages")),
json.getInt("committedSessionId"));
- if (Flags.recoverabilityDetection()) {
- // to make it backward compatible.
- rollbackInfo.setRollbackImpactLevel(json.optInt("rollbackImpactLevel",
- PackageManager.ROLLBACK_USER_IMPACT_LOW));
- }
+ // to make it backward compatible.
+ rollbackInfo.setRollbackImpactLevel(json.optInt("rollbackImpactLevel",
+ PackageManager.ROLLBACK_USER_IMPACT_LOW));
return rollbackInfo;
}
diff --git a/services/core/java/com/android/server/storage/ImmutableVolumeInfo.java b/services/core/java/com/android/server/storage/ImmutableVolumeInfo.java
index 9d60a57..0f8212e 100644
--- a/services/core/java/com/android/server/storage/ImmutableVolumeInfo.java
+++ b/services/core/java/com/android/server/storage/ImmutableVolumeInfo.java
@@ -136,4 +136,9 @@
public boolean isVisibleForWrite(int userId) {
return mVolumeInfo.isVisibleForWrite(userId);
}
+
+ @Override
+ public String toString() {
+ return mVolumeInfo.toString();
+ }
}
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 342b864..281aeb6 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -156,14 +156,15 @@
StorageUserConnection connection = null;
synchronized (mLock) {
connection = mConnections.get(connectionUserId);
- if (connection != null) {
- Slog.i(TAG, "Notifying volume state changed for session with id: " + sessionId);
- connection.notifyVolumeStateChanged(sessionId,
- vol.buildStorageVolume(mContext, vol.getMountUserId(), false));
- } else {
- Slog.w(TAG, "No available storage user connection for userId : "
- + connectionUserId);
- }
+ }
+
+ if (connection != null) {
+ Slog.i(TAG, "Notifying volume state changed for session with id: " + sessionId);
+ connection.notifyVolumeStateChanged(sessionId,
+ vol.buildStorageVolume(mContext, vol.getMountUserId(), false));
+ } else {
+ Slog.w(TAG, "No available storage user connection for userId : "
+ + connectionUserId);
}
}
@@ -225,16 +226,18 @@
String sessionId = vol.getId();
int userId = getConnectionUserIdForVolume(vol);
+ StorageUserConnection connection = null;
synchronized (mLock) {
- StorageUserConnection connection = mConnections.get(userId);
- if (connection != null) {
- Slog.i(TAG, "Removed session for vol with id: " + sessionId);
- connection.removeSession(sessionId);
- return connection;
- } else {
- Slog.w(TAG, "Session already removed for vol with id: " + sessionId);
- return null;
- }
+ connection = mConnections.get(userId);
+ }
+
+ if (connection != null) {
+ Slog.i(TAG, "Removed session for vol with id: " + sessionId);
+ connection.removeSession(sessionId);
+ return connection;
+ } else {
+ Slog.w(TAG, "Session already removed for vol with id: " + sessionId);
+ return null;
}
}
diff --git a/services/core/java/com/android/server/storage/WatchedVolumeInfo.java b/services/core/java/com/android/server/storage/WatchedVolumeInfo.java
index 4124cfb..94e52cd 100644
--- a/services/core/java/com/android/server/storage/WatchedVolumeInfo.java
+++ b/services/core/java/com/android/server/storage/WatchedVolumeInfo.java
@@ -203,4 +203,9 @@
public boolean isVisibleForWrite(int userId) {
return mVolumeInfo.isVisibleForWrite(userId);
}
+
+ @Override
+ public String toString() {
+ return mVolumeInfo.toString();
+ }
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java b/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java
index 07d9ad1..da6478b 100644
--- a/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/AbstractVibratorStep.java
@@ -124,6 +124,8 @@
Slog.d(VibrationThread.TAG,
"Turning off vibrator " + getVibratorId());
}
+ // Make sure we ignore any pending callback from old vibration commands.
+ conductor.nextVibratorCallbackStepId(getVibratorId());
controller.off();
getVibration().stats.reportVibratorOff();
mPendingVibratorOffDeadline = 0;
diff --git a/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java b/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java
index e495af5..b3eead1 100644
--- a/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/ComposePrimitivesVibratorStep.java
@@ -73,7 +73,8 @@
PrimitiveSegment[] primitivesArray =
primitives.toArray(new PrimitiveSegment[primitives.size()]);
- long vibratorOnResult = controller.on(primitivesArray, getVibration().id);
+ int stepId = conductor.nextVibratorCallbackStepId(getVibratorId());
+ long vibratorOnResult = controller.on(primitivesArray, getVibration().id, stepId);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats.reportComposePrimitives(vibratorOnResult, primitivesArray);
diff --git a/services/core/java/com/android/server/vibrator/ComposePwleV2VibratorStep.java b/services/core/java/com/android/server/vibrator/ComposePwleV2VibratorStep.java
index bb8e6ee..7b41457 100644
--- a/services/core/java/com/android/server/vibrator/ComposePwleV2VibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/ComposePwleV2VibratorStep.java
@@ -72,7 +72,8 @@
+ controller.getVibratorInfo().getId());
}
PwlePoint[] pwlesArray = pwles.toArray(new PwlePoint[pwles.size()]);
- long vibratorOnResult = controller.on(pwlesArray, getVibration().id);
+ int stepId = conductor.nextVibratorCallbackStepId(getVibratorId());
+ long vibratorOnResult = controller.on(pwlesArray, getVibration().id, stepId);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats.reportComposePwle(vibratorOnResult, pwlesArray);
diff --git a/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java b/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
index e8952fa..d003251 100644
--- a/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
@@ -71,7 +71,8 @@
+ controller.getVibratorInfo().getId());
}
RampSegment[] pwlesArray = pwles.toArray(new RampSegment[pwles.size()]);
- long vibratorOnResult = controller.on(pwlesArray, getVibration().id);
+ int stepId = conductor.nextVibratorCallbackStepId(getVibratorId());
+ long vibratorOnResult = controller.on(pwlesArray, getVibration().id, stepId);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats.reportComposePwle(vibratorOnResult, pwlesArray);
diff --git a/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java b/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java
index a92ac67..b2cc1f6 100644
--- a/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java
+++ b/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java
@@ -148,7 +148,7 @@
}
@Override
- public void notifyVibratorCallback(int vibratorId, long vibrationId) {
+ public void notifyVibratorCallback(int vibratorId, long vibrationId, long stepId) {
// ignored, external control does not expect callbacks from the vibrator
}
diff --git a/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java b/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java
index 4b23216..88bb181 100644
--- a/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/PerformPrebakedVibratorStep.java
@@ -64,7 +64,8 @@
}
VibrationEffect fallback = getVibration().getFallback(prebaked.getEffectId());
- long vibratorOnResult = controller.on(prebaked, getVibration().id);
+ int stepId = conductor.nextVibratorCallbackStepId(getVibratorId());
+ long vibratorOnResult = controller.on(prebaked, getVibration().id, stepId);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats.reportPerformEffect(vibratorOnResult, prebaked);
diff --git a/services/core/java/com/android/server/vibrator/PerformVendorEffectVibratorStep.java b/services/core/java/com/android/server/vibrator/PerformVendorEffectVibratorStep.java
index 407f3d9..d4bcc36 100644
--- a/services/core/java/com/android/server/vibrator/PerformVendorEffectVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/PerformVendorEffectVibratorStep.java
@@ -49,7 +49,8 @@
public List<Step> play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "PerformVendorEffectVibratorStep");
try {
- long vibratorOnResult = controller.on(effect, getVibration().id);
+ int stepId = conductor.nextVibratorCallbackStepId(getVibratorId());
+ long vibratorOnResult = controller.on(effect, getVibration().id, stepId);
vibratorOnResult = Math.min(vibratorOnResult, VENDOR_EFFECT_MAX_DURATION_MS);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats.reportPerformVendorEffect(vibratorOnResult);
diff --git a/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java b/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java
index 8478e77..26b9595 100644
--- a/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/SetAmplitudeVibratorStep.java
@@ -20,6 +20,7 @@
import android.os.SystemClock;
import android.os.Trace;
import android.os.VibrationEffect;
+import android.os.vibrator.Flags;
import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationEffectSegment;
import android.util.Slog;
@@ -49,6 +50,10 @@
@Override
public boolean acceptVibratorCompleteCallback(int vibratorId) {
+ if (Flags.fixVibrationThreadCallbackHandling()) {
+ // TODO: remove this method once flag removed.
+ return super.acceptVibratorCompleteCallback(vibratorId);
+ }
// Ensure the super method is called and will reset the off timeout and boolean flag.
// This is true if the vibrator was ON and this callback has the same vibratorId.
if (!super.acceptVibratorCompleteCallback(vibratorId)) {
@@ -161,7 +166,8 @@
"Turning on vibrator " + controller.getVibratorInfo().getId() + " for "
+ duration + "ms");
}
- long vibratorOnResult = controller.on(duration, getVibration().id);
+ int stepId = conductor.nextVibratorCallbackStepId(getVibratorId());
+ long vibratorOnResult = controller.on(duration, getVibration().id, stepId);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats.reportVibratorOn(vibratorOnResult);
return vibratorOnResult;
diff --git a/services/core/java/com/android/server/vibrator/SingleVibrationSession.java b/services/core/java/com/android/server/vibrator/SingleVibrationSession.java
index 628221b..309eb8c 100644
--- a/services/core/java/com/android/server/vibrator/SingleVibrationSession.java
+++ b/services/core/java/com/android/server/vibrator/SingleVibrationSession.java
@@ -137,13 +137,13 @@
}
@Override
- public void notifyVibratorCallback(int vibratorId, long vibrationId) {
+ public void notifyVibratorCallback(int vibratorId, long vibrationId, long stepId) {
if (vibrationId != mVibration.id) {
return;
}
synchronized (mLock) {
if (mConductor != null) {
- mConductor.notifyVibratorComplete(vibratorId);
+ mConductor.notifyVibratorComplete(vibratorId, stepId);
}
}
}
diff --git a/services/core/java/com/android/server/vibrator/VendorVibrationSession.java b/services/core/java/com/android/server/vibrator/VendorVibrationSession.java
index 1b6ce9d..bda3d44 100644
--- a/services/core/java/com/android/server/vibrator/VendorVibrationSession.java
+++ b/services/core/java/com/android/server/vibrator/VendorVibrationSession.java
@@ -176,14 +176,14 @@
@Override
public void onCancel() {
- Slog.d(TAG, "Cancellation signal received, cancelling vibration session...");
+ Slog.d(TAG, "Session cancellation signal received, aborting vibration session...");
requestEndSession(Status.CANCELLED_BY_USER, /* shouldAbort= */ true,
/* isVendorRequest= */ true);
}
@Override
public void binderDied() {
- Slog.d(TAG, "Binder died, cancelling vibration session...");
+ Slog.d(TAG, "Session binder died, aborting vibration session...");
requestEndSession(Status.CANCELLED_BINDER_DIED, /* shouldAbort= */ true,
/* isVendorRequest= */ false);
}
@@ -218,19 +218,21 @@
}
@Override
- public void notifyVibratorCallback(int vibratorId, long vibrationId) {
- // Ignore it, the session vibration playback doesn't depend on HAL timings
+ public void notifyVibratorCallback(int vibratorId, long vibrationId, long stepId) {
+ Slog.d(TAG, "Vibration callback received for vibration " + vibrationId + " step " + stepId
+ + " on vibrator " + vibratorId + ", ignoring...");
}
@Override
public void notifySyncedVibratorsCallback(long vibrationId) {
- // Ignore it, the session vibration playback doesn't depend on HAL timings
+ Slog.d(TAG, "Synced vibration callback received for vibration " + vibrationId
+ + ", ignoring...");
}
@Override
public void notifySessionCallback() {
+ Slog.d(TAG, "Session callback received, ending vibration session...");
synchronized (mLock) {
- Slog.d(TAG, "Session callback received, ending vibration session...");
// If end was not requested then the HAL has cancelled the session.
maybeSetEndRequestLocked(Status.CANCELLED_BY_UNKNOWN_REASON,
/* isVendorRequest= */ false);
@@ -307,7 +309,7 @@
}
}
if (isAlreadyEnded) {
- // Session already ended, make sure we end it in the HAL.
+ Slog.d(TAG, "Session already ended after starting the HAL, aborting...");
mHandler.post(() -> mManagerHooks.endSession(mSessionId, /* shouldAbort= */ true));
}
}
@@ -335,8 +337,8 @@
public boolean maybeSetVibrationConductor(VibrationStepConductor conductor) {
synchronized (mLock) {
if (mConductor != null) {
- Slog.d(TAG, "Vibration session still dispatching previous vibration,"
- + " new vibration ignored");
+ Slog.d(TAG, "Session still dispatching previous vibration, new vibration "
+ + conductor.getVibration().id + " ignored");
return false;
}
mConductor = conductor;
@@ -345,19 +347,22 @@
}
private void requestEndSession(Status status, boolean shouldAbort, boolean isVendorRequest) {
+ Slog.d(TAG, "Session end request received with status " + status);
boolean shouldTriggerSessionHook = false;
synchronized (mLock) {
maybeSetEndRequestLocked(status, isVendorRequest);
- if (isStarted()) {
- // Always trigger session hook after it has started, in case new request aborts an
- // already finishing session. Wait for HAL callback before actually ending here.
+ if (!isEnded() && isStarted()) {
+ // Trigger session hook even if it was already triggered, in case a second request
+ // is aborting the ongoing/ending session. This might cause it to end right away.
+ // Wait for HAL callback before setting the end status.
shouldTriggerSessionHook = true;
} else {
- // Session did not start in the HAL, end it right away.
+ // Session not active in the HAL, set end status right away.
maybeSetStatusToRequestedLocked();
}
}
if (shouldTriggerSessionHook) {
+ Slog.d(TAG, "Requesting HAL session end with abort=" + shouldAbort);
mHandler.post(() -> mManagerHooks.endSession(mSessionId, shouldAbort));
}
}
@@ -368,6 +373,7 @@
// End already requested, keep first requested status and time.
return;
}
+ Slog.d(TAG, "Session end request accepted for status " + status);
mEndStatusRequest = status;
mEndedByVendor = isVendorRequest;
mEndTime = System.currentTimeMillis();
@@ -400,6 +406,7 @@
// No end status was requested, nothing to set.
return;
}
+ Slog.d(TAG, "Session end request applied for status " + mEndStatusRequest);
mStatus = mEndStatusRequest;
// Run client callback in separate thread.
final Status endStatus = mStatus;
@@ -407,7 +414,7 @@
try {
mCallback.onFinished(toSessionStatus(endStatus));
} catch (RemoteException e) {
- Slog.e(TAG, "Error notifying vendor session is finishing", e);
+ Slog.e(TAG, "Error notifying vendor session finished", e);
}
});
}
diff --git a/services/core/java/com/android/server/vibrator/VibrationSession.java b/services/core/java/com/android/server/vibrator/VibrationSession.java
index ae95a70..23715e39 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSession.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSession.java
@@ -106,7 +106,7 @@
* complete (e.g. on(), perform(), compose()). This does not mean the vibration is complete,
* since its playback might have one or more interactions with the vibrator hardware.
*/
- void notifyVibratorCallback(int vibratorId, long vibrationId);
+ void notifyVibratorCallback(int vibratorId, long vibrationId, long stepId);
/**
* Notify all synced vibrators have completed the last synchronized command during the playback
diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
index 1e20deb..36e1322 100644
--- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
+++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
@@ -30,6 +30,7 @@
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.vibrator.VibrationSession.Status;
@@ -93,6 +94,8 @@
private final Object mLock = new Object();
@GuardedBy("mLock")
private final IntArray mSignalVibratorsComplete;
+ @GuardedBy("mLock")
+ private final SparseIntArray mSignalVibratorStepIds;
@Nullable
@GuardedBy("mLock")
private Vibration.EndInfo mSignalCancel = null;
@@ -121,6 +124,8 @@
this.vibratorManagerHooks = vibratorManagerHooks;
this.mSignalVibratorsComplete =
new IntArray(mDeviceAdapter.getAvailableVibratorIds().length);
+ this.mSignalVibratorStepIds =
+ new SparseIntArray(mDeviceAdapter.getAvailableVibratorIds().length);
}
@Nullable
@@ -418,7 +423,7 @@
* <p>This is a lightweight method intended to be called directly via native callbacks.
* The state update is recorded for processing on the main execution thread (VibrationThread).
*/
- public void notifyVibratorComplete(int vibratorId) {
+ public void notifyVibratorComplete(int vibratorId, long stepId) {
// HAL callbacks may be triggered directly within HAL calls, so these notifications
// could be on the VibrationThread as it calls the HAL, or some other executor later.
// Therefore no thread assertion is made here.
@@ -428,6 +433,14 @@
}
synchronized (mLock) {
+ if (Flags.fixVibrationThreadCallbackHandling()
+ && mSignalVibratorStepIds.get(vibratorId) != stepId) {
+ if (DEBUG) {
+ Slog.d(TAG, "Vibrator " + vibratorId + " callback for step=" + stepId
+ + " ignored, current step=" + mSignalVibratorStepIds.get(vibratorId));
+ }
+ return;
+ }
mSignalVibratorsComplete.add(vibratorId);
mLock.notify();
}
@@ -645,6 +658,26 @@
}
}
+ /**
+ * Updates and returns the next step id value to be used in vibrator commands.
+ *
+ * <p>This new step id will be kept by this conductor to filter out old callbacks that might be
+ * triggered too late by the HAL, preventing them from affecting the ongoing vibration playback.
+ */
+ public int nextVibratorCallbackStepId(int vibratorId) {
+ if (!Flags.fixVibrationThreadCallbackHandling()) {
+ return 0;
+ }
+ if (Build.IS_DEBUGGABLE) {
+ expectIsVibrationThread(true);
+ }
+ synchronized (mLock) {
+ int stepId = mSignalVibratorStepIds.get(vibratorId) + 1;
+ mSignalVibratorStepIds.put(vibratorId, stepId);
+ return stepId;
+ }
+ }
+
private static CombinedVibration.Sequential toSequential(CombinedVibration effect) {
if (effect instanceof CombinedVibration.Sequential) {
return (CombinedVibration.Sequential) effect;
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index acb31ce..ab13b0e 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -72,7 +72,7 @@
public interface OnVibrationCompleteListener {
/** Callback triggered when an active vibration command is complete. */
- void onComplete(int vibratorId, long vibrationId);
+ void onComplete(int vibratorId, long vibrationId, long stepId);
}
/** Representation of the vibrator state based on the interactions through this controller. */
@@ -285,11 +285,11 @@
* @return The positive duration of the vibration started, if successful, zero if the vibrator
* do not support the input or a negative number if the operation failed.
*/
- public long on(long milliseconds, long vibrationId) {
+ public long on(long milliseconds, long vibrationId, long stepId) {
Trace.traceBegin(TRACE_TAG_VIBRATOR, "VibratorController#on");
try {
synchronized (mLock) {
- long duration = mNativeWrapper.on(milliseconds, vibrationId);
+ long duration = mNativeWrapper.on(milliseconds, vibrationId, stepId);
if (duration > 0) {
mCurrentAmplitude = -1;
updateStateAndNotifyListenersLocked(VibratorState.VIBRATING);
@@ -310,7 +310,7 @@
* @return The positive duration of the vibration started, if successful, zero if the vibrator
* do not support the input or a negative number if the operation failed.
*/
- public long on(VibrationEffect.VendorEffect vendorEffect, long vibrationId) {
+ public long on(VibrationEffect.VendorEffect vendorEffect, long vibrationId, long stepId) {
Trace.traceBegin(TRACE_TAG_VIBRATOR, "VibratorController#on (vendor)");
synchronized (mLock) {
Parcel vendorData = Parcel.obtain();
@@ -319,7 +319,7 @@
vendorData.setDataPosition(0);
long duration = mNativeWrapper.performVendorEffect(vendorData,
vendorEffect.getEffectStrength(), vendorEffect.getScale(),
- vendorEffect.getAdaptiveScale(), vibrationId);
+ vendorEffect.getAdaptiveScale(), vibrationId, stepId);
if (duration > 0) {
mCurrentAmplitude = -1;
updateStateAndNotifyListenersLocked(VibratorState.VIBRATING);
@@ -341,12 +341,12 @@
* @return The positive duration of the vibration started, if successful, zero if the vibrator
* do not support the input or a negative number if the operation failed.
*/
- public long on(PrebakedSegment prebaked, long vibrationId) {
+ public long on(PrebakedSegment prebaked, long vibrationId, long stepId) {
Trace.traceBegin(TRACE_TAG_VIBRATOR, "VibratorController#on (Prebaked)");
try {
synchronized (mLock) {
long duration = mNativeWrapper.perform(prebaked.getEffectId(),
- prebaked.getEffectStrength(), vibrationId);
+ prebaked.getEffectStrength(), vibrationId, stepId);
if (duration > 0) {
mCurrentAmplitude = -1;
updateStateAndNotifyListenersLocked(VibratorState.VIBRATING);
@@ -367,14 +367,14 @@
* @return The positive duration of the vibration started, if successful, zero if the vibrator
* do not support the input or a negative number if the operation failed.
*/
- public long on(PrimitiveSegment[] primitives, long vibrationId) {
+ public long on(PrimitiveSegment[] primitives, long vibrationId, long stepId) {
Trace.traceBegin(TRACE_TAG_VIBRATOR, "VibratorController#on (Primitive)");
try {
if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
return 0;
}
synchronized (mLock) {
- long duration = mNativeWrapper.compose(primitives, vibrationId);
+ long duration = mNativeWrapper.compose(primitives, vibrationId, stepId);
if (duration > 0) {
mCurrentAmplitude = -1;
updateStateAndNotifyListenersLocked(VibratorState.VIBRATING);
@@ -394,7 +394,7 @@
*
* @return The duration of the effect playing, or 0 if unsupported.
*/
- public long on(RampSegment[] primitives, long vibrationId) {
+ public long on(RampSegment[] primitives, long vibrationId, long stepId) {
Trace.traceBegin(TRACE_TAG_VIBRATOR, "VibratorController#on (PWLE)");
try {
if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
@@ -402,7 +402,8 @@
}
synchronized (mLock) {
int braking = mVibratorInfo.getDefaultBraking();
- long duration = mNativeWrapper.composePwle(primitives, braking, vibrationId);
+ long duration = mNativeWrapper.composePwle(
+ primitives, braking, vibrationId, stepId);
if (duration > 0) {
mCurrentAmplitude = -1;
updateStateAndNotifyListenersLocked(VibratorState.VIBRATING);
@@ -422,14 +423,14 @@
*
* @return The duration of the effect playing, or 0 if unsupported.
*/
- public long on(PwlePoint[] pwlePoints, long vibrationId) {
+ public long on(PwlePoint[] pwlePoints, long vibrationId, long stepId) {
Trace.traceBegin(TRACE_TAG_VIBRATOR, "VibratorController#on (PWLE v2)");
try {
if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2)) {
return 0;
}
synchronized (mLock) {
- long duration = mNativeWrapper.composePwleV2(pwlePoints, vibrationId);
+ long duration = mNativeWrapper.composePwleV2(pwlePoints, vibrationId, stepId);
if (duration > 0) {
mCurrentAmplitude = -1;
updateStateAndNotifyListenersLocked(VibratorState.VIBRATING);
@@ -544,26 +545,27 @@
private static native boolean isAvailable(long nativePtr);
- private static native long on(long nativePtr, long milliseconds, long vibrationId);
+ private static native long on(long nativePtr, long milliseconds, long vibrationId,
+ long stepId);
private static native void off(long nativePtr);
private static native void setAmplitude(long nativePtr, float amplitude);
private static native long performEffect(long nativePtr, long effect, long strength,
- long vibrationId);
+ long vibrationId, long stepId);
private static native long performVendorEffect(long nativePtr, Parcel vendorData,
- long strength, float scale, float adaptiveScale, long vibrationId);
+ long strength, float scale, float adaptiveScale, long vibrationId, long stepId);
private static native long performComposedEffect(long nativePtr, PrimitiveSegment[] effect,
- long vibrationId);
+ long vibrationId, long stepId);
private static native long performPwleEffect(long nativePtr, RampSegment[] effect,
- int braking, long vibrationId);
+ int braking, long vibrationId, long stepId);
private static native long performPwleV2Effect(long nativePtr, PwlePoint[] effect,
- long vibrationId);
+ long vibrationId, long stepId);
private static native void setExternalControl(long nativePtr, boolean enabled);
@@ -595,8 +597,8 @@
}
/** Turns vibrator on for given time. */
- public long on(long milliseconds, long vibrationId) {
- return on(mNativePtr, milliseconds, vibrationId);
+ public long on(long milliseconds, long vibrationId, long stepId) {
+ return on(mNativePtr, milliseconds, vibrationId, stepId);
}
/** Turns vibrator off. */
@@ -610,30 +612,31 @@
}
/** Turns vibrator on to perform one of the supported effects. */
- public long perform(long effect, long strength, long vibrationId) {
- return performEffect(mNativePtr, effect, strength, vibrationId);
+ public long perform(long effect, long strength, long vibrationId, long stepId) {
+ return performEffect(mNativePtr, effect, strength, vibrationId, stepId);
}
/** Turns vibrator on to perform a vendor-specific effect. */
public long performVendorEffect(Parcel vendorData, long strength, float scale,
- float adaptiveScale, long vibrationId) {
+ float adaptiveScale, long vibrationId, long stepId) {
return performVendorEffect(mNativePtr, vendorData, strength, scale, adaptiveScale,
- vibrationId);
+ vibrationId, stepId);
}
/** Turns vibrator on to perform effect composed of give primitives effect. */
- public long compose(PrimitiveSegment[] primitives, long vibrationId) {
- return performComposedEffect(mNativePtr, primitives, vibrationId);
+ public long compose(PrimitiveSegment[] primitives, long vibrationId, long stepId) {
+ return performComposedEffect(mNativePtr, primitives, vibrationId, stepId);
}
/** Turns vibrator on to perform PWLE effect composed of given primitives. */
- public long composePwle(RampSegment[] primitives, int braking, long vibrationId) {
- return performPwleEffect(mNativePtr, primitives, braking, vibrationId);
+ public long composePwle(RampSegment[] primitives, int braking, long vibrationId,
+ long stepId) {
+ return performPwleEffect(mNativePtr, primitives, braking, vibrationId, stepId);
}
/** Turns vibrator on to perform PWLE effect composed of given points. */
- public long composePwleV2(PwlePoint[] pwlePoints, long vibrationId) {
- return performPwleV2Effect(mNativePtr, pwlePoints, vibrationId);
+ public long composePwleV2(PwlePoint[] pwlePoints, long vibrationId, long stepId) {
+ return performPwleV2Effect(mNativePtr, pwlePoints, vibrationId, stepId);
}
/** Enabled the device vibrator to be controlled by another service. */
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 804cf46..3f5fc33 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -61,6 +61,7 @@
import android.os.vibrator.Flags;
import android.os.vibrator.IVibrationSessionCallback;
import android.os.vibrator.PrebakedSegment;
+import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
import android.os.vibrator.VibratorInfoFactory;
@@ -786,7 +787,7 @@
synchronized (mLock) {
if (DEBUG) {
- Slog.d(TAG, "Starting session " + session.getSessionId());
+ Slog.d(TAG, "Starting vendor session " + session.getSessionId());
}
Status ignoreStatus = null;
@@ -864,13 +865,16 @@
// Session already ended, possibly cancelled by app cancellation signal.
return session.getStatus();
}
- int mode = startAppOpModeLocked(session.getCallerInfo());
+ CallerInfo callerInfo = session.getCallerInfo();
+ int mode = startAppOpModeLocked(callerInfo);
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
Trace.asyncTraceBegin(TRACE_TAG_VIBRATOR, "vibration", 0);
// Make sure mCurrentVibration is set while triggering the HAL.
mCurrentSession = session;
if (!session.linkToDeath()) {
+ // Shouldn't happen. The method call already logs.
+ finishAppOpModeLocked(callerInfo);
mCurrentSession = null;
return Status.IGNORED_ERROR_TOKEN;
}
@@ -878,14 +882,14 @@
Slog.e(TAG, "Error starting session " + sessionId + " on vibrators "
+ Arrays.toString(session.getVibratorIds()));
session.unlinkToDeath();
+ finishAppOpModeLocked(callerInfo);
mCurrentSession = null;
return Status.IGNORED_UNSUPPORTED;
}
session.notifyStart();
return null;
case AppOpsManager.MODE_ERRORED:
- Slog.w(TAG, "Start AppOpsManager operation errored for uid "
- + session.getCallerInfo().uid);
+ Slog.w(TAG, "Start AppOpsManager operation errored for uid " + callerInfo.uid);
return Status.IGNORED_ERROR_APP_OPS;
default:
return Status.IGNORED_APP_OPS;
@@ -1081,11 +1085,12 @@
@Nullable
private Status startVibrationOnThreadLocked(SingleVibrationSession session) {
if (DEBUG) {
- Slog.d(TAG, "Starting vibration " + session.getVibration().id + " on thread");
+ Slog.d(TAG, "Starting vibration " + session.getVibration().id + " on thread");
}
VibrationStepConductor conductor = createVibrationStepConductor(session.getVibration());
session.setVibrationConductor(conductor);
- int mode = startAppOpModeLocked(session.getCallerInfo());
+ CallerInfo callerInfo = session.getCallerInfo();
+ int mode = startAppOpModeLocked(callerInfo);
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
Trace.asyncTraceBegin(TRACE_TAG_VIBRATOR, "vibration", 0);
@@ -1093,19 +1098,21 @@
mCurrentSession = session;
if (!mCurrentSession.linkToDeath()) {
// Shouldn't happen. The method call already logs.
+ finishAppOpModeLocked(callerInfo);
mCurrentSession = null; // Aborted.
return Status.IGNORED_ERROR_TOKEN;
}
if (!mVibrationThread.runVibrationOnVibrationThread(conductor)) {
// Shouldn't happen. The method call already logs.
session.setVibrationConductor(null); // Rejected by thread, clear it in session.
+ mCurrentSession.unlinkToDeath();
+ finishAppOpModeLocked(callerInfo);
mCurrentSession = null; // Aborted.
return Status.IGNORED_ERROR_SCHEDULING;
}
return null;
case AppOpsManager.MODE_ERRORED:
- Slog.w(TAG, "Start AppOpsManager operation errored for uid "
- + session.getCallerInfo().uid);
+ Slog.w(TAG, "Start AppOpsManager operation errored for uid " + callerInfo.uid);
return Status.IGNORED_ERROR_APP_OPS;
default:
return Status.IGNORED_APP_OPS;
@@ -1286,14 +1293,14 @@
}
}
- private void onVibrationComplete(int vibratorId, long vibrationId) {
+ private void onVibrationComplete(int vibratorId, long vibrationId, long stepId) {
synchronized (mLock) {
if (mCurrentSession != null) {
if (DEBUG) {
- Slog.d(TAG, "Vibration " + vibrationId + " on vibrator " + vibratorId
- + " complete, notifying thread");
+ Slog.d(TAG, "Vibration " + vibrationId + " step " + stepId
+ + " on vibrator " + vibratorId + " complete, notifying thread");
}
- mCurrentSession.notifyVibratorCallback(vibratorId, vibrationId);
+ mCurrentSession.notifyVibratorCallback(vibratorId, vibrationId, stepId);
}
}
}
@@ -1494,6 +1501,13 @@
private int checkAppOpModeLocked(CallerInfo callerInfo) {
int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE,
callerInfo.attrs.getAudioUsage(), callerInfo.uid, callerInfo.opPkg);
+ if (DEBUG) {
+ int opMode = mAppOps.checkOpNoThrow(AppOpsManager.OP_VIBRATE, callerInfo.uid,
+ callerInfo.opPkg);
+ Slog.d(TAG, "Check AppOp mode VIBRATE for uid " + callerInfo.uid + " and package "
+ + callerInfo.opPkg + " returned audio=" + AppOpsManager.MODE_NAMES[mode]
+ + ", op=" + AppOpsManager.MODE_NAMES[opMode]);
+ }
int fixedMode = fixupAppOpModeLocked(mode, callerInfo.attrs);
if (mode != fixedMode && fixedMode == AppOpsManager.MODE_ALLOWED) {
// If we're just ignoring the vibration op then this is set by DND and we should ignore
@@ -1507,9 +1521,13 @@
/** Start an operation in {@link AppOpsManager}, if allowed. */
@GuardedBy("mLock")
private int startAppOpModeLocked(CallerInfo callerInfo) {
- return fixupAppOpModeLocked(
- mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, callerInfo.uid, callerInfo.opPkg),
- callerInfo.attrs);
+ int mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, callerInfo.uid,
+ callerInfo.opPkg);
+ if (DEBUG) {
+ Slog.d(TAG, "Start AppOp mode VIBRATE for uid " + callerInfo.uid + " and package "
+ + callerInfo.opPkg + " returned " + AppOpsManager.MODE_NAMES[mode]);
+ }
+ return fixupAppOpModeLocked(mode, callerInfo.attrs);
}
/**
@@ -1518,6 +1536,10 @@
*/
@GuardedBy("mLock")
private void finishAppOpModeLocked(CallerInfo callerInfo) {
+ if (DEBUG) {
+ Slog.d(TAG, "Finish AppOp mode VIBRATE for uid " + callerInfo.uid + " and package "
+ + callerInfo.opPkg);
+ }
mAppOps.finishOp(AppOpsManager.OP_VIBRATE, callerInfo.uid, callerInfo.opPkg);
}
@@ -2078,10 +2100,10 @@
}
@Override
- public void onComplete(int vibratorId, long vibrationId) {
+ public void onComplete(int vibratorId, long vibrationId, long stepId) {
VibratorManagerService service = mServiceRef.get();
if (service != null) {
- service.onVibrationComplete(vibratorId, vibrationId);
+ service.onVibrationComplete(vibratorId, vibrationId, stepId);
}
}
}
@@ -2651,7 +2673,7 @@
CombinedVibration.ParallelCombination combination =
CombinedVibration.startParallel();
while ("-v".equals(getNextOption())) {
- int vibratorId = Integer.parseInt(getNextArgRequired());
+ int vibratorId = parseInt(getNextArgRequired(), "Expected vibrator id after -v");
combination.addVibrator(vibratorId, nextEffect());
}
runVibrate(commonOptions, combination.combine());
@@ -2663,7 +2685,7 @@
CombinedVibration.SequentialCombination combination =
CombinedVibration.startSequential();
while ("-v".equals(getNextOption())) {
- int vibratorId = Integer.parseInt(getNextArgRequired());
+ int vibratorId = parseInt(getNextArgRequired(), "Expected vibrator id after -v");
combination.addNext(vibratorId, nextEffect());
}
runVibrate(commonOptions, combination.combine());
@@ -2688,7 +2710,7 @@
private int runHapticFeedback() {
CommonOptions commonOptions = new CommonOptions();
- int constant = Integer.parseInt(getNextArgRequired());
+ int constant = parseInt(getNextArgRequired(), "Expected haptic feedback constant id");
IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
: mShellCallbacksToken;
@@ -2715,6 +2737,8 @@
addPrebakedToComposition(composition);
} else if ("primitives".equals(nextArg)) {
addPrimitivesToComposition(composition);
+ } else if ("envelope".equals(nextArg)) {
+ addEnvelopeToComposition(composition);
} else {
// nextArg is not an effect, finish reading.
break;
@@ -2734,17 +2758,135 @@
if ("-a".equals(nextOption)) {
hasAmplitude = true;
} else if ("-w".equals(nextOption)) {
- delay = Integer.parseInt(getNextArgRequired());
+ delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
}
}
- long duration = Long.parseLong(getNextArgRequired());
- int amplitude = hasAmplitude ? Integer.parseInt(getNextArgRequired())
+ long duration = parseInt(getNextArgRequired(), "Expected one-shot duration millis");
+ int amplitude = hasAmplitude
+ ? parseInt(getNextArgRequired(), "Expected one-shot amplitude")
: VibrationEffect.DEFAULT_AMPLITUDE;
composition.addOffDuration(Duration.ofMillis(delay));
composition.addEffect(VibrationEffect.createOneShot(duration, amplitude));
}
+ private interface EnvelopeBuilder {
+ void setInitialSharpness(float sharpness);
+ void addControlPoint(float intensity, float sharpness, long duration);
+ void reset(float initialSharpness);
+ VibrationEffect build();
+ }
+
+ private static class BasicEnveloperBuilderWrapper implements EnvelopeBuilder {
+ private VibrationEffect.BasicEnvelopeBuilder mBuilder =
+ new VibrationEffect.BasicEnvelopeBuilder();
+
+ @Override
+ public void setInitialSharpness(float sharpness) {
+ mBuilder.setInitialSharpness(sharpness);
+ }
+
+ @Override
+ public void addControlPoint(float intensity, float sharpness, long duration) {
+ mBuilder.addControlPoint(intensity, sharpness, duration);
+ }
+
+ @Override
+ public void reset(float initialSharpness) {
+ mBuilder = new VibrationEffect.BasicEnvelopeBuilder();
+ mBuilder.setInitialSharpness(initialSharpness);
+ }
+
+ @Override
+ public VibrationEffect build() {
+ return mBuilder.build();
+ }
+ }
+
+ private static class AdvancedEnveloperBuilderWrapper implements EnvelopeBuilder {
+ private VibrationEffect.WaveformEnvelopeBuilder mBuilder =
+ new VibrationEffect.WaveformEnvelopeBuilder();
+
+ @Override
+ public void setInitialSharpness(float sharpness) {
+ mBuilder.setInitialFrequencyHz(sharpness);
+ }
+
+ @Override
+ public void addControlPoint(float intensity, float sharpness, long duration) {
+ mBuilder.addControlPoint(intensity, sharpness, duration);
+ }
+
+ @Override
+ public void reset(float initialSharpness) {
+ mBuilder = new VibrationEffect.WaveformEnvelopeBuilder();
+ mBuilder.setInitialFrequencyHz(initialSharpness);
+ }
+
+ @Override
+ public VibrationEffect build() {
+ return mBuilder.build();
+ }
+ }
+
+ private void addEnvelopeToComposition(VibrationEffect.Composition composition) {
+ getNextArgRequired(); // consume "envelope"
+ int repeat = -1;
+ float initialSharpness = Float.NaN;
+ VibrationEffect preamble = null;
+ boolean isAdvanced = false;
+ String nextOption;
+ while ((nextOption = getNextOption()) != null) {
+ switch (nextOption) {
+ case "-a" -> isAdvanced = true;
+ case "-i" -> initialSharpness = parseFloat(getNextArgRequired(),
+ "Expected initial sharpness after -i");
+ case "-r" -> repeat = parseInt(getNextArgRequired(),
+ "Expected repeat index after -r");
+ }
+ }
+
+ EnvelopeBuilder builder = isAdvanced ? new AdvancedEnveloperBuilderWrapper()
+ : new BasicEnveloperBuilderWrapper();
+
+ if (!Float.isNaN(initialSharpness)) {
+ builder.setInitialSharpness(initialSharpness);
+ }
+
+ int duration, pos = 0;
+ float intensity, sharpness = 0f;
+ String nextArg;
+ while ((nextArg = peekNextArg()) != null) {
+ if (pos > 0 && pos == repeat) {
+ preamble = builder.build();
+ builder.reset(sharpness);
+ }
+ try {
+ duration = Integer.parseInt(nextArg);
+ getNextArgRequired(); // consume the duration
+ } catch (NumberFormatException e) {
+ // nextArg is not a duration, finish reading.
+ break;
+ }
+ intensity = parseFloat(getNextArgRequired(), "Expected envelope intensity");
+ sharpness = parseFloat(getNextArgRequired(), "Expected envelope sharpness");
+ builder.addControlPoint(intensity, sharpness, duration);
+ pos++;
+ }
+
+ if (repeat >= 0) {
+ if (preamble == null) {
+ composition.addEffect(VibrationEffect.createRepeatingEffect(builder.build()));
+ } else {
+ composition.addEffect(
+ VibrationEffect.createRepeatingEffect(preamble, builder.build()));
+ }
+ return;
+ }
+
+ composition.addEffect(builder.build());
+ }
+
private void addWaveformToComposition(VibrationEffect.Composition composition) {
boolean hasAmplitudes = false;
boolean hasFrequencies = false;
@@ -2755,16 +2897,14 @@
getNextArgRequired(); // consume "waveform"
String nextOption;
while ((nextOption = getNextOption()) != null) {
- if ("-a".equals(nextOption)) {
- hasAmplitudes = true;
- } else if ("-r".equals(nextOption)) {
- repeat = Integer.parseInt(getNextArgRequired());
- } else if ("-w".equals(nextOption)) {
- delay = Integer.parseInt(getNextArgRequired());
- } else if ("-f".equals(nextOption)) {
- hasFrequencies = true;
- } else if ("-c".equals(nextOption)) {
- isContinuous = true;
+ switch (nextOption) {
+ case "-a" -> hasAmplitudes = true;
+ case "-f" -> hasFrequencies = true;
+ case "-c" -> isContinuous = true;
+ case "-r" -> repeat = parseInt(getNextArgRequired(),
+ "Expected repeat index after -r");
+ case "-w" -> delay = parseInt(getNextArgRequired(),
+ "Expected delay millis after -w");
}
}
List<Integer> durations = new ArrayList<>();
@@ -2782,14 +2922,15 @@
break;
}
if (hasAmplitudes) {
- amplitudes.add(
- Float.parseFloat(getNextArgRequired()) / VibrationEffect.MAX_AMPLITUDE);
+ int amplitude = parseInt(getNextArgRequired(), "Expected waveform amplitude");
+ amplitudes.add((float) amplitude / VibrationEffect.MAX_AMPLITUDE);
} else {
amplitudes.add(nextAmplitude);
nextAmplitude = 1 - nextAmplitude;
}
if (hasFrequencies) {
- frequencies.add(Float.parseFloat(getNextArgRequired()));
+ frequencies.add(
+ parseFloat(getNextArgRequired(), "Expected waveform frequency"));
}
}
@@ -2848,27 +2989,37 @@
if ("-b".equals(nextOption)) {
shouldFallback = true;
} else if ("-w".equals(nextOption)) {
- delay = Integer.parseInt(getNextArgRequired());
+ delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
}
}
- int effectId = Integer.parseInt(getNextArgRequired());
+ int effectId = parseInt(getNextArgRequired(), "Expected prebaked effect id");
composition.addOffDuration(Duration.ofMillis(delay));
composition.addEffect(VibrationEffect.get(effectId, shouldFallback));
}
private void addPrimitivesToComposition(VibrationEffect.Composition composition) {
getNextArgRequired(); // consume "primitives"
- String nextArg;
- while ((nextArg = peekNextArg()) != null) {
+ while (peekNextArg() != null) {
int delay = 0;
- if ("-w".equals(nextArg)) {
- getNextArgRequired(); // consume "-w"
- delay = Integer.parseInt(getNextArgRequired());
- nextArg = peekNextArg();
+ float scale = 1f;
+ int delayType = PrimitiveSegment.DEFAULT_DELAY_TYPE;
+
+ String nextOption;
+ while ((nextOption = getNextOption()) != null) {
+ if ("-s".equals(nextOption)) {
+ scale = parseFloat(getNextArgRequired(), "Expected scale after -s");
+ } else if ("-o".equals(nextOption)) {
+ delayType = VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET;
+ delay = parseInt(getNextArgRequired(), "Expected offset millis after -o");
+ } else if ("-w".equals(nextOption)) {
+ delayType = PrimitiveSegment.DEFAULT_DELAY_TYPE;
+ delay = parseInt(getNextArgRequired(), "Expected delay millis after -w");
+ }
}
try {
- composition.addPrimitive(Integer.parseInt(nextArg), /* scale= */ 1, delay);
+ String nextArg = peekNextArg(); // Just in case this is not a primitive.
+ composition.addPrimitive(Integer.parseInt(nextArg), scale, delay, delayType);
getNextArgRequired(); // consume the primitive id
} catch (NumberFormatException | NullPointerException e) {
// nextArg is not describing a primitive, leave it to be consumed by outer loops
@@ -2894,17 +3045,15 @@
VibrationXmlParser.parseDocument(new StringReader(xml));
VibratorInfo combinedVibratorInfo = getCombinedVibratorInfo();
if (combinedVibratorInfo == null) {
- throw new IllegalStateException(
- "No combined vibrator info to parse vibration XML " + xml);
+ throw new IllegalStateException("No vibrator info available to parse XML");
}
VibrationEffect effect = parsedVibration.resolve(combinedVibratorInfo);
if (effect == null) {
- throw new IllegalArgumentException(
- "Parsed vibration cannot be resolved for vibration XML " + xml);
+ throw new IllegalArgumentException("Parsed XML cannot be resolved: " + xml);
}
return CombinedVibration.createParallel(effect);
} catch (IOException e) {
- throw new RuntimeException("Error parsing vibration XML " + xml, e);
+ throw new RuntimeException("Error parsing XML: " + xml, e);
}
}
@@ -2922,16 +3071,30 @@
}
}
+ private static int parseInt(String text, String errorMessage) {
+ try {
+ return Integer.parseInt(text);
+ } catch (NumberFormatException | NullPointerException e) {
+ throw new IllegalArgumentException(errorMessage, e);
+ }
+ }
+
+ private static float parseFloat(String text, String errorMessage) {
+ try {
+ return Float.parseFloat(text);
+ } catch (NumberFormatException | NullPointerException e) {
+ throw new IllegalArgumentException(errorMessage, e);
+ }
+ }
+
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
pw.println("Vibrator Manager commands:");
pw.println(" help");
pw.println(" Prints this help text.");
- pw.println("");
pw.println(" list");
- pw.println(" Prints the id of device vibrators. This does not include any ");
- pw.println(" connected input device.");
+ pw.println(" Prints device vibrator ids; does not include input devices.");
pw.println(" synced [options] <effect>...");
pw.println(" Vibrates effect on all vibrators in sync.");
pw.println(" combined [options] (-v <vibrator-id> <effect>...)...");
@@ -2941,58 +3104,63 @@
pw.println(" xml [options] <xml>");
pw.println(" Vibrates using combined vibration described in given XML string");
pw.println(" on all vibrators in sync. The XML could be:");
- pw.println(" XML containing a single effect, or");
- pw.println(" A vibration select XML containing multiple effects.");
- pw.println(" Vibrates using combined vibration described in given XML string.");
- pw.println(" XML containing a single effect it runs on all vibrators in sync.");
+ pw.println(" A single <vibration-effect>, or");
+ pw.println(" A <vibration-select> containing multiple effects.");
+ pw.println(" feedback [options] <constant>");
+ pw.println(" Performs a haptic feedback with the given constant.");
pw.println(" cancel");
pw.println(" Cancels any active vibration");
- pw.println(" feedback [-f] [-d <description>] <constant>");
- pw.println(" Performs a haptic feedback with the given constant.");
- pw.println(" The force (-f) option enables the `always` configuration, which");
- pw.println(" plays the haptic irrespective of the vibration intensity settings");
pw.println("");
pw.println("Effect commands:");
pw.println(" oneshot [-w delay] [-a] <duration> [<amplitude>]");
- pw.println(" Vibrates for duration milliseconds; ignored when device is on ");
- pw.println(" DND (Do Not Disturb) mode; touch feedback strength user setting ");
- pw.println(" will be used to scale amplitude.");
+ pw.println(" Vibrates for duration milliseconds.");
pw.println(" If -w is provided, the effect will be played after the specified");
pw.println(" wait time in milliseconds.");
pw.println(" If -a is provided, the command accepts a second argument for ");
pw.println(" amplitude, in a scale of 1-255.");
pw.print(" waveform [-w delay] [-r index] [-a] [-f] [-c] ");
pw.println("(<duration> [<amplitude>] [<frequency>])...");
- pw.println(" Vibrates for durations and amplitudes in list; ignored when ");
- pw.println(" device is on DND (Do Not Disturb) mode; touch feedback strength ");
- pw.println(" user setting will be used to scale amplitude.");
+ pw.println(" Vibrates for durations and amplitudes in list.");
pw.println(" If -w is provided, the effect will be played after the specified");
pw.println(" wait time in milliseconds.");
pw.println(" If -r is provided, the waveform loops back to the specified");
- pw.println(" index (e.g. 0 loops from the beginning)");
+ pw.println(" index (e.g. 0 loops from the beginning).");
pw.println(" If -a is provided, the command expects amplitude to follow each");
pw.println(" duration; otherwise, it accepts durations only and alternates");
- pw.println(" off/on");
+ pw.println(" off/on.");
pw.println(" If -f is provided, the command expects frequency to follow each");
- pw.println(" amplitude or duration; otherwise, it uses resonant frequency");
+ pw.println(" amplitude or duration; otherwise, it uses resonant frequency.");
pw.println(" If -c is provided, the waveform is continuous and will ramp");
pw.println(" between values; otherwise each entry is a fixed step.");
pw.println(" Duration is in milliseconds; amplitude is a scale of 1-255;");
- pw.println(" frequency is an absolute value in hertz;");
+ pw.println(" frequency is an absolute value in hertz.");
+ pw.print(" envelope [-a] [-i initial sharpness] [-r index] ");
+ pw.println("[<duration1> <intensity1> <sharpness1>]...");
+ pw.println(" Generates a vibration pattern based on a series of duration, ");
+ pw.println(" intensity, and sharpness values. The total vibration time is ");
+ pw.println(" the sum of all durations.");
+ pw.println(" If -a is provided, the waveform will use the advanced APIs to ");
+ pw.println(" generate the vibration pattern and the input parameters ");
+ pw.println(" become [<duration1> <amplitude1> <frequency1>].");
+ pw.println(" If -i is provided, the waveform will have an initial sharpness ");
+ pw.println(" it will start from.");
+ pw.println(" If -r is provided, the waveform loops back to the specified index");
+ pw.println(" (e.g. 0 loops from the beginning).");
pw.println(" prebaked [-w delay] [-b] <effect-id>");
- pw.println(" Vibrates with prebaked effect; ignored when device is on DND ");
- pw.println(" (Do Not Disturb) mode; touch feedback strength user setting ");
- pw.println(" will be used to scale amplitude.");
+ pw.println(" Vibrates with prebaked effect.");
pw.println(" If -w is provided, the effect will be played after the specified");
pw.println(" wait time in milliseconds.");
pw.println(" If -b is provided, the prebaked fallback effect will be played if");
pw.println(" the device doesn't support the given effect-id.");
- pw.println(" primitives ([-w delay] <primitive-id>)...");
- pw.println(" Vibrates with a composed effect; ignored when device is on DND ");
- pw.println(" (Do Not Disturb) mode; touch feedback strength user setting ");
- pw.println(" will be used to scale primitive intensities.");
+ pw.print(" primitives ([-w delay] [-o time] [-s scale]");
+ pw.println("<primitive-id> [<scale>])...");
+ pw.println(" Vibrates with a composed effect.");
pw.println(" If -w is provided, the next primitive will be played after the ");
pw.println(" specified wait time in milliseconds.");
+ pw.println(" If -o is provided, the next primitive will be played at the ");
+ pw.println(" specified start offset time in milliseconds.");
+ pw.println(" If -s is provided, the next primitive will be played with the");
+ pw.println(" specified amplitude scale, in a scale of [0,1].");
pw.println("");
pw.println("Common Options:");
pw.println(" -f");
@@ -3003,6 +3171,11 @@
pw.println(" -d <description>");
pw.println(" Add description to the vibration.");
pw.println("");
+ pw.println("Notes");
+ pw.println(" Vibrations triggered by these commands will be ignored when");
+ pw.println(" device is on DND (Do Not Disturb) mode; notification strength");
+ pw.println(" user settings will be applied for scale.");
+ pw.println("");
}
}
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
index b3e68a35..8e8455a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
@@ -16,6 +16,8 @@
package com.android.server.wallpaper;
+import static android.app.WallpaperManager.ORIENTATION_LANDSCAPE;
+import static android.app.WallpaperManager.ORIENTATION_SQUARE_LANDSCAPE;
import static android.app.WallpaperManager.ORIENTATION_UNKNOWN;
import static android.app.WallpaperManager.getOrientation;
import static android.app.WallpaperManager.getRotatedOrientation;
@@ -28,6 +30,7 @@
import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
import static com.android.window.flags.Flags.multiCrop;
+import android.app.WallpaperManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageDecoder;
@@ -821,4 +824,54 @@
}
}
}
+
+ /**
+ * Returns true if a wallpaper is compatible with a given display with ID, {@code displayId}.
+ *
+ * <p>A wallpaper is compatible with a display if any of the following are true
+ * <ol>the display is a default display</o>
+ * <ol>the wallpaper is a stock wallpaper</ol>
+ * <ol>the wallpaper size is at least 3/4 of the display resolution and, in landscape displays,
+ * the wallpaper has an aspect ratio of at least 11:13.</ol>
+ */
+ @VisibleForTesting
+ boolean isWallpaperCompatibleForDisplay(int displayId, WallpaperData wallpaperData) {
+ if (displayId == DEFAULT_DISPLAY) {
+ return true;
+ }
+
+ File wallpaperFile = wallpaperData.getWallpaperFile();
+ if (!wallpaperFile.exists()) {
+ // Assumption: Stock wallpaper is suitable for all display sizes.
+ return true;
+ }
+
+ DisplayInfo displayInfo = mWallpaperDisplayHelper.getDisplayInfo(displayId);
+ Point displaySize = new Point(displayInfo.logicalWidth, displayInfo.logicalHeight);
+ int displayOrientation = WallpaperManager.getOrientation(displaySize);
+
+ Point wallpaperImageSize = new Point(
+ (int) Math.ceil(wallpaperData.cropHint.width() / wallpaperData.mSampleSize),
+ (int) Math.ceil(wallpaperData.cropHint.height() / wallpaperData.mSampleSize));
+ if (wallpaperImageSize.equals(0, 0)) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(wallpaperFile.getAbsolutePath(), options);
+ wallpaperImageSize.set(options.outWidth, options.outHeight);
+ }
+
+ double maxDisplayToImageRatio = Math.max((double) displaySize.x / wallpaperImageSize.x,
+ (double) displaySize.y / wallpaperImageSize.y);
+ if (maxDisplayToImageRatio > 1.5) {
+ return false;
+ }
+
+ // For displays in landscape, we only support images with an aspect ratio >= 11:13
+ if (displayOrientation == ORIENTATION_LANDSCAPE) {
+ return ((double) wallpaperImageSize.x / wallpaperImageSize.y) >= 11.0 / 13;
+ }
+
+ // For other orientations, we don't enforce any aspect ratio.
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 69b2b9b..d620e98 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -118,7 +118,6 @@
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.IntArray;
import android.util.Slog;
@@ -161,7 +160,6 @@
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -743,10 +741,8 @@
final WallpaperDisplayHelper mWallpaperDisplayHelper;
final WallpaperCropper mWallpaperCropper;
- // TODO(b/384519749): Remove this set after we introduce the aspect ratio check.
- private final Set<Integer> mWallpaperCompatibleDisplaysForTest = new ArraySet<>();
-
- private boolean isWallpaperCompatibleForDisplay(int displayId, WallpaperConnection connection) {
+ @VisibleForTesting
+ boolean isWallpaperCompatibleForDisplay(int displayId, WallpaperConnection connection) {
if (connection == null) {
return false;
}
@@ -757,26 +753,14 @@
// Image wallpaper
if (isDeviceEligibleForDesktopExperienceWallpaper(mContext)) {
- // TODO(b/384519749): check display's resolution and image wallpaper cropped image
- // aspect ratio.
- return displayId == DEFAULT_DISPLAY
- || mWallpaperCompatibleDisplaysForTest.contains(displayId);
+ return mWallpaperCropper.isWallpaperCompatibleForDisplay(displayId,
+ connection.mWallpaper);
}
// When enableConnectedDisplaysWallpaper is off, we assume the image wallpaper supports all
// usable displays.
return true;
}
- @VisibleForTesting
- void addWallpaperCompatibleDisplayForTest(int displayId) {
- mWallpaperCompatibleDisplaysForTest.add(displayId);
- }
-
- @VisibleForTesting
- void removeWallpaperCompatibleDisplayForTest(int displayId) {
- mWallpaperCompatibleDisplaysForTest.remove(displayId);
- }
-
private void updateFallbackConnection(int clientUid) {
if (mLastWallpaper == null || mFallbackWallpaper == null) return;
final WallpaperConnection systemConnection = mLastWallpaper.connection;
@@ -844,7 +828,7 @@
// `which` flag.
DisplayConnector fallbackConnector =
mFallbackWallpaper.connection.getDisplayConnectorOrCreate(displayId);
- if (fallbackConnector != null && fallbackConnector.mEngine != null) {
+ if (fallbackConnector != null) {
fallbackConnector.mWhich = which;
fallbackConnector.connectLocked(mFallbackWallpaper.connection,
mFallbackWallpaper);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 333d91a..7b6d408f 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -109,7 +109,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED;
import static android.view.WindowManager.PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING;
-import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_UNSET;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
import static android.view.WindowManager.hasWindowExtensionsEnabled;
@@ -289,6 +288,7 @@
import android.content.pm.UserProperties;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.PixelFormat;
@@ -320,9 +320,7 @@
import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
-import android.view.AppTransitionAnimationSpec;
import android.view.DisplayInfo;
-import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.InputApplicationHandle;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
@@ -352,7 +350,6 @@
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.TimeoutRecord;
import com.android.internal.os.TransferPipe;
-import com.android.internal.policy.AttributeCache;
import com.android.internal.policy.PhoneWindow;
import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.XmlUtils;
@@ -479,6 +476,8 @@
final String processName; // process where this component wants to run
final String taskAffinity; // as per ActivityInfo.taskAffinity
final boolean stateNotNeeded; // As per ActivityInfo.flags
+ @Nullable
+ final WindowStyle mWindowStyle;
@VisibleForTesting
int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
@VisibleForTesting
@@ -491,6 +490,7 @@
private long createTime = System.currentTimeMillis();
long lastVisibleTime; // last time this activity became visible
long pauseTime; // last time we started pausing the activity
+ long mStoppedTime; // last time we completely stopped the activity
long launchTickTime; // base time for launch tick messages
long topResumedStateLossTime; // last time we reported top resumed state loss to an activity
// Last configuration reported to the activity in the client process.
@@ -1926,22 +1926,17 @@
? android.R.style.Theme : android.R.style.Theme_Holo;
}
- final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
- realTheme, com.android.internal.R.styleable.Window, mUserId);
-
- if (ent != null) {
- final boolean styleTranslucent = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsTranslucent, false);
- final boolean styleFloating = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsFloating, false);
- mOccludesParent = !(styleTranslucent || styleFloating)
+ final WindowStyle style = mAtmService.getWindowStyle(packageName, realTheme, mUserId);
+ mWindowStyle = style;
+ if (style != null) {
+ mOccludesParent = !(style.isTranslucent() || style.isFloating())
// This style is propagated to the main window attributes with
// FLAG_SHOW_WALLPAPER from PhoneWindow#generateLayout.
- || ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
+ || style.showWallpaper();
mStyleFillsParent = mOccludesParent;
- mNoDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
- mOptOutEdgeToEdge = PhoneWindow.isOptingOutEdgeToEdgeEnforcement(
- aInfo.applicationInfo, false /* local */, ent.array);
+ mNoDisplay = style.noDisplay();
+ mOptOutEdgeToEdge = style.optOutEdgeToEdge() && PhoneWindow.isOptOutEdgeToEdgeEnabled(
+ aInfo.applicationInfo, false /* local */);
} else {
mStyleFillsParent = mOccludesParent = true;
mNoDisplay = false;
@@ -2272,21 +2267,17 @@
return false;
}
- final AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
- com.android.internal.R.styleable.Window, mWmService.mCurrentUserId);
- if (ent == null) {
+ final WindowStyle style = theme == this.theme
+ ? mWindowStyle : mAtmService.getWindowStyle(pkg, theme, mUserId);
+ if (style == null) {
// Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
// see that.
return false;
}
- final boolean windowIsTranslucent = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsTranslucent, false);
- final boolean windowIsFloating = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsFloating, false);
- final boolean windowShowWallpaper = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowShowWallpaper, false);
- final boolean windowDisableStarting = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowDisablePreview, false);
+ final boolean windowIsTranslucent = style.isTranslucent();
+ final boolean windowIsFloating = style.isFloating();
+ final boolean windowShowWallpaper = style.showWallpaper();
+ final boolean windowDisableStarting = style.disablePreview();
ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
"Translucent=%s Floating=%s ShowWallpaper=%s Disable=%s",
windowIsTranslucent, windowIsFloating, windowShowWallpaper,
@@ -2355,7 +2346,8 @@
// The snapshot of home is only used once because it won't be updated while screen
// is on (see {@link TaskSnapshotController#screenTurningOff}).
mWmService.mTaskSnapshotController.removeSnapshotCache(task.mTaskId);
- if ((mDisplayContent.mAppTransition.getTransitFlags()
+ final Transition transition = mTransitionController.getCollectingTransition();
+ if (transition != null && (transition.getFlags()
& WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0) {
// Only use snapshot of home as starting window when unlocking directly.
return false;
@@ -3644,7 +3636,6 @@
if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
}
- mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
// When finishing the activity preemptively take the snapshot before the app window
// is marked as hidden and any configuration changes take place
@@ -3746,7 +3737,6 @@
private void prepareActivityHideTransitionAnimation() {
final DisplayContent dc = mDisplayContent;
- dc.prepareAppTransition(TRANSIT_CLOSE);
setVisibility(false);
dc.executeAppTransition();
}
@@ -4398,13 +4388,6 @@
removeStartingWindow();
}
- // If app transition animation was running for this activity, then we need to ensure that
- // the app transition notifies that animations have completed in
- // DisplayContent.handleAnimatingStoppedAndTransition(), so add to that list now
- if (isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_APP_TRANSITION)) {
- getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
- }
-
if (delayed && !isEmpty()) {
// set the token aside because it has an active animation to be finished
ProtoLog.v(WM_DEBUG_ADD_REMOVE,
@@ -5076,8 +5059,6 @@
void applyOptionsAnimation() {
if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
if (mPendingRemoteAnimation != null) {
- mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(
- mPendingRemoteAnimation);
mTransitionController.setStatusBarTransitionDelay(
mPendingRemoteAnimation.getStatusBarTransitionDelay());
} else {
@@ -5107,14 +5088,6 @@
IRemoteCallback finishCallback = null;
switch (animationType) {
case ANIM_CUSTOM:
- displayContent.mAppTransition.overridePendingAppTransition(
- pendingOptions.getPackageName(),
- pendingOptions.getCustomEnterResId(),
- pendingOptions.getCustomExitResId(),
- pendingOptions.getCustomBackgroundColor(),
- pendingOptions.getAnimationStartedListener(),
- pendingOptions.getAnimationFinishedListener(),
- pendingOptions.getOverrideTaskTransition());
options = AnimationOptions.makeCustomAnimOptions(pendingOptions.getPackageName(),
pendingOptions.getCustomEnterResId(), pendingOptions.getCustomExitResId(),
pendingOptions.getCustomBackgroundColor(),
@@ -5123,9 +5096,6 @@
finishCallback = pendingOptions.getAnimationFinishedListener();
break;
case ANIM_CLIP_REVEAL:
- displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getWidth(), pendingOptions.getHeight());
options = AnimationOptions.makeClipRevealAnimOptions(
pendingOptions.getStartX(), pendingOptions.getStartY(),
pendingOptions.getWidth(), pendingOptions.getHeight());
@@ -5137,9 +5107,6 @@
}
break;
case ANIM_SCALE_UP:
- displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getWidth(), pendingOptions.getHeight());
options = AnimationOptions.makeScaleUpAnimOptions(
pendingOptions.getStartX(), pendingOptions.getStartY(),
pendingOptions.getWidth(), pendingOptions.getHeight(),
@@ -5155,10 +5122,6 @@
case ANIM_THUMBNAIL_SCALE_DOWN:
final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
final HardwareBuffer buffer = pendingOptions.getThumbnail();
- displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getAnimationStartedListener(),
- scaleUp);
options = AnimationOptions.makeThumbnailAnimOptions(buffer,
pendingOptions.getStartX(), pendingOptions.getStartY(), scaleUp);
startCallback = pendingOptions.getAnimationStartedListener();
@@ -5171,36 +5134,9 @@
break;
case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
- final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
- final IAppTransitionAnimationSpecsFuture specsFuture =
- pendingOptions.getSpecsFuture();
- if (specsFuture != null) {
- displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
- specsFuture, pendingOptions.getAnimationStartedListener(),
- animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
- } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
- && specs != null) {
- displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
- specs, pendingOptions.getAnimationStartedListener(),
- pendingOptions.getAnimationFinishedListener(), false);
- } else {
- displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
- pendingOptions.getThumbnail(),
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getWidth(), pendingOptions.getHeight(),
- pendingOptions.getAnimationStartedListener(),
- (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
- if (intent.getSourceBounds() == null) {
- intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
- pendingOptions.getStartY(),
- pendingOptions.getStartX() + pendingOptions.getWidth(),
- pendingOptions.getStartY() + pendingOptions.getHeight()));
- }
- }
+ // TODO(b/397847511): remove the related types from ActivityOptions.
break;
case ANIM_OPEN_CROSS_PROFILE_APPS:
- displayContent.mAppTransition
- .overridePendingAppTransitionStartCrossProfileApps();
options = AnimationOptions.makeCrossProfileAnimOptions();
break;
case ANIM_NONE:
@@ -5457,8 +5393,6 @@
}
private void setVisibility(boolean visible, boolean deferHidingClient) {
- final AppTransition appTransition = getDisplayContent().mAppTransition;
-
// Don't set visibility to false if we were already not visible. This prevents WM from
// adding the app to the closing app list which doesn't make sense for something that is
// already not visible. However, set visibility to true even if we are already visible.
@@ -5478,8 +5412,8 @@
}
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
- token, visible, appTransition, isVisible(), mVisibleRequested,
+ "setAppVisibility(%s, visible=%b): visible=%b mVisibleRequested=%b Callers=%s",
+ token, visible, isVisible(), mVisibleRequested,
Debug.getCallers(6));
// Before setting mVisibleRequested so we can track changes.
@@ -5576,15 +5510,6 @@
updateReportedVisibilityLocked();
}
- @Override
- boolean applyAnimation(LayoutParams lp, @TransitionOldType int transit, boolean enter,
- boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
- if ((mTransitionChangeFlags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
- return false;
- }
- return super.applyAnimation(lp, transit, enter, isVoiceInteraction, sources);
- }
-
/**
* Update visibility to this {@link ActivityRecord}.
*
@@ -6454,6 +6379,7 @@
Slog.w(TAG, "Exception thrown during pause", e);
// Just in case, assume it to be stopped.
mAppStopped = true;
+ mStoppedTime = SystemClock.uptimeMillis();
ProtoLog.v(WM_DEBUG_STATES, "Stop failed; moving to STOPPED: %s", this);
setState(STOPPED, "stopIfPossible");
}
@@ -6487,6 +6413,7 @@
if (isStopping) {
ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPED: %s (stop complete)", this);
+ mStoppedTime = SystemClock.uptimeMillis();
setState(STOPPED, "activityStopped");
}
@@ -6646,9 +6573,7 @@
// starting window is drawn, the transition can start earlier. Exclude finishing and bubble
// because it may be a trampoline.
if (app == null && !finishing && !mLaunchedFromBubble
- && mVisibleRequested && !mDisplayContent.mAppTransition.isReady()
- && !mDisplayContent.mAppTransition.isRunning()
- && mDisplayContent.isNextTransitionForward()) {
+ && mVisibleRequested && mDisplayContent.isNextTransitionForward()) {
// The pending transition state will be cleared after the transition is started, so
// save the state for launching the client later (used by LaunchActivityItem).
mStartingData.mIsTransitionForward = true;
@@ -7135,14 +7060,10 @@
if (theme == 0) {
return false;
}
- final AttributeCache.Entry ent = AttributeCache.instance().get(packageName, theme,
- R.styleable.Window, mWmService.mCurrentUserId);
- if (ent != null) {
- if (ent.array.hasValue(R.styleable.Window_windowSplashScreenBehavior)) {
- return ent.array.getInt(R.styleable.Window_windowSplashScreenBehavior,
- SPLASH_SCREEN_BEHAVIOR_DEFAULT)
- == SPLASH_SCREEN_BEHAVIOR_ICON_PREFERRED;
- }
+ final WindowStyle style = theme == this.theme
+ ? mWindowStyle : mAtmService.getWindowStyle(packageName, theme, mUserId);
+ if (style != null) {
+ return style.mSplashScreenBehavior == SPLASH_SCREEN_BEHAVIOR_ICON_PREFERRED;
}
return false;
}
@@ -7534,7 +7455,6 @@
}
}
- getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
scheduleAnimation();
// Schedule to handle the stopping and finishing activities which the animation is done
@@ -9655,7 +9575,18 @@
&& !mDisplayContent.isSleeping()) {
// Visibility of starting activities isn't calculated until pause-complete, so if
// this is not paused yet, don't consider it ready.
- return false;
+ // However, due to pip1 having an intermediate state, add a special exception here
+ // that skips waiting if the next activity is already visible.
+ final ActivityRecord toResume = isPip2ExperimentEnabled() ? null
+ : mDisplayContent.getActivity((r) -> !r.finishing
+ && r.isVisibleRequested()
+ && !r.isTaskOverlay()
+ && !r.isAlwaysOnTop());
+ if (toResume == null || !toResume.isVisible()) {
+ return false;
+ } else {
+ Slog.i(TAG, "Assuming sync-finish while pausing due to visible target");
+ }
}
return true;
}
@@ -9814,6 +9745,68 @@
int mBackgroundColor;
}
+ static class WindowStyle {
+ private static final int FLAG_IS_TRANSLUCENT = 1;
+ private static final int FLAG_IS_FLOATING = 1 << 1;
+ private static final int FLAG_SHOW_WALLPAPER = 1 << 2;
+ private static final int FLAG_NO_DISPLAY = 1 << 3;
+ private static final int FLAG_DISABLE_PREVIEW = 1 << 4;
+ private static final int FLAG_OPT_OUT_EDGE_TO_EDGE = 1 << 5;
+
+ final int mFlags;
+
+ @SplashScreenBehavior
+ final int mSplashScreenBehavior;
+
+ WindowStyle(TypedArray array) {
+ int flags = 0;
+ if (array.getBoolean(R.styleable.Window_windowIsTranslucent, false)) {
+ flags |= FLAG_IS_TRANSLUCENT;
+ }
+ if (array.getBoolean(R.styleable.Window_windowIsFloating, false)) {
+ flags |= FLAG_IS_FLOATING;
+ }
+ if (array.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
+ flags |= FLAG_SHOW_WALLPAPER;
+ }
+ if (array.getBoolean(R.styleable.Window_windowNoDisplay, false)) {
+ flags |= FLAG_NO_DISPLAY;
+ }
+ if (array.getBoolean(R.styleable.Window_windowDisablePreview, false)) {
+ flags |= FLAG_DISABLE_PREVIEW;
+ }
+ if (array.getBoolean(R.styleable.Window_windowOptOutEdgeToEdgeEnforcement, false)) {
+ flags |= FLAG_OPT_OUT_EDGE_TO_EDGE;
+ }
+ mFlags = flags;
+ mSplashScreenBehavior = array.getInt(R.styleable.Window_windowSplashScreenBehavior, 0);
+ }
+
+ boolean isTranslucent() {
+ return (mFlags & FLAG_IS_TRANSLUCENT) != 0;
+ }
+
+ boolean isFloating() {
+ return (mFlags & FLAG_IS_FLOATING) != 0;
+ }
+
+ boolean showWallpaper() {
+ return (mFlags & FLAG_SHOW_WALLPAPER) != 0;
+ }
+
+ boolean noDisplay() {
+ return (mFlags & FLAG_NO_DISPLAY) != 0;
+ }
+
+ boolean disablePreview() {
+ return (mFlags & FLAG_DISABLE_PREVIEW) != 0;
+ }
+
+ boolean optOutEdgeToEdge() {
+ return (mFlags & FLAG_OPT_OUT_EDGE_TO_EDGE) != 0;
+ }
+ }
+
static class Builder {
private final ActivityTaskManagerService mAtmService;
private WindowProcessController mCallerApp;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 0a57cb5..c243cdc 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -617,6 +617,9 @@
*/
public abstract boolean isBaseOfLockedTask(String packageName);
+ /** Returns the value of {@link android.R.attr#windowNoDisplay} from the given theme. */
+ public abstract boolean isNoDisplay(String packageName, int theme, int userId);
+
/**
* Creates an interface to update configuration for the calling application.
*/
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 819e117..6f83822 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -286,6 +286,7 @@
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wallpaper.WallpaperManagerInternal;
+import com.android.server.wm.utils.WindowStyleCache;
import com.android.wm.shell.Flags;
import java.io.BufferedReader;
@@ -500,6 +501,8 @@
boolean mSuppressResizeConfigChanges;
+ private final WindowStyleCache<ActivityRecord.WindowStyle> mWindowStyleCache =
+ new WindowStyleCache<>(ActivityRecord.WindowStyle::new);
final UpdateConfigurationResult mTmpUpdateConfigurationResult =
new UpdateConfigurationResult();
@@ -2127,6 +2130,26 @@
}
@Override
+ public boolean setTaskIsPerceptible(int taskId, boolean isPerceptible) {
+ enforceTaskPermission("setTaskIsPerceptible()");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
+ MATCH_ATTACHED_TASK_ONLY);
+ if (task == null) {
+ Slog.w(TAG, "setTaskIsPerceptible: No task to set with id=" + taskId);
+ return false;
+ }
+ task.mIsPerceptible = isPerceptible;
+ }
+ return true;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public boolean removeTask(int taskId) {
mAmInternal.enforceCallingPermission(REMOVE_TASKS, "removeTask()");
synchronized (mGlobalLock) {
@@ -5570,6 +5593,16 @@
return mUserManagerInternal;
}
+ @Nullable
+ ActivityRecord.WindowStyle getWindowStyle(String packageName, int theme, int userId) {
+ if (!com.android.window.flags.Flags.cacheWindowStyle()) {
+ final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+ theme, com.android.internal.R.styleable.Window, userId);
+ return ent != null ? new ActivityRecord.WindowStyle(ent.array) : null;
+ }
+ return mWindowStyleCache.get(packageName, theme, userId);
+ }
+
AppWarnings getAppWarningsLocked() {
return mAppWarnings;
}
@@ -6518,6 +6551,7 @@
mCompatModePackages.handlePackageUninstalledLocked(name);
mPackageConfigPersister.onPackageUninstall(name, userId);
}
+ mWindowStyleCache.invalidatePackage(name);
}
@Override
@@ -6534,6 +6568,7 @@
if (mRootWindowContainer == null) return;
mRootWindowContainer.updateActivityApplicationInfo(aInfo);
}
+ mWindowStyleCache.invalidatePackage(aInfo.packageName);
}
@Override
@@ -7433,6 +7468,18 @@
}
@Override
+ public boolean isNoDisplay(String packageName, int theme, int userId) {
+ if (!com.android.window.flags.Flags.cacheWindowStyle()) {
+ final AttributeCache.Entry ent = AttributeCache.instance()
+ .get(packageName, theme, R.styleable.Window, userId);
+ return ent != null
+ && ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
+ }
+ final ActivityRecord.WindowStyle style = getWindowStyle(packageName, theme, userId);
+ return style != null && style.noDisplay();
+ }
+
+ @Override
public PackageConfigurationUpdater createPackageConfigurationUpdater() {
return new PackageConfigurationUpdaterImpl(Binder.getCallingPid(),
ActivityTaskManagerService.this);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index b607b0f..463a92f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -900,108 +900,9 @@
lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);
}
- try {
- if (!proc.hasThread()) {
- throw new RemoteException();
- }
- List<ResultInfo> results = null;
- List<ReferrerIntent> newIntents = null;
- if (andResume) {
- // We don't need to deliver new intents and/or set results if activity is going
- // to pause immediately after launch.
- results = r.results;
- newIntents = r.newIntents;
- }
- if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
- "Launching: " + r + " savedState=" + r.getSavedState()
- + " with results=" + results + " newIntents=" + newIntents
- + " andResume=" + andResume);
- EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
- task.mTaskId, r.shortComponentName);
- updateHomeProcessIfNeeded(r);
- mService.getPackageManagerInternalLocked().notifyPackageUse(
- r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
- mService.getAppWarningsLocked().onStartActivity(r);
-
- final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
- final Configuration overrideConfig = r.getMergedOverrideConfiguration();
- r.setLastReportedConfiguration(procConfig, overrideConfig);
-
- final ActivityWindowInfo activityWindowInfo = r.getActivityWindowInfo();
- r.setLastReportedActivityWindowInfo(activityWindowInfo);
-
- logIfTransactionTooLarge(r.intent, r.getSavedState());
-
- final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();
- if (organizedTaskFragment != null) {
- // Sending TaskFragmentInfo to client to ensure the info is updated before
- // the activity creation.
- mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
- organizedTaskFragment);
- }
-
- // Create activity launch transaction.
- final boolean isTransitionForward = r.isTransitionForward();
- final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
- final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
- final LaunchActivityItem launchActivityItem = new LaunchActivityItem(r.token,
- r.intent, System.identityHashCode(r), r.info,
- procConfig, overrideConfig, deviceId,
- r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
- proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
- results, newIntents, r.takeSceneTransitionInfo(), isTransitionForward,
- proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
- r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken,
- r.initialCallerInfoAccessToken, activityWindowInfo);
-
- // Set desired final state.
- final ActivityLifecycleItem lifecycleItem;
- if (andResume) {
- lifecycleItem = new ResumeActivityItem(r.token, isTransitionForward,
- r.shouldSendCompatFakeFocus());
- } else if (r.isVisibleRequested()) {
- lifecycleItem = new PauseActivityItem(r.token);
- } else {
- lifecycleItem = new StopActivityItem(r.token);
- }
-
- // Schedule transaction.
- if (shouldDispatchLaunchActivityItemIndependently(r.info.packageName, r.getUid())) {
- // LaunchActivityItem has @UnsupportedAppUsage usages.
- // Guard with targetSDK on Android 15+.
- // To not bundle the transaction, dispatch the pending before schedule new
- // transaction.
- mService.getLifecycleManager().dispatchPendingTransaction(proc.getThread());
- }
- mService.getLifecycleManager().scheduleTransactionItems(
- proc.getThread(),
- // Immediately dispatch the transaction, so that if it fails, the server can
- // restart the process and retry now.
- true /* shouldDispatchImmediately */,
- launchActivityItem, lifecycleItem);
-
- if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) {
- // If the seq is increased, there should be something changed (e.g. registered
- // activity configuration).
- proc.setLastReportedConfiguration(procConfig);
- }
- if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
- && mService.mHasHeavyWeightFeature) {
- // This may be a heavy-weight process! Note that the package manager will ensure
- // that only activity can run in the main process of the .apk, which is the only
- // thing that will be considered heavy-weight.
- if (proc.mName.equals(proc.mInfo.packageName)) {
- if (mService.mHeavyWeightProcess != null
- && mService.mHeavyWeightProcess != proc) {
- Slog.w(TAG, "Starting new heavy weight process " + proc
- + " when already running "
- + mService.mHeavyWeightProcess);
- }
- mService.setHeavyWeightProcess(r);
- }
- }
-
- } catch (RemoteException e) {
+ final RemoteException e = tryRealStartActivityInner(
+ task, r, proc, activityClientController, andResume);
+ if (e != null) {
if (r.launchFailed) {
// This is the second time we failed -- finish activity and give up.
Slog.e(TAG, "Second failure launching "
@@ -1024,7 +925,7 @@
r.launchFailed = false;
- // TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
+ // Resume or pause requests are done as part of launch transaction,
// so updating the state should be done accordingly.
if (andResume && readyToResume()) {
// As part of the process of launching, ActivityThread also performs
@@ -1064,6 +965,122 @@
return true;
}
+ /** @return {@link RemoteException} if the app process failed to handle the activity start. */
+ @Nullable
+ private RemoteException tryRealStartActivityInner(
+ @NonNull Task task,
+ @NonNull ActivityRecord r,
+ @NonNull WindowProcessController proc,
+ @Nullable IActivityClientController activityClientController,
+ boolean andResume) {
+ if (!proc.hasThread()) {
+ return new RemoteException();
+ }
+ List<ResultInfo> results = null;
+ List<ReferrerIntent> newIntents = null;
+ if (andResume) {
+ // We don't need to deliver new intents and/or set results if activity is going
+ // to pause immediately after launch.
+ results = r.results;
+ newIntents = r.newIntents;
+ }
+ if (DEBUG_SWITCH) {
+ Slog.v(TAG_SWITCH,
+ "Launching: " + r + " savedState=" + r.getSavedState()
+ + " with results=" + results + " newIntents=" + newIntents
+ + " andResume=" + andResume);
+ }
+ EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
+ task.mTaskId, r.shortComponentName);
+ updateHomeProcessIfNeeded(r);
+ mService.getPackageManagerInternalLocked().notifyPackageUse(
+ r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
+ mService.getAppWarningsLocked().onStartActivity(r);
+
+ final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
+ final Configuration overrideConfig = r.getMergedOverrideConfiguration();
+ r.setLastReportedConfiguration(procConfig, overrideConfig);
+
+ final ActivityWindowInfo activityWindowInfo = r.getActivityWindowInfo();
+ r.setLastReportedActivityWindowInfo(activityWindowInfo);
+
+ logIfTransactionTooLarge(r.intent, r.getSavedState());
+
+ final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();
+ if (organizedTaskFragment != null) {
+ // Sending TaskFragmentInfo to client to ensure the info is updated before
+ // the activity creation.
+ mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
+ organizedTaskFragment);
+ }
+
+ // Create activity launch transaction.
+ final boolean isTransitionForward = r.isTransitionForward();
+ final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
+ final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
+ final LaunchActivityItem launchActivityItem = new LaunchActivityItem(r.token,
+ r.intent, System.identityHashCode(r), r.info,
+ procConfig, overrideConfig, deviceId,
+ r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
+ proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
+ results, newIntents, r.takeSceneTransitionInfo(), isTransitionForward,
+ proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
+ r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken,
+ r.initialCallerInfoAccessToken, activityWindowInfo);
+
+ // Set desired final state.
+ final ActivityLifecycleItem lifecycleItem;
+ if (andResume) {
+ lifecycleItem = new ResumeActivityItem(r.token, isTransitionForward,
+ r.shouldSendCompatFakeFocus());
+ } else if (r.isVisibleRequested()) {
+ lifecycleItem = new PauseActivityItem(r.token);
+ } else {
+ lifecycleItem = new StopActivityItem(r.token);
+ }
+
+ // Schedule transaction.
+ if (shouldDispatchLaunchActivityItemIndependently(r.info.packageName, r.getUid())) {
+ // LaunchActivityItem has @UnsupportedAppUsage usages.
+ // Guard with targetSDK on Android 15+.
+ // To not bundle the transaction, dispatch the pending before schedule new
+ // transaction.
+ mService.getLifecycleManager().dispatchPendingTransaction(proc.getThread());
+ }
+ try {
+ mService.getLifecycleManager().scheduleTransactionItems(
+ proc.getThread(),
+ // Immediately dispatch the transaction, so that if it fails, the server can
+ // restart the process and retry now.
+ true /* shouldDispatchImmediately */,
+ launchActivityItem, lifecycleItem);
+ } catch (RemoteException e) {
+ return e;
+ }
+
+ if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) {
+ // If the seq is increased, there should be something changed (e.g. registered
+ // activity configuration).
+ proc.setLastReportedConfiguration(procConfig);
+ }
+ if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
+ && mService.mHasHeavyWeightFeature) {
+ // This may be a heavy-weight process! Note that the package manager will ensure
+ // that only activity can run in the main process of the .apk, which is the only
+ // thing that will be considered heavy-weight.
+ if (proc.mName.equals(proc.mInfo.packageName)) {
+ if (mService.mHeavyWeightProcess != null
+ && mService.mHeavyWeightProcess != proc) {
+ Slog.w(TAG, "Starting new heavy weight process " + proc
+ + " when already running "
+ + mService.mHeavyWeightProcess);
+ }
+ mService.setHeavyWeightProcess(r);
+ }
+ }
+ return null;
+ }
+
void updateHomeProcessIfNeeded(@NonNull ActivityRecord r) {
if (!r.isActivityTypeHome()) return;
// Make sure that we use the bottom most activity from the same package, because the home
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
index 15c0789..3535a96 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
@@ -36,8 +36,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
-
-import com.android.window.flags.Flags;
+import android.window.DesktopModeFlags;
/**
* Encapsulate app compat policy logic related to aspect ratio.
@@ -298,7 +297,8 @@
// Camera compat mode is an exception to this, where the activity is letterboxed
// to an aspect ratio commonly found on phones, e.g. 16:9, to avoid issues like
// stretching of the camera preview.
- || (Flags.ignoreAspectRatioRestrictionsForResizeableFreeformActivities()
+ || (DesktopModeFlags
+ .IGNORE_ASPECT_RATIO_RESTRICTIONS_FOR_RESIZEABLE_FREEFORM_ACTIVITIES.isTrue()
&& task.getWindowingMode() == WINDOWING_MODE_FREEFORM
&& !mActivityRecord.shouldCreateAppCompatDisplayInsets()
&& !AppCompatCameraPolicy.shouldCameraCompatControlAspectRatio(
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 094ad18..d652ea1 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -281,6 +281,10 @@
} else if (hasTranslucentActivity(currentActivity, prevActivities)) {
// skip if one of participant activity is translucent
backType = BackNavigationInfo.TYPE_CALLBACK;
+ } else if (!allActivitiesHaveProcesses(prevActivities)) {
+ // Skip if one of previous activity has no process. Restart process can be slow, and
+ // the final hierarchy could be different.
+ backType = BackNavigationInfo.TYPE_CALLBACK;
} else if (prevActivities.size() > 0
&& requestOverride == SystemOverrideOnBackInvokedCallback.OVERRIDE_UNDEFINED) {
if ((!isOccluded || isAllActivitiesCanShowWhenLocked(prevActivities))
@@ -603,6 +607,17 @@
return false;
}
+ private static boolean allActivitiesHaveProcesses(
+ @NonNull ArrayList<ActivityRecord> prevActivities) {
+ for (int i = prevActivities.size() - 1; i >= 0; --i) {
+ final ActivityRecord test = prevActivities.get(i);
+ if (!test.hasProcess()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private static boolean isAllActivitiesCanShowWhenLocked(
@NonNull ArrayList<ActivityRecord> prevActivities) {
for (int i = prevActivities.size() - 1; i >= 0; --i) {
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index ac98792..b6f74a0 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -75,8 +75,8 @@
return RESULT_SKIP;
}
if (com.android.window.flags.Flags.fixLayoutExistingTask()
- && task.getOrganizedTask() != null) {
- appendLog("task is organized, skipping");
+ && task.getCreatedByOrganizerTask() != null) {
+ appendLog("has created-by-organizer-task, skipping");
return RESULT_SKIP;
}
@@ -111,6 +111,11 @@
return RESULT_SKIP;
}
+ if ((options == null || options.getLaunchBounds() == null) && task.hasOverrideBounds()) {
+ appendLog("current task has bounds set, not overriding");
+ return RESULT_SKIP;
+ }
+
DesktopModeBoundsCalculator.updateInitialBounds(task, layout, activity, options,
outParams.mBounds, this::appendLog);
appendLog("final desktop mode task bounds set to %s", outParams.mBounds);
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index b932ef3..6718ae4 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -748,14 +748,9 @@
&& policy.okToAnimate(true /* ignoreScreenOn */)) {
return false;
}
- // Consider unoccluding only when all unknown visibilities have been
- // resolved, as otherwise we just may be starting another occluding activity.
- final boolean isUnoccluding =
- mDisplayContent.mAppTransition.isUnoccluding()
- && mDisplayContent.mUnknownAppVisibilityController.allResolved();
- // If keyguard is showing, or we're unoccluding, force the keyguard's orientation,
+ // Use keyguard's orientation if it is showing and not occluded
// even if SystemUI hasn't updated the attrs yet.
- if (policy.isKeyguardShowingAndNotOccluded() || isUnoccluding) {
+ if (policy.isKeyguardShowingAndNotOccluded()) {
return true;
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7eebbba..214a3a1 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -88,7 +88,6 @@
import static android.window.DisplayAreaOrganizer.FEATURE_IME;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
-import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_BOOT;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_CONTENT_RECORDING;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_FOCUS;
@@ -369,12 +368,6 @@
private MetricsLogger mMetricsLogger;
- /**
- * List of clients without a transtiton animation that we notify once we are done
- * transitioning since they won't be notified through the app window animator.
- */
- final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
-
// Mapping from a token IBinder to a WindowToken object on this display.
private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
@@ -829,28 +822,36 @@
*/
private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
final ActivityRecord focusedApp = mFocusedApp;
+ final boolean canReceiveKeys = w.canReceiveKeys();
ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
- w, w.mAttrs.flags, w.canReceiveKeys(),
+ w, w.mAttrs.flags, canReceiveKeys,
w.canReceiveKeysReason(false /* fromUserTouch */));
- if (!w.canReceiveKeys()) {
+ if (!canReceiveKeys) {
return false;
}
- // When switching the app task, we keep the IME window visibility for better
- // transitioning experiences.
- // However, in case IME created a child window or the IME selection dialog without
- // dismissing during the task switching to keep the window focus because IME window has
- // higher window hierarchy, we don't give it focus if the next IME layering target
- // doesn't request IME visible.
- if (w.mIsImWindow && w.isChildWindow() && (mImeLayeringTarget == null
- || !mImeLayeringTarget.isRequestedVisible(ime()))) {
- return false;
- }
- if (w.mAttrs.type == TYPE_INPUT_METHOD_DIALOG && mImeLayeringTarget != null
- && !(mImeLayeringTarget.isRequestedVisible(ime())
- && mImeLayeringTarget.isVisibleRequested())) {
- return false;
+ // IME windows remain visibleRequested while switching apps to maintain a smooth animation.
+ // This persists until the new app is focused, so they can be visibleRequested despite not
+ // being visible to the user (i.e. occluded). These rank higher in the window hierarchy than
+ // app windows, so they will always be considered first. To avoid having the focus stuck,
+ // an IME window (child or not) cannot be focused if the IME parent is not visible. However,
+ // child windows also require the IME to be visible in the current app.
+ if (w.mIsImWindow) {
+ final boolean imeParentVisible = mInputMethodSurfaceParentWindow != null
+ && mInputMethodSurfaceParentWindow.isVisibleRequested();
+ if (!imeParentVisible) {
+ ProtoLog.v(WM_DEBUG_FOCUS, "findFocusedWindow: IME window not focusable as"
+ + " IME parent is not visible");
+ return false;
+ }
+
+ if (w.isChildWindow()
+ && !getInsetsStateController().getImeSourceProvider().isImeShowing()) {
+ ProtoLog.v(WM_DEBUG_FOCUS, "findFocusedWindow: IME child window not focusable as"
+ + " IME is not visible");
+ return false;
+ }
}
final ActivityRecord activity = w.mActivityRecord;
@@ -1171,8 +1172,6 @@
mFixedRotationTransitionListener = new FixedRotationTransitionListener(mDisplayId);
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
- mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
- mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
mTransitionController.registerLegacyListener(mFixedRotationTransitionListener);
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
mRemoteDisplayChangeController = new RemoteDisplayChangeController(this);
@@ -2858,13 +2857,6 @@
return isVisible() && !mRemoved && !mRemoving;
}
- @Override
- void onAppTransitionDone() {
- super.onAppTransitionDone();
- mWmService.mWindowsChanged = true;
- onTransitionFinished();
- }
-
void onTransitionFinished() {
// If the transition finished callback cannot match the token for some reason, make sure the
// rotated state is cleared if it is already invisible.
@@ -3385,9 +3377,7 @@
mDeferredRemoval = false;
try {
mUnknownAppVisibilityController.clear();
- mAppTransition.removeAppTransitionTimeoutCallbacks();
mTransitionController.unregisterLegacyListener(mFixedRotationTransitionListener);
- handleAnimatingStoppedAndTransition();
mDeviceStateController.unregisterDeviceStateCallback(mDeviceStateConsumer);
super.removeImmediately();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
@@ -3570,11 +3560,7 @@
mDisplayRotation.dumpDebug(proto, DISPLAY_ROTATION);
mDisplayFrames.dumpDebug(proto, DISPLAY_FRAMES);
proto.write(MIN_SIZE_OF_RESIZEABLE_TASK_DP, mMinSizeOfResizeableTaskDp);
- if (mTransitionController.isShellTransitionsEnabled()) {
- mTransitionController.dumpDebugLegacy(proto, APP_TRANSITION);
- } else {
- mAppTransition.dumpDebug(proto, APP_TRANSITION);
- }
+ mTransitionController.dumpDebugLegacy(proto, APP_TRANSITION);
if (mFocusedApp != null) {
mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
}
@@ -3845,7 +3831,6 @@
if (mTmpWindow == null) {
ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: No focusable windows, display=%d",
getDisplayId());
- return null;
}
return mTmpWindow;
}
@@ -5635,61 +5620,20 @@
* @see AppTransition#prepareAppTransition
*/
void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit,
- @WindowManager.TransitionFlags int flags) {
- prepareAppTransition(transit, flags);
- mTransitionController.requestTransitionIfNeeded(transit, flags, null /* trigger */, this);
+ @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) {
+ mTransitionController.requestTransitionIfNeeded(transit, flags, trigger, this);
}
void executeAppTransition() {
mTransitionController.setReady(this);
- if (mAppTransition.isTransitionSet()) {
- ProtoLog.w(WM_DEBUG_APP_TRANSITIONS,
- "Execute app transition: %s, displayId: %d Callers=%s",
- mAppTransition, mDisplayId, Debug.getCallers(5));
- mAppTransition.setReady();
- mWmService.mWindowPlacerLocked.requestTraversal();
- }
- }
-
- /**
- * Update pendingLayoutChanges after app transition has finished.
- */
- void handleAnimatingStoppedAndTransition() {
- int changes = 0;
-
- mAppTransition.setIdle();
-
- for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
- final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
- mAppTransition.notifyAppTransitionFinishedLocked(token);
- }
- mNoAnimationNotifyOnTransitionFinished.clear();
-
- mWallpaperController.hideDeferredWallpapersIfNeededLegacy();
-
- onAppTransitionDone();
-
- changes |= FINISH_LAYOUT_REDO_LAYOUT;
- ProtoLog.v(WM_DEBUG_WALLPAPER, "Wallpaper layer changed: assigning layers + relayout");
- computeImeTarget(true /* updateImeTarget */);
- mWallpaperMayChange = true;
- // Since the window list has been rebuilt, focus might have to be recomputed since the
- // actual order of windows might have changed again.
- mWmService.mFocusMayChange = true;
-
- pendingLayoutChanges |= changes;
}
/** Check if pending app transition is for activity / task launch. */
boolean isNextTransitionForward() {
// TODO(b/191375840): decouple "forwardness" from transition system.
- if (mTransitionController.isShellTransitionsEnabled()) {
- @WindowManager.TransitionType int type =
- mTransitionController.getCollectingTransitionType();
- return type == TRANSIT_OPEN || type == TRANSIT_TO_FRONT;
- }
- return mAppTransition.containsTransitRequest(TRANSIT_OPEN)
- || mAppTransition.containsTransitRequest(TRANSIT_TO_FRONT);
+ final @WindowManager.TransitionType int type =
+ mTransitionController.getCollectingTransitionType();
+ return type == TRANSIT_OPEN || type == TRANSIT_TO_FRONT;
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index fbe8501..7aa2101 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -631,7 +631,6 @@
mHandler.post(mAppTransitionFinished);
}
};
- displayContent.mAppTransition.registerListenerLocked(mAppTransitionListener);
displayContent.mTransitionController.registerLegacyListener(mAppTransitionListener);
// TODO: Make it can take screenshot on external display
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 6091b83..6d73739 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -250,7 +250,7 @@
// to the locked state before holding the sleep token again
if (!ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS) {
dc.requestTransitionAndLegacyPrepare(
- TRANSIT_TO_FRONT, TRANSIT_FLAG_KEYGUARD_APPEARING);
+ TRANSIT_TO_FRONT, TRANSIT_FLAG_KEYGUARD_APPEARING, /* trigger= */ null);
}
dc.mWallpaperController.adjustWallpaperWindows();
dc.executeAppTransition();
diff --git a/services/core/java/com/android/server/wm/PresentationController.java b/services/core/java/com/android/server/wm/PresentationController.java
index 6946343..b3cff9c 100644
--- a/services/core/java/com/android/server/wm/PresentationController.java
+++ b/services/core/java/com/android/server/wm/PresentationController.java
@@ -56,11 +56,6 @@
ProtoLog.v(WmProtoLogGroups.WM_DEBUG_PRESENTATION, "Presentation added to display %d: %s",
win.getDisplayId(), win);
mPresentingDisplayIds.add(win.getDisplayId());
- if (enablePresentationForConnectedDisplays()) {
- // A presentation hides all activities behind on the same display.
- win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
- /*notifyClients=*/ true);
- }
win.mWmService.mDisplayManagerInternal.onPresentation(displayId, /*isShown=*/ true);
}
@@ -76,11 +71,6 @@
if (displayIdIndex != -1) {
mPresentingDisplayIds.remove(displayIdIndex);
}
- if (enablePresentationForConnectedDisplays()) {
- // A presentation hides all activities behind on the same display.
- win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
- /*notifyClients=*/ true);
- }
win.mWmService.mDisplayManagerInternal.onPresentation(displayId, /*isShown=*/ false);
}
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 40f16c1..f309372 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2103,10 +2103,6 @@
removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);
}
- // Set a transition to ensure that we don't immediately try and update the visibility
- // of the activity entering PIP
- r.getDisplayContent().prepareAppTransition(TRANSIT_NONE);
-
transitionController.collect(task);
// Defer the windowing mode change until after the transition to prevent the activity
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6b3499a..6cd1336 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -54,7 +54,6 @@
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
-import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -504,6 +503,17 @@
int mOffsetYForInsets;
/**
+ * When set to true, the task will be kept at a PERCEPTIBLE_APP_ADJ, and downgraded
+ * to PREVIOUS_APP_ADJ if not in foreground for a period of time.
+ * One example use case is for desktop form factors, where it is important keep tasks in the
+ * perceptible state (rather than cached where it may be frozen) when a user moves it to the
+ * foreground.
+ * On startup, restored Tasks will not be perceptible, until user actually interacts with it
+ * (i.e. brings it to the foreground)
+ */
+ boolean mIsPerceptible = false;
+
+ /**
* Whether the compatibility overrides that change the resizability of the app should be allowed
* for the specific app.
*/
@@ -1647,8 +1657,7 @@
// Prevent the transition from being executed too early if the top activity is
// resumed but the mVisibleRequested of any other activity is true, the transition
// should wait until next activity resumed.
- if (r.isState(RESUMED) || (r.isVisible()
- && !mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CLOSE))) {
+ if (r.isState(RESUMED) || r.isVisible()) {
r.finishIfPossible(reason, false /* oomAdj */);
} else {
r.destroyIfPossible(reason);
@@ -2324,11 +2333,6 @@
mLastSurfaceSize.set(width, height);
}
- @VisibleForTesting
- boolean isInChangeTransition() {
- return AppTransition.isChangeTransitOld(mTransit);
- }
-
@Override
void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
@@ -3854,6 +3858,7 @@
pw.print(ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture);
pw.print(" isResizeable="); pw.println(isResizeable());
+ pw.print(" isPerceptible="); pw.println(mIsPerceptible);
pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
pw.print(prefix); pw.println(" isTrimmable=" + mIsTrimmableFromRecents);
@@ -5293,11 +5298,9 @@
// Place a new activity at top of root task, so it is next to interact with the user.
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
- mDisplayContent.prepareAppTransition(TRANSIT_NONE);
mTaskSupervisor.mNoAnimActivities.add(r);
mTransitionController.setNoAnimation(r);
} else {
- mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
mTaskSupervisor.mNoAnimActivities.remove(r);
}
if (newTask && !r.mLaunchTaskBehind) {
@@ -5477,7 +5480,8 @@
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
Task finishedTask = r.getTask();
- mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED);
+ mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED,
+ finishedTask);
r.finishIfPossible(reason, false /* oomAdj */);
// Also terminate any activities below it that aren't yet stopped, to avoid a situation
@@ -5695,7 +5699,6 @@
ActivityOptions.abort(options);
}
}
- mDisplayContent.prepareAppTransition(transit);
}
final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
@@ -5747,12 +5750,9 @@
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
if (noAnimation) {
- mDisplayContent.prepareAppTransition(TRANSIT_NONE);
mTaskSupervisor.mNoAnimActivities.add(top);
- if (mTransitionController.isShellTransitionsEnabled()) {
- mTransitionController.collect(top);
- mTransitionController.setNoAnimation(top);
- }
+ mTransitionController.collect(top);
+ mTransitionController.setNoAnimation(top);
ActivityOptions.abort(options);
} else {
updateTransitLocked(TRANSIT_TO_FRONT, options);
@@ -5862,10 +5862,6 @@
moveTaskToBackInner(tr, transition);
});
} else {
- // Skip the transition for pinned task.
- if (!inPinnedWindowingMode()) {
- mDisplayContent.prepareAppTransition(TRANSIT_TO_BACK);
- }
moveTaskToBackInner(tr, null /* transition */);
}
return true;
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index a698a9e..80095b3 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -44,10 +44,6 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OPEN;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_STATES;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
@@ -56,7 +52,6 @@
import static com.android.server.wm.ActivityRecord.State.STOPPING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
@@ -1682,36 +1677,15 @@
final DisplayContent dc = taskDisplayArea.mDisplayContent;
if (prev != null) {
if (prev.finishing) {
- if (DEBUG_TRANSITION) {
- Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev);
- }
if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {
anim = false;
- dc.prepareAppTransition(TRANSIT_NONE);
- } else {
- dc.prepareAppTransition(TRANSIT_CLOSE);
}
prev.setVisibility(false);
- } else {
- if (DEBUG_TRANSITION) {
- Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);
- }
- if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
- anim = false;
- dc.prepareAppTransition(TRANSIT_NONE);
- } else {
- dc.prepareAppTransition(TRANSIT_OPEN,
- next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);
- }
- }
- } else {
- if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
- if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
+ } else if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
anim = false;
- dc.prepareAppTransition(TRANSIT_NONE);
- } else {
- dc.prepareAppTransition(TRANSIT_OPEN);
}
+ } else if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
+ anim = false;
}
if (anim) {
@@ -1910,14 +1884,17 @@
if (!hasDirectChildActivities()) {
return false;
}
- if (mResumedActivity != null && mTransitionController.isTransientLaunch(mResumedActivity)) {
+ if (mResumedActivity != null && !mResumedActivity.finishing
+ && mTransitionController.isTransientLaunch(mResumedActivity)) {
// Even if the transient activity is occluded, defer pausing (addToStopping will still
// be called) it until the transient transition is done. So the current resuming
// activity won't need to wait for additional pause complete.
+ ProtoLog.d(WM_DEBUG_STATES, "startPausing: Skipping pause for transient "
+ + "resumed activity=%s", mResumedActivity);
return false;
}
- ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,
+ ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag=%s mResumedActivity=%s", this,
mResumedActivity);
if (mPausingActivity != null) {
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index e3a5b66..6c7d979 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -384,7 +384,7 @@
// an existing task.
adjustBoundsToAvoidConflictInDisplayArea(taskDisplayArea, outParams.mBounds);
}
- } else {
+ } else if (task == null || !task.hasOverrideBounds()) {
if (source != null && source.inFreeformWindowingMode()
&& resolvedMode == WINDOWING_MODE_FREEFORM
&& outParams.mBounds.isEmpty()
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 5217a75..fd7d96a 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1640,6 +1640,12 @@
mSyncEngine.setSyncMethod(syncId, BLASTSyncEngine.METHOD_BLAST);
}
mSyncEngine.addToSyncSet(syncId, target);
+ } else {
+ // If there is an existing sync group for the commit-at-end activity,
+ // enforce BLAST sync method for its windows, before resuming config dispatch.
+ target.forAllWindows(windowState -> {
+ windowState.mSyncMethodOverride = BLASTSyncEngine.METHOD_BLAST;
+ }, true /* traverseTopToBottom */);
}
// Reset surface state here (since it was skipped in buildFinishTransaction). Since
// we are resuming config to the "current" state, we have to calculate the matching
@@ -2026,23 +2032,18 @@
if (mOverrideOptions == null) {
return;
}
-
- if (!Flags.moveAnimationOptionsToChange()) {
- info.setAnimationOptions(mOverrideOptions);
- } else {
- final List<TransitionInfo.Change> changes = info.getChanges();
- for (int i = changes.size() - 1; i >= 0; --i) {
- final WindowContainer<?> container = mTargets.get(i).mContainer;
- if (container.asActivityRecord() != null
- || shouldApplyAnimOptionsToTask(container.asTask())) {
- changes.get(i).setAnimationOptions(mOverrideOptions);
- // TODO(b/295805497): Extract mBackgroundColor from AnimationOptions.
- changes.get(i).setBackgroundColor(mOverrideOptions.getBackgroundColor());
- } else if (shouldApplyAnimOptionsToEmbeddedTf(container.asTaskFragment())) {
- // We only override AnimationOptions because backgroundColor should be from
- // TaskFragmentAnimationParams.
- changes.get(i).setAnimationOptions(mOverrideOptions);
- }
+ final List<TransitionInfo.Change> changes = info.getChanges();
+ for (int i = changes.size() - 1; i >= 0; --i) {
+ final WindowContainer<?> container = mTargets.get(i).mContainer;
+ if (container.asActivityRecord() != null
+ || shouldApplyAnimOptionsToTask(container.asTask())) {
+ changes.get(i).setAnimationOptions(mOverrideOptions);
+ // TODO(b/295805497): Extract mBackgroundColor from AnimationOptions.
+ changes.get(i).setBackgroundColor(mOverrideOptions.getBackgroundColor());
+ } else if (shouldApplyAnimOptionsToEmbeddedTf(container.asTaskFragment())) {
+ // We only override AnimationOptions because backgroundColor should be from
+ // TaskFragmentAnimationParams.
+ changes.get(i).setAnimationOptions(mOverrideOptions);
}
}
updateActivityTargetForCrossProfileAnimation(info);
@@ -2933,9 +2934,6 @@
final AnimationOptions animOptionsForActivityTransition =
calculateAnimationOptionsForActivityTransition(type, sortedTargets);
- if (!Flags.moveAnimationOptionsToChange() && animOptionsForActivityTransition != null) {
- out.setAnimationOptions(animOptionsForActivityTransition);
- }
final ArraySet<WindowContainer> occludedAtEndContainers = new ArraySet<>();
// Convert all the resolved ChangeInfos into TransactionInfo.Change objects in order.
@@ -3059,27 +3057,25 @@
}
AnimationOptions animOptions = null;
- if (Flags.moveAnimationOptionsToChange()) {
- if (activityRecord != null && animOptionsForActivityTransition != null) {
- animOptions = animOptionsForActivityTransition;
- } else if (Flags.activityEmbeddingOverlayPresentationFlag()
- && isEmbeddedTaskFragment) {
- final TaskFragmentAnimationParams params = taskFragment.getAnimationParams();
- if (params.hasOverrideAnimation()) {
- // Only set AnimationOptions if there's any animation override.
- // We use separated field for backgroundColor, and
- // AnimationOptions#backgroundColor will be removed in long term.
- animOptions = AnimationOptions.makeCustomAnimOptions(
- taskFragment.getTask().getBasePackageName(),
- params.getOpenAnimationResId(), params.getChangeAnimationResId(),
- params.getCloseAnimationResId(), 0 /* backgroundColor */,
- false /* overrideTaskTransition */);
- animOptions.setUserId(taskFragment.getTask().mUserId);
- }
+ if (activityRecord != null && animOptionsForActivityTransition != null) {
+ animOptions = animOptionsForActivityTransition;
+ } else if (Flags.activityEmbeddingOverlayPresentationFlag()
+ && isEmbeddedTaskFragment) {
+ final TaskFragmentAnimationParams params = taskFragment.getAnimationParams();
+ if (params.hasOverrideAnimation()) {
+ // Only set AnimationOptions if there's any animation override.
+ // We use separated field for backgroundColor, and
+ // AnimationOptions#backgroundColor will be removed in long term.
+ animOptions = AnimationOptions.makeCustomAnimOptions(
+ taskFragment.getTask().getBasePackageName(),
+ params.getOpenAnimationResId(), params.getChangeAnimationResId(),
+ params.getCloseAnimationResId(), 0 /* backgroundColor */,
+ false /* overrideTaskTransition */);
+ animOptions.setUserId(taskFragment.getTask().mUserId);
}
- if (animOptions != null) {
- change.setAnimationOptions(animOptions);
- }
+ }
+ if (animOptions != null) {
+ change.setAnimationOptions(animOptions);
}
if (activityRecord != null) {
diff --git a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
index 2428836..e612d8e 100644
--- a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
+++ b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
@@ -20,6 +20,7 @@
import static android.graphics.Matrix.MSCALE_Y;
import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
+import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_TPL;
@@ -35,6 +36,7 @@
import android.util.IntArray;
import android.util.Pair;
import android.util.Size;
+import android.util.SparseArray;
import android.view.InputWindowHandle;
import android.window.ITrustedPresentationListener;
import android.window.TrustedPresentationThresholds;
@@ -251,7 +253,7 @@
Rect tmpLogicalDisplaySize = new Rect();
Matrix tmpInverseMatrix = new Matrix();
float[] tmpMatrix = new float[9];
- Region coveredRegionsAbove = new Region();
+ SparseArray<Region> coveredRegionsAboveByDisplay = new SparseArray<>();
long currTimeMs = System.currentTimeMillis();
ProtoLog.v(WM_DEBUG_TPL, "Checking %d windows", mLastWindowHandles.first.length);
@@ -262,7 +264,7 @@
ProtoLog.v(WM_DEBUG_TPL, "Skipping %s", windowHandle.name);
continue;
}
- var displayFound = false;
+ int displayId = INVALID_DISPLAY;
tmpRectF.set(windowHandle.frame);
for (var displayHandle : mLastWindowHandles.second) {
if (displayHandle.mDisplayId == windowHandle.displayId) {
@@ -273,17 +275,18 @@
tmpLogicalDisplaySize.set(0, 0, displayHandle.mLogicalSize.getWidth(),
displayHandle.mLogicalSize.getHeight());
tmpRect.intersect(tmpLogicalDisplaySize);
- displayFound = true;
+ displayId = displayHandle.mDisplayId;
break;
}
}
- if (!displayFound) {
+ if (displayId == INVALID_DISPLAY) {
ProtoLog.v(WM_DEBUG_TPL, "Skipping %s, no associated display %d", windowHandle.name,
windowHandle.displayId);
continue;
}
+ Region coveredRegionsAbove = coveredRegionsAboveByDisplay.get(displayId, new Region());
var listeners = mRegisteredListeners.get(windowHandle.getWindowToken());
if (listeners != null) {
Region region = new Region();
@@ -304,6 +307,7 @@
}
coveredRegionsAbove.op(tmpRect, Region.Op.UNION);
+ coveredRegionsAboveByDisplay.put(displayId, coveredRegionsAbove);
ProtoLog.v(WM_DEBUG_TPL, "coveredRegionsAbove updated with %s frame:%s region:%s",
windowHandle.name, tmpRect.toShortString(), coveredRegionsAbove);
}
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 7c88abc..9506ffe 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -217,8 +217,7 @@
}
// If in a transition, defer commits for activities that are going invisible
- if (!visible && (mTransitionController.inTransition()
- || getDisplayContent().mAppTransition.isRunning())) {
+ if (!visible && mTransitionController.inTransition()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 45202a2..d0d2067 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -16,9 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
@@ -29,24 +26,15 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
-import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.UserHandle.USER_NULL;
import static android.view.SurfaceControl.Transaction;
import static android.view.WindowInsets.Type.InsetsType;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
-import static android.window.TaskFragmentAnimationParams.DEFAULT_ANIMATION_BACKGROUND_COLOR;
import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ANIM;
-import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_SYNC_ENGINE;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
-import static com.android.server.wm.AppTransition.isActivityTransitOld;
-import static com.android.server.wm.AppTransition.isTaskFragmentTransitOld;
-import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -65,7 +53,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_AFTER_ANIM;
import android.annotation.CallSuper;
import android.annotation.ColorInt;
@@ -81,10 +68,8 @@
import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Pair;
import android.util.Pools;
import android.util.RotationUtils;
import android.util.Slog;
@@ -102,14 +87,11 @@
import android.view.SurfaceControlViewHost;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
-import android.view.animation.Animation;
import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.graphics.ColorUtils;
import com.android.internal.protolog.ProtoLog;
-import com.android.internal.protolog.common.LogLevel;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.wm.SurfaceAnimator.Animatable;
import com.android.server.wm.SurfaceAnimator.AnimationType;
@@ -1315,31 +1297,12 @@
}
/**
- * Returns true if the container or one of its children as some content it can display or wants
- * to display (e.g. app views or saved surface).
- *
- * NOTE: While this method will return true if the there is some content to display, it doesn't
- * mean the container is visible. Use {@link #isVisible()} to determine if the container is
- * visible.
- */
- boolean hasContentToDisplay() {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer wc = mChildren.get(i);
- if (wc.hasContentToDisplay()) {
- return true;
- }
- }
- return false;
- }
-
- /**
* Returns true if the container or one of its children is considered visible from the
* WindowManager perspective which usually means valid surface and some other internal state
* are true.
*
* NOTE: While this method will return true if the surface is visible, it doesn't mean the
- * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
- * the container has any content to display.
+ * client has actually displayed any content.
*/
boolean isVisible() {
// TODO: Will this be more correct if it checks the visibility of its parents?
@@ -1480,13 +1443,6 @@
}
}
- void onAppTransitionDone() {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer wc = mChildren.get(i);
- wc.onAppTransitionDone();
- }
- }
-
/**
* Called when this container or one of its descendants changed its requested orientation, and
* wants this container to handle it or pass it to its parent.
@@ -3039,264 +2995,10 @@
getRelativePosition(outPosition);
}
- /**
- * Applies the app transition animation according the given the layout properties in the
- * window hierarchy.
- *
- * @param lp The layout parameters of the window.
- * @param transit The app transition type indicates what kind of transition to be applied.
- * @param enter Whether the app transition is entering transition or not.
- * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
- * @param sources {@link ActivityRecord}s which causes this app transition animation.
- *
- * @return {@code true} when the container applied the app transition, {@code false} if the
- * app transition is disabled or skipped.
- *
- * @see #getAnimationAdapter
- */
- boolean applyAnimation(WindowManager.LayoutParams lp, @TransitionOldType int transit,
- boolean enter, boolean isVoiceInteraction,
- @Nullable ArrayList<WindowContainer> sources) {
- if (mWmService.mDisableTransitionAnimation) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
- "applyAnimation: transition animation is disabled or skipped. "
- + "container=%s", this);
- cancelAnimation();
- return false;
- }
-
- // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
- // to animate and it can cause strange artifacts when we unfreeze the display if some
- // different animation is running.
- try {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
- if (okToAnimate()) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
- "applyAnimation: transit=%s, enter=%b, wc=%s",
- AppTransition.appTransitionOldToString(transit), enter, this);
- applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
- } else {
- cancelAnimation();
- }
- } finally {
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- }
-
- return isAnimating();
- }
-
- /**
- * Gets the {@link AnimationAdapter} according the given window layout properties in the window
- * hierarchy.
- *
- * @return The return value will always contain two elements, one for normal animations and the
- * other for thumbnail animation, both can be {@code null}.
- *
- * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
- * @See LocalAnimationAdapter
- */
- Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
- @TransitionOldType int transit, boolean enter, boolean isVoiceInteraction) {
- final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
- final int appRootTaskClipMode = getDisplayContent().mAppTransition.getAppRootTaskClipMode();
-
- // Separate position and size for use in animators.
- final Rect screenBounds = getAnimationBounds(appRootTaskClipMode);
- mTmpRect.set(screenBounds);
- getAnimationPosition(mTmpPoint);
- mTmpRect.offsetTo(0, 0);
-
- final boolean isChanging = AppTransition.isChangeTransitOld(transit);
-
- if (isChanging) {
- final float durationScale = mWmService.getTransitionAnimationScaleLocked();
- final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
- mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
-
- final AnimationAdapter adapter = new LocalAnimationAdapter(
- new WindowChangeAnimationSpec(null /* startBounds */, mTmpRect,
- displayInfo, durationScale, true /* isAppAnimation */,
- false /* isThumbnail */),
- getSurfaceAnimationRunner());
-
- final AnimationAdapter thumbnailAdapter = null;
- resultAdapters = new Pair<>(adapter, thumbnailAdapter);
- mTransit = transit;
- mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
- } else {
- mNeedsAnimationBoundsLayer = (appRootTaskClipMode == ROOT_TASK_CLIP_AFTER_ANIM);
- final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
-
- if (a != null) {
- // Only apply corner radius to animation if we're not in multi window mode.
- // We don't want rounded corners when in pip or split screen.
- final float windowCornerRadius = !inMultiWindowMode()
- ? getDisplayContent().getWindowCornerRadius()
- : 0;
- if (asActivityRecord() != null
- && asActivityRecord().isNeedsLetterboxedAnimation()) {
- asActivityRecord().getLetterboxInnerBounds(mTmpRect);
- }
- AnimationAdapter adapter = new LocalAnimationAdapter(
- new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
- getDisplayContent().mAppTransition.canSkipFirstFrame(),
- appRootTaskClipMode, true /* isAppAnimation */, windowCornerRadius),
- getSurfaceAnimationRunner());
-
- resultAdapters = new Pair<>(adapter, null);
- mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP
- || AppTransition.isClosingTransitOld(transit);
- mTransit = transit;
- mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
- } else {
- resultAdapters = new Pair<>(null, null);
- }
- }
- return resultAdapters;
- }
-
- protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
- @TransitionOldType int transit, boolean isVoiceInteraction,
- @Nullable ArrayList<WindowContainer> sources) {
- final Task task = asTask();
- if (task != null && !enter && !task.isActivityTypeHomeOrRecents()) {
- final InsetsControlTarget imeTarget = mDisplayContent.getImeTarget(IME_TARGET_LAYERING);
- final boolean isImeLayeringTarget = imeTarget != null && imeTarget.getWindow() != null
- && imeTarget.getWindow().getTask() == task;
- // Attach and show the IME screenshot when the task is the IME target and performing
- // task closing transition to the next task.
- if (isImeLayeringTarget && AppTransition.isTaskCloseTransitOld(transit)) {
- mDisplayContent.showImeScreenshot();
- }
- }
- final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
- transit, enter, isVoiceInteraction);
- AnimationAdapter adapter = adapters.first;
- AnimationAdapter thumbnailAdapter = adapters.second;
- if (adapter != null) {
- if (sources != null) {
- mSurfaceAnimationSources.addAll(sources);
- }
-
- AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder();
-
- // Check if the animation requests to show background color for Activity and embedded
- // TaskFragment.
- final ActivityRecord activityRecord = asActivityRecord();
- final TaskFragment taskFragment = asTaskFragment();
- if (adapter.getShowBackground()
- // Check if it is Activity transition.
- && ((activityRecord != null && isActivityTransitOld(transit))
- // Check if it is embedded TaskFragment transition.
- || (taskFragment != null && taskFragment.isEmbedded()
- && isTaskFragmentTransitOld(transit)))) {
- final @ColorInt int backgroundColorForTransition;
- if (adapter.getBackgroundColor() != 0) {
- // If available use the background color provided through getBackgroundColor
- // which if set originates from a call to overridePendingAppTransition.
- backgroundColorForTransition = adapter.getBackgroundColor();
- } else {
- final TaskFragment organizedTf = activityRecord != null
- ? activityRecord.getOrganizedTaskFragment()
- : taskFragment.getOrganizedTaskFragment();
- if (organizedTf != null && organizedTf.getAnimationParams()
- .getAnimationBackgroundColor() != DEFAULT_ANIMATION_BACKGROUND_COLOR) {
- // This window is embedded and has an animation background color set on the
- // TaskFragment. Pass this color with this window, so the handler can use it
- // as the animation background color if needed,
- backgroundColorForTransition = organizedTf.getAnimationParams()
- .getAnimationBackgroundColor();
- } else {
- // Otherwise default to the window's background color if provided through
- // the theme as the background color for the animation - the top most window
- // with a valid background color and showBackground set takes precedence.
- final Task parentTask = activityRecord != null
- ? activityRecord.getTask()
- : taskFragment.getTask();
- backgroundColorForTransition = parentTask.getTaskDescription()
- .getBackgroundColor();
- }
- }
- // Set to opaque for animation background to prevent it from exposing the blank
- // background or content below.
- animationRunnerBuilder.setTaskBackgroundColor(ColorUtils.setAlphaComponent(
- backgroundColorForTransition, 255));
- }
-
- animationRunnerBuilder.build()
- .startAnimation(getPendingTransaction(), adapter, !isVisible(),
- ANIMATION_TYPE_APP_TRANSITION, thumbnailAdapter);
-
- if (adapter.getShowWallpaper()) {
- getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- }
- }
- }
-
final SurfaceAnimationRunner getSurfaceAnimationRunner() {
return mWmService.mSurfaceAnimationRunner;
}
- private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
- boolean isVoiceInteraction) {
- if ((isOrganized()
- // TODO(b/161711458): Clean-up when moved to shell.
- && getWindowingMode() != WINDOWING_MODE_FULLSCREEN
- && getWindowingMode() != WINDOWING_MODE_FREEFORM
- && getWindowingMode() != WINDOWING_MODE_MULTI_WINDOW)) {
- return null;
- }
-
- final DisplayContent displayContent = getDisplayContent();
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int width = displayInfo.appWidth;
- final int height = displayInfo.appHeight;
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
-
- // Determine the visible rect to calculate the thumbnail clip with
- // getAnimationFrames.
- final Rect frame = new Rect(0, 0, width, height);
- final Rect displayFrame = new Rect(0, 0,
- displayInfo.logicalWidth, displayInfo.logicalHeight);
- final Rect insets = new Rect();
- final Rect stableInsets = new Rect();
- final Rect surfaceInsets = new Rect();
- getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
-
- if (mLaunchTaskBehind) {
- // Differentiate the two animations. This one which is briefly on the screen
- // gets the !enter animation, and the other one which remains on the
- // screen gets the enter animation. Both appear in the mOpeningApps set.
- enter = false;
- }
- ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
- "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
- + "surfaceInsets=%s",
- AppTransition.appTransitionOldToString(transit), enter, frame, insets,
- surfaceInsets);
- final Configuration displayConfig = displayContent.getConfiguration();
- final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
- displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
- surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
- if (a != null) {
- if (a != null) {
- // Setup the maximum app transition duration to prevent malicious app may set a long
- // animation duration or infinite repeat counts for the app transition through
- // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.
- a.restrictDuration(MAX_APP_TRANSITION_DURATION);
- }
- if (ProtoLog.isEnabled(WM_DEBUG_ANIM, LogLevel.DEBUG)) {
- ProtoLog.i(WM_DEBUG_ANIM, "Loaded animation %s for %s, duration: %d, stack=%s",
- a, this, ((a != null) ? a.getDuration() : 0), Debug.getCallers(20));
- }
- final int containingWidth = frame.width();
- final int containingHeight = frame.height();
- a.initialize(containingWidth, containingHeight, width, height);
- a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
- }
- return a;
- }
-
boolean canCreateRemoteAnimationTarget() {
return false;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d699a68..8aed91b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -157,6 +157,7 @@
import static com.android.server.wm.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER;
import static com.android.server.wm.WindowManagerServiceDumpProto.WINDOW_FRAMES_VALID;
import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions;
+import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays;
import static com.android.window.flags.Flags.multiCrop;
import static com.android.window.flags.Flags.setScPropertiesInClient;
@@ -1820,121 +1821,27 @@
final boolean hideSystemAlertWindows = shouldHideNonSystemOverlayWindow(win);
win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
- boolean imMayMove = true;
-
- win.mToken.addWindow(win);
- displayPolicy.addWindowLw(win, attrs);
- displayPolicy.setDropInputModePolicy(win, win.mAttrs);
- if (type == TYPE_APPLICATION_STARTING && activity != null) {
- activity.attachStartingWindow(win);
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
- activity, win);
- } else if (type == TYPE_INPUT_METHOD
- // IME window is always touchable.
- // Ignore non-touchable windows e.g. Stylus InkWindow.java.
- && (win.getAttrs().flags & FLAG_NOT_TOUCHABLE) == 0) {
- displayContent.setInputMethodWindowLocked(win);
- imMayMove = false;
- } else if (type == TYPE_INPUT_METHOD_DIALOG) {
- displayContent.computeImeTarget(true /* updateImeTarget */);
- imMayMove = false;
- } else {
- if (type == TYPE_WALLPAPER) {
- displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
- displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- } else if (win.hasWallpaper()) {
- displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
- // If there is currently a wallpaper being shown, and
- // the base layer of the new window is below the current
- // layer of the target window, then adjust the wallpaper.
- // This is to avoid a new window being placed between the
- // wallpaper and its target.
- displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ // Only a presentation window needs a transition because its visibility affets the
+ // lifecycle of apps below (b/390481865).
+ if (enablePresentationForConnectedDisplays() && win.isPresentation()) {
+ Transition transition = null;
+ if (!win.mTransitionController.isCollecting()) {
+ transition = win.mTransitionController.createAndStartCollecting(TRANSIT_OPEN);
}
- }
-
- final WindowStateAnimator winAnimator = win.mWinAnimator;
- winAnimator.mEnterAnimationPending = true;
- winAnimator.mEnteringAnimation = true;
-
- if (displayPolicy.areSystemBarsForcedConsumedLw()) {
- res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
- }
- if (displayContent.isInTouchMode()) {
- res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
- }
- if (win.mActivityRecord == null || win.mActivityRecord.isClientVisible()) {
- res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
- }
-
- displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
-
- boolean focusChanged = false;
- if (win.canReceiveKeys()) {
- focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
- false /*updateInputWindows*/);
- if (focusChanged) {
- imMayMove = false;
- }
- }
-
- if (imMayMove) {
- displayContent.computeImeTarget(true /* updateImeTarget */);
- if (win.isImeOverlayLayeringTarget()) {
- dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type,
- win.isVisibleRequestedOrAdding(), false /* removed */,
- displayContent.getDisplayId());
- }
- }
-
- // Don't do layout here, the window must call
- // relayout to be displayed, so we'll do it there.
- if (win.mActivityRecord != null && win.mActivityRecord.isEmbedded()) {
- // Assign child layers from the parent Task if the Activity is embedded.
- win.getTask().assignChildLayers();
- } else {
- win.getParent().assignChildLayers();
- }
-
- if (focusChanged) {
- displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
- false /*updateInputWindows*/);
- }
- displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
-
- ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s"
- + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5));
-
- boolean needToSendNewConfiguration =
- win.isVisibleRequestedOrAdding() && displayContent.updateOrientation();
- if (win.providesDisplayDecorInsets()) {
- needToSendNewConfiguration |= displayPolicy.updateDecorInsetsInfo();
- }
- if (needToSendNewConfiguration) {
- displayContent.sendNewConfiguration();
- }
-
- // This window doesn't have a frame yet. Don't let this window cause the insets change.
- displayContent.getInsetsStateController().updateAboveInsetsState(
- false /* notifyInsetsChanged */);
-
- win.fillInsetsState(outInsetsState, true /* copySources */);
- getInsetsSourceControls(win, outActiveControls);
-
- if (win.mLayoutAttached) {
- outAttachedFrame.set(win.getParentWindow().getFrame());
- if (win.mInvGlobalScale != 1f) {
- outAttachedFrame.scale(win.mInvGlobalScale);
+ win.mTransitionController.collect(win.mToken);
+ res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState,
+ outAttachedFrame, outActiveControls, client, outSizeCompatScale, attrs);
+ // A presentation hides all activities behind on the same display.
+ win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
+ /*notifyClients=*/ true);
+ win.mTransitionController.getCollectingTransition().setReady(win.mToken, true);
+ if (transition != null) {
+ win.mTransitionController.requestStartTransition(transition, null,
+ null /* remoteTransition */, null /* displayChange */);
}
} else {
- // Make this invalid which indicates a null attached frame.
- outAttachedFrame.set(0, 0, -1, -1);
- }
- outSizeCompatScale[0] = win.getCompatScaleForClient();
-
- if (res >= ADD_OKAY && win.isPresentation()) {
- mPresentationController.onPresentationAdded(win);
+ res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState,
+ outAttachedFrame, outActiveControls, client, outSizeCompatScale, attrs);
}
}
@@ -1943,6 +1850,133 @@
return res;
}
+ private int addWindowInner(@NonNull WindowState win, @NonNull DisplayPolicy displayPolicy,
+ @NonNull ActivityRecord activity, @NonNull DisplayContent displayContent,
+ @NonNull InsetsState outInsetsState, @NonNull Rect outAttachedFrame,
+ @NonNull InsetsSourceControl.Array outActiveControls, @NonNull IWindow client,
+ @NonNull float[] outSizeCompatScale, @NonNull LayoutParams attrs) {
+ int res = 0;
+ final int type = attrs.type;
+ boolean imMayMove = true;
+
+ win.mToken.addWindow(win);
+ displayPolicy.addWindowLw(win, attrs);
+ displayPolicy.setDropInputModePolicy(win, win.mAttrs);
+ if (type == TYPE_APPLICATION_STARTING && activity != null) {
+ activity.attachStartingWindow(win);
+ ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
+ activity, win);
+ } else if (type == TYPE_INPUT_METHOD
+ // IME window is always touchable.
+ // Ignore non-touchable windows e.g. Stylus InkWindow.java.
+ && (win.getAttrs().flags & FLAG_NOT_TOUCHABLE) == 0) {
+ displayContent.setInputMethodWindowLocked(win);
+ imMayMove = false;
+ } else if (type == TYPE_INPUT_METHOD_DIALOG) {
+ displayContent.computeImeTarget(true /* updateImeTarget */);
+ imMayMove = false;
+ } else {
+ if (type == TYPE_WALLPAPER) {
+ displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
+ displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ } else if (win.hasWallpaper()) {
+ displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
+ // If there is currently a wallpaper being shown, and
+ // the base layer of the new window is below the current
+ // layer of the target window, then adjust the wallpaper.
+ // This is to avoid a new window being placed between the
+ // wallpaper and its target.
+ displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ }
+ }
+
+ final WindowStateAnimator winAnimator = win.mWinAnimator;
+ winAnimator.mEnterAnimationPending = true;
+ winAnimator.mEnteringAnimation = true;
+
+ if (displayPolicy.areSystemBarsForcedConsumedLw()) {
+ res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
+ }
+ if (displayContent.isInTouchMode()) {
+ res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
+ }
+ if (win.mActivityRecord == null || win.mActivityRecord.isClientVisible()) {
+ res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
+ }
+
+ displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
+
+ boolean focusChanged = false;
+ if (win.canReceiveKeys()) {
+ focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
+ false /*updateInputWindows*/);
+ if (focusChanged) {
+ imMayMove = false;
+ }
+ }
+
+ if (imMayMove) {
+ displayContent.computeImeTarget(true /* updateImeTarget */);
+ if (win.isImeOverlayLayeringTarget()) {
+ dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type,
+ win.isVisibleRequestedOrAdding(), false /* removed */,
+ displayContent.getDisplayId());
+ }
+ }
+
+ // Don't do layout here, the window must call
+ // relayout to be displayed, so we'll do it there.
+ if (win.mActivityRecord != null && win.mActivityRecord.isEmbedded()) {
+ // Assign child layers from the parent Task if the Activity is embedded.
+ win.getTask().assignChildLayers();
+ } else {
+ win.getParent().assignChildLayers();
+ }
+
+ if (focusChanged) {
+ displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
+ false /*updateInputWindows*/);
+ }
+ displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
+
+ ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s"
+ + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5));
+
+ boolean needToSendNewConfiguration =
+ win.isVisibleRequestedOrAdding() && displayContent.updateOrientation();
+ if (win.providesDisplayDecorInsets()) {
+ needToSendNewConfiguration |= displayPolicy.updateDecorInsetsInfo();
+ }
+ if (needToSendNewConfiguration) {
+ displayContent.sendNewConfiguration();
+ }
+
+ // This window doesn't have a frame yet. Don't let this window cause the insets change.
+ displayContent.getInsetsStateController().updateAboveInsetsState(
+ false /* notifyInsetsChanged */);
+
+ win.fillInsetsState(outInsetsState, true /* copySources */);
+ getInsetsSourceControls(win, outActiveControls);
+
+ if (win.mLayoutAttached) {
+ outAttachedFrame.set(win.getParentWindow().getFrame());
+ if (win.mInvGlobalScale != 1f) {
+ outAttachedFrame.scale(win.mInvGlobalScale);
+ }
+ } else {
+ // Make this invalid which indicates a null attached frame.
+ outAttachedFrame.set(0, 0, -1, -1);
+ }
+ outSizeCompatScale[0] = win.getCompatScaleForClient();
+
+ if (res >= ADD_OKAY && win.isPresentation()) {
+ mPresentationController.onPresentationAdded(win);
+ }
+
+ return res;
+ }
+
private boolean unprivilegedAppCanCreateTokenWith(WindowState parentWindow,
int callingUid, int type, int rootType, IBinder tokenForLog, String packageName) {
if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 30dde54..270de01 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -37,6 +37,7 @@
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.STARTED;
import static com.android.server.wm.ActivityRecord.State.STOPPING;
+import static com.android.server.wm.ActivityRecord.State.STOPPED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
@@ -344,6 +345,12 @@
*/
private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
+ /**
+ * The most recent timestamp of when one of this process's stopped activities in a
+ * perceptible task became stopped. Written by window manager and read by activity manager.
+ */
+ private volatile long mPerceptibleTaskStoppedTimeMillis = Long.MIN_VALUE;
+
public WindowProcessController(@NonNull ActivityTaskManagerService atm,
@NonNull ApplicationInfo info, String name, int uid, int userId, Object owner,
@NonNull WindowProcessListener listener) {
@@ -475,8 +482,9 @@
r.detachFromProcess();
if (r.isVisibleRequested()) {
hasVisibleActivity = true;
+ Task finishingTask = r.getTask();
r.mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_CLOSE,
- TRANSIT_FLAG_APP_CRASHED);
+ TRANSIT_FLAG_APP_CRASHED, finishingTask);
}
r.destroyIfPossible("handleAppCrashed");
}
@@ -1228,6 +1236,17 @@
return mActivityStateFlags;
}
+ /**
+ * Returns the most recent timestamp when one of this process's stopped activities in a
+ * perceptible task became stopped. It should only be called if {@link #hasActivities}
+ * returns {@code true} and {@link #getActivityStateFlags} does not have any of
+ * the ACTIVITY_STATE_FLAG_IS_(VISIBLE|PAUSING_OR_PAUSED|STOPPING) bit set.
+ */
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
+ public long getPerceptibleTaskStoppedTimeMillis() {
+ return mPerceptibleTaskStoppedTimeMillis;
+ }
+
void computeProcessActivityState() {
// Since there could be more than one activities in a process record, we don't need to
// compute the OomAdj with each of them, just need to find out the activity with the
@@ -1239,6 +1258,7 @@
int minTaskLayer = Integer.MAX_VALUE;
int stateFlags = 0;
int nonOccludedRatio = 0;
+ long perceptibleTaskStoppedTimeMillis = Long.MIN_VALUE;
final boolean wasResumed = hasResumedActivity();
final boolean wasAnyVisible = (mActivityStateFlags
& (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
@@ -1287,6 +1307,11 @@
bestInvisibleState = STOPPING;
// Not "finishing" if any of activity isn't finishing.
allStoppingFinishing &= r.finishing;
+ } else if (bestInvisibleState == DESTROYED && r.isState(STOPPED)) {
+ if (task.mIsPerceptible) {
+ perceptibleTaskStoppedTimeMillis =
+ Long.max(r.mStoppedTime, perceptibleTaskStoppedTimeMillis);
+ }
}
}
}
@@ -1324,6 +1349,7 @@
}
}
mActivityStateFlags = stateFlags;
+ mPerceptibleTaskStoppedTimeMillis = perceptibleTaskStoppedTimeMillis;
final boolean anyVisible = (stateFlags
& (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9f1289b2..bfedc90 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -95,6 +95,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
+import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;
@@ -182,6 +183,7 @@
import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
+import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays;
import static com.android.window.flags.Flags.surfaceTrustedOverlay;
import android.annotation.CallSuper;
@@ -1696,17 +1698,6 @@
|| mActivityRecord.isStartingWindowDisplayed());
}
- @Override
- boolean hasContentToDisplay() {
- if (!isDrawn() && (mViewVisibility == View.VISIBLE
- || (isAnimating(TRANSITION | PARENTS)
- && !getDisplayContent().mAppTransition.isTransitionSet()))) {
- return true;
- }
-
- return super.hasContentToDisplay();
- }
-
private boolean isVisibleByPolicyOrInsets() {
return isVisibleByPolicy()
// If we don't have a provider, this window isn't used as a window generating
@@ -2297,11 +2288,6 @@
dc.updateImeInputAndControlTarget(null);
}
- final int type = mAttrs.type;
-
- if (isPresentation()) {
- mWmService.mPresentationController.onPresentationRemoved(this);
- }
// Check if window provides non decor insets before clearing its provided insets.
final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets();
@@ -2442,11 +2428,33 @@
}
}
- removeImmediately();
- mWmService.updateFocusedWindowLocked(isFocused()
- ? UPDATE_FOCUS_REMOVING_FOCUS
- : UPDATE_FOCUS_NORMAL,
- true /*updateInputWindows*/);
+ // Only a presentation window needs a transition because its visibility affets the
+ // lifecycle of apps below (b/390481865).
+ if (enablePresentationForConnectedDisplays() && isPresentation()) {
+ Transition transition = null;
+ if (!mTransitionController.isCollecting()) {
+ transition = mTransitionController.createAndStartCollecting(TRANSIT_CLOSE);
+ }
+ mTransitionController.collect(mToken);
+ mAnimatingExit = true;
+ mRemoveOnExit = true;
+ mToken.setVisibleRequested(false);
+ mWmService.mPresentationController.onPresentationRemoved(this);
+ // A presentation hides all activities behind on the same display.
+ mDisplayContent.ensureActivitiesVisible(/*starting=*/ null,
+ /*notifyClients=*/ true);
+ mTransitionController.getCollectingTransition().setReady(mToken, true);
+ if (transition != null) {
+ mTransitionController.requestStartTransition(transition, null,
+ null /* remoteTransition */, null /* displayChange */);
+ }
+ } else {
+ removeImmediately();
+ mWmService.updateFocusedWindowLocked(isFocused()
+ ? UPDATE_FOCUS_REMOVING_FOCUS
+ : UPDATE_FOCUS_NORMAL,
+ true /*updateInputWindows*/);
+ }
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/wm/utils/WindowStyleCache.java b/services/core/java/com/android/server/wm/utils/WindowStyleCache.java
new file mode 100644
index 0000000..a253c2c
--- /dev/null
+++ b/services/core/java/com/android/server/wm/utils/WindowStyleCache.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.utils;
+
+import android.content.res.TypedArray;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.policy.AttributeCache;
+
+import java.util.function.Function;
+
+/**
+ * A wrapper of AttributeCache to preserve more dedicated style caches.
+ * @param <T> The type of style cache.
+ */
+public class WindowStyleCache<T> {
+ @GuardedBy("itself")
+ private final ArrayMap<String, SparseArray<T>> mCache = new ArrayMap<>();
+ private final Function<TypedArray, T> mEntryFactory;
+
+ public WindowStyleCache(Function<TypedArray, T> entryFactory) {
+ mEntryFactory = entryFactory;
+ }
+
+ /** Returns the cached entry. */
+ public T get(String packageName, int theme, int userId) {
+ SparseArray<T> themeMap;
+ synchronized (mCache) {
+ themeMap = mCache.get(packageName);
+ if (themeMap != null) {
+ T style = themeMap.get(theme);
+ if (style != null) {
+ return style;
+ }
+ }
+ }
+
+ final AttributeCache attributeCache = AttributeCache.instance();
+ if (attributeCache == null) {
+ return null;
+ }
+ final AttributeCache.Entry ent = attributeCache.get(packageName, theme,
+ R.styleable.Window, userId);
+ if (ent == null) {
+ return null;
+ }
+
+ final T style = mEntryFactory.apply(ent.array);
+ synchronized (mCache) {
+ if (themeMap == null) {
+ mCache.put(packageName, themeMap = new SparseArray<>());
+ }
+ themeMap.put(theme, style);
+ }
+ return style;
+ }
+
+ /** Called when the package is updated or removed. */
+ public void invalidatePackage(String packageName) {
+ synchronized (mCache) {
+ mCache.remove(packageName);
+ }
+ }
+}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index d26539c..9577608 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -204,6 +204,7 @@
"android.frameworks.sensorservice-V1-ndk",
"android.frameworks.stats@1.0",
"android.frameworks.stats-V2-ndk",
+ "android.os.vibrator.flags-aconfig-cc",
"android.system.suspend.control-V1-cpp",
"android.system.suspend.control.internal-cpp",
"android.system.suspend-V1-ndk",
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 0d0c0ba..a8c49e1 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -47,6 +47,7 @@
#include <dispatcher/Entry.h>
#include <include/gestures.h>
#include <input/Input.h>
+#include <input/InputFlags.h>
#include <input/PointerController.h>
#include <input/PrintTools.h>
#include <input/SpriteController.h>
@@ -666,7 +667,7 @@
}
void NativeInputManager::setDisplayTopology(JNIEnv* env, jobject topologyGraph) {
- if (!com::android::input::flags::connected_displays_cursor()) {
+ if (!InputFlags::connectedDisplaysCursorEnabled()) {
return;
}
diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
index abd4cd2..534dbb1 100644
--- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp
+++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
@@ -21,6 +21,7 @@
#include <android/binder_parcel_jni.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
#include <android/persistable_bundle_aidl.h>
+#include <android_os_vibrator.h>
#include <nativehelper/JNIHelp.h>
#include <utils/Log.h>
#include <utils/misc.h>
@@ -143,21 +144,23 @@
return mHal->doWithRetry(fn, functionName);
}
- std::function<void()> createCallback(jlong vibrationId) {
+ std::function<void()> createCallback(jlong vibrationId, jlong stepId) {
auto callbackId = ++mCallbackId;
- return [vibrationId, callbackId, this]() {
+ return [vibrationId, stepId, callbackId, this]() {
auto currentCallbackId = mCallbackId.load();
- if (currentCallbackId != callbackId) {
- // This callback is from an older HAL call that is no longer relevant to the service
+ if (!android_os_vibrator_fix_vibration_thread_callback_handling() &&
+ currentCallbackId != callbackId) {
+ // This callback is from an older HAL call that is no longer relevant
return;
}
auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
- jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, mVibratorId,
- vibrationId);
+ jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, mVibratorId, vibrationId,
+ stepId);
};
}
void disableOldCallbacks() {
+ // TODO remove this once android_os_vibrator_fix_vibration_thread_callback_handling removed
mCallbackId++;
}
@@ -165,6 +168,7 @@
const std::shared_ptr<vibrator::HalController> mHal;
const int32_t mVibratorId;
const jobject mCallbackListener;
+ // TODO remove this once android_os_vibrator_fix_vibration_thread_callback_handling removed
std::atomic<int64_t> mCallbackId;
};
@@ -273,13 +277,13 @@
}
static jlong vibratorOn(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong timeoutMs,
- jlong vibrationId) {
+ jlong vibrationId, jlong stepId) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorOn failed because native wrapper was not initialized");
return -1;
}
- auto callback = wrapper->createCallback(vibrationId);
+ auto callback = wrapper->createCallback(vibrationId, stepId);
auto onFn = [timeoutMs, &callback](vibrator::HalWrapper* hal) {
return hal->on(std::chrono::milliseconds(timeoutMs), callback);
};
@@ -324,7 +328,7 @@
}
static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong effect,
- jlong strength, jlong vibrationId) {
+ jlong strength, jlong vibrationId, jlong stepId) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorPerformEffect failed because native wrapper was not initialized");
@@ -332,7 +336,7 @@
}
Aidl::Effect effectType = static_cast<Aidl::Effect>(effect);
Aidl::EffectStrength effectStrength = static_cast<Aidl::EffectStrength>(strength);
- auto callback = wrapper->createCallback(vibrationId);
+ auto callback = wrapper->createCallback(vibrationId, stepId);
auto performEffectFn = [effectType, effectStrength, &callback](vibrator::HalWrapper* hal) {
return hal->performEffect(effectType, effectStrength, callback);
};
@@ -342,7 +346,7 @@
static jlong vibratorPerformVendorEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
jobject vendorData, jlong strength, jfloat scale,
- jfloat adaptiveScale, jlong vibrationId) {
+ jfloat adaptiveScale, jlong vibrationId, jlong stepId) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorPerformVendorEffect failed because native wrapper was not initialized");
@@ -350,7 +354,7 @@
}
Aidl::VendorEffect effect =
vendorEffectFromJavaParcel(env, vendorData, strength, scale, adaptiveScale);
- auto callback = wrapper->createCallback(vibrationId);
+ auto callback = wrapper->createCallback(vibrationId, stepId);
auto performVendorEffectFn = [&effect, &callback](vibrator::HalWrapper* hal) {
return hal->performVendorEffect(effect, callback);
};
@@ -359,7 +363,8 @@
}
static jlong vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
- jobjectArray composition, jlong vibrationId) {
+ jobjectArray composition, jlong vibrationId,
+ jlong stepId) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorPerformComposedEffect failed because native wrapper was not initialized");
@@ -371,7 +376,7 @@
jobject element = env->GetObjectArrayElement(composition, i);
effects.push_back(effectFromJavaPrimitive(env, element));
}
- auto callback = wrapper->createCallback(vibrationId);
+ auto callback = wrapper->createCallback(vibrationId, stepId);
auto performComposedEffectFn = [&effects, &callback](vibrator::HalWrapper* hal) {
return hal->performComposedEffect(effects, callback);
};
@@ -381,7 +386,8 @@
}
static jlong vibratorPerformPwleEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
- jobjectArray waveform, jint brakingId, jlong vibrationId) {
+ jobjectArray waveform, jint brakingId, jlong vibrationId,
+ jlong stepId) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorPerformPwleEffect failed because native wrapper was not initialized");
@@ -406,7 +412,7 @@
}
}
- auto callback = wrapper->createCallback(vibrationId);
+ auto callback = wrapper->createCallback(vibrationId, stepId);
auto performPwleEffectFn = [&primitives, &callback](vibrator::HalWrapper* hal) {
return hal->performPwleEffect(primitives, callback);
};
@@ -415,7 +421,7 @@
}
static jlong vibratorPerformPwleV2Effect(JNIEnv* env, jclass /* clazz */, jlong ptr,
- jobjectArray waveform, jlong vibrationId) {
+ jobjectArray waveform, jlong vibrationId, jlong stepId) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorPerformPwleV2Effect failed because native wrapper was not initialized");
@@ -431,7 +437,7 @@
}
composite.pwlePrimitives = primitives;
- auto callback = wrapper->createCallback(vibrationId);
+ auto callback = wrapper->createCallback(vibrationId, stepId);
auto composePwleV2Fn = [&composite, &callback](vibrator::HalWrapper* hal) {
return hal->composePwleV2(composite, callback);
};
@@ -610,16 +616,16 @@
(void*)vibratorNativeInit},
{"getNativeFinalizer", "()J", (void*)vibratorGetNativeFinalizer},
{"isAvailable", "(J)Z", (void*)vibratorIsAvailable},
- {"on", "(JJJ)J", (void*)vibratorOn},
+ {"on", "(JJJJ)J", (void*)vibratorOn},
{"off", "(J)V", (void*)vibratorOff},
{"setAmplitude", "(JF)V", (void*)vibratorSetAmplitude},
- {"performEffect", "(JJJJ)J", (void*)vibratorPerformEffect},
- {"performVendorEffect", "(JLandroid/os/Parcel;JFFJ)J", (void*)vibratorPerformVendorEffect},
- {"performComposedEffect", "(J[Landroid/os/vibrator/PrimitiveSegment;J)J",
+ {"performEffect", "(JJJJJ)J", (void*)vibratorPerformEffect},
+ {"performVendorEffect", "(JLandroid/os/Parcel;JFFJJ)J", (void*)vibratorPerformVendorEffect},
+ {"performComposedEffect", "(J[Landroid/os/vibrator/PrimitiveSegment;JJ)J",
(void*)vibratorPerformComposedEffect},
- {"performPwleEffect", "(J[Landroid/os/vibrator/RampSegment;IJ)J",
+ {"performPwleEffect", "(J[Landroid/os/vibrator/RampSegment;IJJ)J",
(void*)vibratorPerformPwleEffect},
- {"performPwleV2Effect", "(J[Landroid/os/vibrator/PwlePoint;J)J",
+ {"performPwleV2Effect", "(J[Landroid/os/vibrator/PwlePoint;JJ)J",
(void*)vibratorPerformPwleV2Effect},
{"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
{"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
@@ -632,7 +638,7 @@
auto listenerClassName =
"com/android/server/vibrator/VibratorController$OnVibrationCompleteListener";
jclass listenerClass = FindClassOrDie(env, listenerClassName);
- sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(IJ)V");
+ sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(IJJ)V");
jclass primitiveClass = FindClassOrDie(env, "android/os/vibrator/PrimitiveSegment");
sPrimitiveClassInfo.id = GetFieldIDOrDie(env, primitiveClass, "mPrimitiveId", "I");
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
index 40554ac..7edf646 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
@@ -21,11 +21,16 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.credentials.CredentialManager;
import android.credentials.CredentialProviderInfo;
+import android.credentials.flags.Flags;
import android.service.credentials.CredentialProviderInfoFactory;
+import android.service.credentials.CredentialProviderService;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -78,14 +83,16 @@
mInfo = providerInfo;
}
- @Override // from PerUserSystemService when a new setting based service is to be created
+ @Override // from PerUserSystemService when a new service is to be created
@GuardedBy("mLock")
protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent)
- throws PackageManager.NameNotFoundException {
+ throws PackageManager.NameNotFoundException, SecurityException, NullPointerException {
+ boolean isSystemProvider = false;
if (mInfo != null) {
Slog.i(TAG, "newServiceInfoLocked, mInfo not null : "
+ mInfo.getServiceInfo().getComponentName().flattenToString() + " , "
+ serviceComponent.flattenToString());
+ isSystemProvider = mInfo.isSystemProvider();
} else {
Slog.i(TAG, "newServiceInfoLocked, mInfo null, "
+ serviceComponent.flattenToString());
@@ -94,7 +101,7 @@
getPrimaryProvidersForUserId(mMaster.getContext(), mUserId);
mInfo = CredentialProviderInfoFactory.create(
getContext(), serviceComponent,
- mUserId, /*isSystemProvider=*/false,
+ mUserId, isSystemProvider,
primaryProviders.contains(serviceComponent));
return mInfo.getServiceInfo();
}
@@ -148,15 +155,63 @@
* @param packageName package of the app being updated.
*/
@GuardedBy("mLock")
+ @SuppressWarnings("GuardedBy") // ErrorProne requires this.mMaster.mLock which is the case
+ // because this method is called by this.mMaster anyway
protected void handlePackageUpdateLocked(@NonNull String packageName) {
if (mInfo != null && mInfo.getServiceInfo() != null
&& mInfo.getServiceInfo().getComponentName()
.getPackageName().equals(packageName)) {
- try {
- newServiceInfoLocked(mInfo.getServiceInfo().getComponentName());
- } catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "Issue while updating serviceInfo: " + e.getMessage());
+ if (Flags.packageUpdateFixEnabled()) {
+ try {
+ updateCredentialProviderInfo(mInfo.getServiceInfo().getComponentName(),
+ mInfo.isSystemProvider());
+ } catch (SecurityException | PackageManager.NameNotFoundException
+ | NullPointerException e) {
+ Slog.w(TAG, "Unable to update provider, must be removed: " + e.getMessage());
+ mMaster.handleServiceRemovedMultiModeLocked(mInfo.getComponentName(), mUserId);
+ }
+ } else {
+ try {
+ newServiceInfoLocked(mInfo.getServiceInfo().getComponentName());
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Issue while updating serviceInfo: " + e.getMessage());
+ }
}
}
}
+
+ @GuardedBy("mLock")
+ private void updateCredentialProviderInfo(ComponentName componentName, boolean isSystemProvider)
+ throws SecurityException, PackageManager.NameNotFoundException {
+ Slog.d(TAG, "Updating credential provider: " + componentName.flattenToString());
+ if (!isValidCredentialProviderInfo(componentName, mUserId, isSystemProvider)) {
+ throw new SecurityException("Service has not been set up correctly");
+ }
+ newServiceInfoLocked(componentName);
+ }
+
+ private boolean isValidCredentialProviderInfo(ComponentName componentName, int userId,
+ boolean isSystemProvider) {
+ Context context = getContext();
+ if (context == null) {
+ return false;
+ }
+ String serviceInterface = CredentialProviderService.SERVICE_INTERFACE;
+ if (isSystemProvider) {
+ serviceInterface = CredentialProviderService.SYSTEM_SERVICE_INTERFACE;
+ }
+ final List<ResolveInfo> resolveInfos =
+ context.getPackageManager()
+ .queryIntentServicesAsUser(
+ new Intent(serviceInterface),
+ PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA),
+ userId);
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+ if (serviceInfo.getComponentName().equals(componentName)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index bbbfe0b..e3b9fdb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -65,6 +65,7 @@
import android.util.SparseArray;
import android.util.Xml;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -120,11 +121,13 @@
/**
* Map of <userId, Map<policyKey, policyState>>
*/
+ @GuardedBy("mLock")
private final SparseArray<Map<PolicyKey, PolicyState<?>>> mLocalPolicies;
/**
* Map of <policyKey, policyState>
*/
+ @GuardedBy("mLock")
private final Map<PolicyKey, PolicyState<?>> mGlobalPolicies;
/**
@@ -152,6 +155,7 @@
mAdminPolicySize = new SparseArray<>();
}
+ @GuardedBy("mLock")
private void forceEnforcementRefreshIfUserRestrictionLocked(
@NonNull PolicyDefinition<?> policyDefinition) {
try {
@@ -185,6 +189,7 @@
return false;
}
+ @GuardedBy("mLock")
private void forceEnforcementRefreshLocked(PolicyDefinition<Boolean> policyDefinition) {
Binder.withCleanCallingIdentity(() -> {
// Sync global state
@@ -296,6 +301,7 @@
*
* <p>Passing a {@code null} value means the policy set by this admin should be removed.
*/
+ @GuardedBy("mLock")
private <V> void setNonCoexistableLocalPolicyLocked(
PolicyDefinition<V> policyDefinition,
PolicyState<V> localPolicyState,
@@ -440,6 +446,7 @@
/**
* Enforces the new policy and notifies relevant admins.
*/
+ @GuardedBy("mLock")
private <V> void onLocalPolicyChangedLocked(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull EnforcingAdmin enforcingAdmin,
@@ -600,6 +607,7 @@
/**
* Enforces the new policy globally and notifies relevant admins.
*/
+ @GuardedBy("mLock")
private <V> void onGlobalPolicyChangedLocked(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull EnforcingAdmin enforcingAdmin) {
@@ -627,6 +635,7 @@
*
* <p>Returns {@code true} if the policy is enforced successfully on all users.
*/
+ @GuardedBy("mLock")
private <V> boolean applyGlobalPolicyOnUsersWithLocalPoliciesLocked(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull EnforcingAdmin enforcingAdmin,
@@ -930,6 +939,7 @@
removePoliciesForAdmin(oldAdmin);
}
+ @GuardedBy("mLock")
private Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdminLocked(
Map<PolicyKey, PolicyState<?>> policies,
EnforcingAdmin admin) {
@@ -949,6 +959,7 @@
return keys;
}
+ @GuardedBy("mLock")
private <V> boolean hasLocalPolicyLocked(PolicyDefinition<V> policyDefinition, int userId) {
if (policyDefinition.isGlobalOnlyPolicy()) {
return false;
@@ -963,6 +974,7 @@
.getPoliciesSetByAdmins().isEmpty();
}
+ @GuardedBy("mLock")
private <V> boolean hasGlobalPolicyLocked(PolicyDefinition<V> policyDefinition) {
if (policyDefinition.isLocalOnlyPolicy()) {
return false;
@@ -974,6 +986,7 @@
.isEmpty();
}
+ @GuardedBy("mLock")
@NonNull
private <V> PolicyState<V> getLocalPolicyStateLocked(
PolicyDefinition<V> policyDefinition, int userId) {
@@ -993,6 +1006,7 @@
return getPolicyStateLocked(mLocalPolicies.get(userId), policyDefinition);
}
+ @GuardedBy("mLock")
private <V> void removeLocalPolicyStateLocked(
PolicyDefinition<V> policyDefinition, int userId) {
if (!mLocalPolicies.contains(userId)) {
@@ -1001,6 +1015,7 @@
mLocalPolicies.get(userId).remove(policyDefinition.getPolicyKey());
}
+ @GuardedBy("mLock")
@NonNull
private <V> PolicyState<V> getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
if (policyDefinition.isLocalOnlyPolicy()) {
@@ -1015,10 +1030,12 @@
return getPolicyStateLocked(mGlobalPolicies, policyDefinition);
}
+ @GuardedBy("mLock")
private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
mGlobalPolicies.remove(policyDefinition.getPolicyKey());
}
+ @GuardedBy("mLock")
private static <V> PolicyState<V> getPolicyStateLocked(
Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) {
try {
@@ -1089,6 +1106,7 @@
}
// TODO(b/261430877): Finalise the decision on which admins to send the updates to.
+ @GuardedBy("mLock")
private <V> void sendPolicyChangedToAdminsLocked(
PolicyState<V> policyState,
EnforcingAdmin callingAdmin,
@@ -1378,6 +1396,7 @@
});
}
+ @GuardedBy("mLock")
private <V> void enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState) {
if (!policyState.getPolicyDefinition().isInheritable()) {
return;
@@ -1435,11 +1454,12 @@
}
for (int i = 0; i < mLocalPolicies.size(); i++) {
- Set<PolicyKey> localPolicies = new HashSet<>(
- mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet());
+ // New users are potentially added to mLocalPolicies during the loop body
+ // (see b/374511959).
+ int userId = mLocalPolicies.keyAt(i);
+ Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet());
for (PolicyKey policy : localPolicies) {
- PolicyState<?> policyState = mLocalPolicies.get(
- mLocalPolicies.keyAt(i)).get(policy);
+ PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
removeLocalPolicy(
policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i));
@@ -1509,6 +1529,7 @@
* Called after an admin policy has been added to start binding to the admin if a connection
* was not already established.
*/
+ @GuardedBy("mLock")
private void updateDeviceAdminServiceOnPolicyAddLocked(@NonNull EnforcingAdmin enforcingAdmin) {
int userId = enforcingAdmin.getUserId();
@@ -1537,6 +1558,7 @@
* Called after an admin policy has been removed to stop binding to the admin if they no longer
* have any policies set.
*/
+ @GuardedBy("mLock")
private void updateDeviceAdminServiceOnPolicyRemoveLocked(
@NonNull EnforcingAdmin enforcingAdmin) {
if (doesAdminHavePoliciesLocked(enforcingAdmin)) {
@@ -1562,6 +1584,7 @@
/* actionForLog= */ "policy-removed");
}
+ @GuardedBy("mLock")
private boolean doesAdminHavePoliciesLocked(@NonNull EnforcingAdmin enforcingAdmin) {
for (PolicyKey policy : mGlobalPolicies.keySet()) {
PolicyState<?> policyState = mGlobalPolicies.get(policy);
@@ -1785,6 +1808,7 @@
}
}
+ @GuardedBy("mLock")
<V> void reapplyAllPoliciesOnBootLocked() {
for (PolicyKey policy : mGlobalPolicies.keySet()) {
PolicyState<?> policyState = mGlobalPolicies.get(policy);
@@ -1919,6 +1943,7 @@
}
}
+ @GuardedBy("mLock")
void writeToFileLocked() {
Log.d(TAG, "Writing to " + mFile);
@@ -1931,7 +1956,7 @@
out.startDocument(null, true);
// Actual content
- writeInner(out);
+ writeInnerLocked(out);
out.endDocument();
out.flush();
@@ -1948,16 +1973,19 @@
}
}
+ @GuardedBy("mLock")
// TODO(b/256846294): Add versioning to read/write
- void writeInner(TypedXmlSerializer serializer) throws IOException {
- writeLocalPoliciesInner(serializer);
- writeGlobalPoliciesInner(serializer);
- writeEnforcingAdminsInner(serializer);
- writeEnforcingAdminSizeInner(serializer);
- writeMaxPolicySizeInner(serializer);
+ void writeInnerLocked(TypedXmlSerializer serializer) throws IOException {
+ writeLocalPoliciesInnerLocked(serializer);
+ writeGlobalPoliciesInnerLocked(serializer);
+ writeEnforcingAdminsInnerLocked(serializer);
+ writeEnforcingAdminSizeInnerLocked(serializer);
+ writeMaxPolicySizeInnerLocked(serializer);
}
- private void writeLocalPoliciesInner(TypedXmlSerializer serializer) throws IOException {
+ @GuardedBy("mLock")
+ private void writeLocalPoliciesInnerLocked(TypedXmlSerializer serializer)
+ throws IOException {
if (mLocalPolicies != null) {
for (int i = 0; i < mLocalPolicies.size(); i++) {
int userId = mLocalPolicies.keyAt(i);
@@ -1981,7 +2009,9 @@
}
}
- private void writeGlobalPoliciesInner(TypedXmlSerializer serializer) throws IOException {
+ @GuardedBy("mLock")
+ private void writeGlobalPoliciesInnerLocked(TypedXmlSerializer serializer)
+ throws IOException {
if (mGlobalPolicies != null) {
for (Map.Entry<PolicyKey, PolicyState<?>> policy : mGlobalPolicies.entrySet()) {
serializer.startTag(/* namespace= */ null, TAG_GLOBAL_POLICY_ENTRY);
@@ -1999,7 +2029,9 @@
}
}
- private void writeEnforcingAdminsInner(TypedXmlSerializer serializer) throws IOException {
+ @GuardedBy("mLock")
+ private void writeEnforcingAdminsInnerLocked(TypedXmlSerializer serializer)
+ throws IOException {
if (mEnforcingAdmins != null) {
for (int i = 0; i < mEnforcingAdmins.size(); i++) {
int userId = mEnforcingAdmins.keyAt(i);
@@ -2012,7 +2044,8 @@
}
}
- private void writeEnforcingAdminSizeInner(TypedXmlSerializer serializer)
+ @GuardedBy("mLock")
+ private void writeEnforcingAdminSizeInnerLocked(TypedXmlSerializer serializer)
throws IOException {
if (mAdminPolicySize != null) {
for (int i = 0; i < mAdminPolicySize.size(); i++) {
@@ -2034,7 +2067,8 @@
}
}
- private void writeMaxPolicySizeInner(TypedXmlSerializer serializer)
+ @GuardedBy("mLock")
+ private void writeMaxPolicySizeInnerLocked(TypedXmlSerializer serializer)
throws IOException {
serializer.startTag(/* namespace= */ null, TAG_MAX_POLICY_SIZE_LIMIT);
serializer.attributeInt(
@@ -2042,6 +2076,7 @@
serializer.endTag(/* namespace= */ null, TAG_MAX_POLICY_SIZE_LIMIT);
}
+ @GuardedBy("mLock")
void readFromFileLocked() {
if (!mFile.exists()) {
Log.d(TAG, "" + mFile + " doesn't exist");
@@ -2055,7 +2090,7 @@
input = f.openRead();
TypedXmlPullParser parser = Xml.resolvePullParser(input);
- readInner(parser);
+ readInnerLocked(parser);
} catch (XmlPullParserException | IOException | ClassNotFoundException e) {
Slogf.wtf(TAG, "Error parsing resources file", e);
@@ -2064,7 +2099,8 @@
}
}
- private void readInner(TypedXmlPullParser parser)
+ @GuardedBy("mLock")
+ private void readInnerLocked(TypedXmlPullParser parser)
throws IOException, XmlPullParserException, ClassNotFoundException {
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 191c21e..aee32a0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -423,6 +423,7 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.hardware.usb.UsbManager;
+import android.health.connect.HealthConnectManager;
import android.location.Location;
import android.location.LocationManager;
import android.media.AudioManager;
@@ -2149,6 +2150,14 @@
.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
mBackgroundHandler = BackgroundThread.getHandler();
+ // Add the health permission to the list of restricted permissions.
+ if (android.permission.flags.Flags.replaceBodySensorPermissionEnabled()) {
+ Set<String> healthPermissions = HealthConnectManager.getHealthPermissions(mContext);
+ for (String permission : healthPermissions) {
+ SENSOR_PERMISSIONS.add(permission);
+ }
+ }
+
// Needed when mHasFeature == false, because it controls the certificate warning text.
mCertificateMonitor = new CertificateMonitor(this, mInjector, mBackgroundHandler);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2bbd69c..e158310 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1279,12 +1279,6 @@
if (!Flags.refactorCrashrecovery()) {
// Initialize RescueParty.
CrashRecoveryAdaptor.rescuePartyRegisterHealthObserver(mSystemContext);
- if (!Flags.recoverabilityDetection()) {
- // Now that we have the bare essentials of the OS up and running, take
- // note that we just booted, which might send out a rescue party if
- // we're stuck in a runtime restart loop.
- CrashRecoveryAdaptor.packageWatchdogNoteBoot(mSystemContext);
- }
}
@@ -1558,14 +1552,6 @@
boolean enableVrService = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
- if (!Flags.recoverabilityDetection()) {
- // For debugging RescueParty
- if (Build.IS_DEBUGGABLE
- && SystemProperties.getBoolean("debug.crash_system", false)) {
- throw new RuntimeException();
- }
- }
-
try {
final String SECONDARY_ZYGOTE_PRELOAD = "SecondaryZygotePreload";
// We start the preload ~1s before the webview factory preparation, to
@@ -3091,13 +3077,11 @@
CrashRecoveryAdaptor.initializeCrashrecoveryModuleService(mSystemServiceManager);
t.traceEnd();
} else {
- if (Flags.recoverabilityDetection()) {
- // Now that we have the essential services needed for mitigations, register the boot
- // with package watchdog.
- // Note that we just booted, which might send out a rescue party if we're stuck in a
- // runtime restart loop.
- CrashRecoveryAdaptor.packageWatchdogNoteBoot(mSystemContext);
- }
+ // Now that we have the essential services needed for mitigations, register the boot
+ // with package watchdog.
+ // Note that we just booted, which might send out a rescue party if we're stuck in a
+ // runtime restart loop.
+ CrashRecoveryAdaptor.packageWatchdogNoteBoot(mSystemContext);
}
t.traceBegin("MakeDisplayManagerServiceReady");
@@ -3511,12 +3495,10 @@
* are updated outside of OTA; and to avoid breaking dependencies from system into apexes.
*/
private void startApexServices(@NonNull TimingsTraceAndSlog t) {
- if (Flags.recoverabilityDetection()) {
- // For debugging RescueParty
- if (Build.IS_DEBUGGABLE
- && SystemProperties.getBoolean("debug.crash_system", false)) {
- throw new RuntimeException();
- }
+ // For debugging RescueParty
+ if (Build.IS_DEBUGGABLE
+ && SystemProperties.getBoolean("debug.crash_system", false)) {
+ throw new RuntimeException();
}
t.traceBegin("startApexServices");
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml
index 4552326..79dd129 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.inputmethod.imetests">
+ package="com.android.inputmethodservice">
<!-- Permissions required for granting and logging -->
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
@@ -33,7 +33,7 @@
</application>
<!-- The "targetPackage" reference the instruments APK package, which is the SimpleTestIme.apk,
- while the test package is "com.android.inputmethod.imetests" (FrameworksImeTests.apk).-->
+ while the test package is "com.android.inputmethodservice" (FrameworksImeTests.apk).-->
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.apps.inputmethod.simpleime"
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml
index 8e6954b..5fe5b23 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml
@@ -34,14 +34,15 @@
<option name="test-tag" value="FrameworksImeTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.inputmethod.imetests" />
+ <option name="package" value="com.android.inputmethodservice" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
- <!-- Collect the files in the dump directory for debugging -->
+ <!-- Collect output of DumpOnFailure -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
- <option name="directory-keys" value="/sdcard/FrameworksImeTests/" />
+ <option name="directory-keys" value="/data/user/0/com.android.apps.inputmethod.simpleime/files" />
<option name="collect-on-run-ended-only" value="true" />
+ <option name="clean-up" value="true" />
</metrics_collector>
</configuration>
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index 2d3f723..6e16d29 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -40,10 +40,15 @@
import android.graphics.Insets;
import android.os.Build;
import android.os.RemoteException;
+import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
+import android.server.wm.DumpOnFailure;
import android.server.wm.WindowManagerStateHelper;
import android.util.Log;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.Flags;
@@ -72,6 +77,7 @@
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -118,6 +124,9 @@
@Rule
public final TestName mName = new TestName();
+ @Rule
+ public final DumpOnFailure mDumpOnFailure = new DumpOnFailure();
+
private Instrumentation mInstrumentation;
private UiDevice mUiDevice;
private InputMethodManager mImm;
@@ -139,10 +148,9 @@
if (!mOriginalVerboseImeTrackerLoggingEnabled) {
setVerboseImeTrackerLogging(true);
}
+ mUiDevice.setOrientationNatural();
prepareIme();
prepareActivity();
- mUiDevice.freezeRotation();
- mUiDevice.setOrientationNatural();
// Waits for input binding ready.
eventually(() -> {
mInputMethodService = InputMethodServiceWrapper.getInstance();
@@ -169,6 +177,9 @@
@After
public void tearDown() throws Exception {
+ if (!mUiDevice.isNaturalOrientation()) {
+ mUiDevice.setOrientationNatural();
+ }
mUiDevice.unfreezeRotation();
if (!mOriginalVerboseImeTrackerLoggingEnabled) {
setVerboseImeTrackerLogging(false);
@@ -245,6 +256,61 @@
}
/**
+ * This checks that the surface is removed after the window was hidden in
+ * InputMethodService#hideSoftInput
+ */
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
+ public void testSurfaceRemovedAfterHideSoftInput() {
+ setShowImeWithHardKeyboard(true /* enabled */);
+
+ // Triggers to show IME via public API.
+ verifyInputViewStatusOnMainSync(() -> mActivity.showImeWithWindowInsetsController(),
+ EVENT_SHOW, true /* eventExpected */, true /* shown */, "IME is shown");
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
+
+ final var window = mInputMethodService.getWindow().getWindow();
+ assertWithMessage("IME window exists").that(window).isNotNull();
+ eventually(() -> assertWithMessage("IME window showing").that(
+ window.getDecorView().getVisibility()).isEqualTo(View.VISIBLE));
+
+ mActivity.getWindow().getDecorView().setWindowInsetsAnimationCallback(
+ new WindowInsetsAnimation.Callback(
+ WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
+ @NonNull
+ @Override
+ public WindowInsetsAnimation.Bounds onStart(
+ @NonNull WindowInsetsAnimation animation,
+ @NonNull WindowInsetsAnimation.Bounds bounds) {
+ return super.onStart(animation, bounds);
+ }
+
+ @NonNull
+ @Override
+ public WindowInsets onProgress(@NonNull WindowInsets insets,
+ @NonNull List<WindowInsetsAnimation> runningAnimations) {
+ assertWithMessage("IME surface not removed during the animation").that(
+ window.getDecorView().getVisibility()).isEqualTo(View.VISIBLE);
+ return insets;
+ }
+
+ @Override
+ public void onEnd(@NonNull WindowInsetsAnimation animation) {
+ assertWithMessage(
+ "IME surface not removed before the end of the animation").that(
+ window.getDecorView().getVisibility()).isEqualTo(View.VISIBLE);
+ super.onEnd(animation);
+ }
+ });
+
+ // Triggers to hide IME via public API.
+ verifyInputViewStatusOnMainSync(() -> mActivity.hideImeWithWindowInsetsController(),
+ EVENT_HIDE, true /* eventExpected */, false /* shown */, "IME is not shown");
+ eventually(() -> assertWithMessage("IME window not showing").that(
+ window.getDecorView().getVisibility()).isEqualTo(View.GONE));
+ }
+
+ /**
* This checks the result of calling IMS#requestShowSelf and IMS#requestHideSelf.
*/
@Test
@@ -866,6 +932,9 @@
() -> mActivity.showImeWithWindowInsetsController(),
EVENT_SHOW, true /* eventExpected */, true /* shown */, "IME is shown");
+ eventually(() -> assertWithMessage("IME navigation bar is shown")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue());
+
final var backButton = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID));
verifyInputViewStatus(
() -> {
@@ -892,6 +961,9 @@
() -> mActivity.showImeWithWindowInsetsController(),
EVENT_SHOW, true /* eventExpected */, true /* shown */, "IME is shown");
+ eventually(() -> assertWithMessage("IME navigation bar is shown")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue());
+
final var backButton = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID));
verifyInputViewStatus(
() -> {
@@ -927,6 +999,9 @@
},
EVENT_SHOW, true /* eventExpected */, true /* shown */, "IME is shown");
+ eventually(() -> assertWithMessage("IME navigation bar is shown")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue());
+
final var imeSwitcherButton = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID));
imeSwitcherButton.click();
mInstrumentation.waitForIdleSync();
@@ -965,6 +1040,9 @@
},
EVENT_SHOW, true /* eventExpected */, true /* shown */, "IME is shown");
+ eventually(() -> assertWithMessage("IME navigation bar is shown")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue());
+
final var imeSwitcherButton = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID));
imeSwitcherButton.longClick();
mInstrumentation.waitForIdleSync();
@@ -1210,8 +1288,13 @@
@NonNull
private UiObject2 getUiObject(@NonNull BySelector bySelector) {
+ final var preScreenshot = mInstrumentation.getUiAutomation().takeScreenshot();
+ mDumpOnFailure.dumpOnFailure("pre-getUiObject", preScreenshot);
final var uiObject = mUiDevice.wait(Until.findObject(bySelector), TIMEOUT_MS);
- assertWithMessage("UiObject with " + bySelector + " was found").that(uiObject).isNotNull();
+ mInstrumentation.waitForIdleSync();
+ final var postScreenshot = mInstrumentation.getUiAutomation().takeScreenshot();
+ mDumpOnFailure.dumpOnFailure("post-getUiObject", postScreenshot);
+ assertWithMessage("UiObject with " + bySelector + " was found").that(uiObject).isNull();
return uiObject;
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java
index 9e3d9ec..d98a0d1 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ClientControllerTest.java
@@ -28,6 +28,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
import android.content.pm.PackageManagerInternal;
import android.os.Handler;
import android.os.IBinder;
@@ -55,8 +56,7 @@
private static final String SOME_PACKAGE_NAME = "some.package";
@Rule
- public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
- .setProvideMainThread(true).build();
+ public final RavenwoodRule mRavenwood = new RavenwoodRule();
@Mock
private PackageManagerInternal mMockPackageManagerInternal;
@@ -65,7 +65,7 @@
private IInputMethodClient mClient;
@Mock
- private IRemoteInputConnection mConnection;
+ private IRemoteInputConnection mFallbackConnection;
private Handler mHandler;
@@ -81,23 +81,25 @@
}
// TODO(b/322895594): No need to directly invoke create$ravenwood once b/322895594 is fixed.
- private IInputMethodClientInvoker createInvoker(IInputMethodClient client, Handler handler) {
+ @NonNull
+ private IInputMethodClientInvoker createInvoker(@NonNull IInputMethodClient client,
+ @NonNull Handler handler) {
return RavenwoodRule.isOnRavenwood()
- ? IInputMethodClientInvoker.create$ravenwood(client, handler) :
- IInputMethodClientInvoker.create(client, handler);
+ ? IInputMethodClientInvoker.create$ravenwood(client, handler)
+ : IInputMethodClientInvoker.create(client, handler);
}
@Test
public void testAddClient_cannotAddTheSameClientTwice() {
final var invoker = createInvoker(mClient, mHandler);
synchronized (ImfLock.class) {
- mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, ANY_CALLER_UID,
+ mController.addClient(invoker, mFallbackConnection, ANY_DISPLAY_ID, ANY_CALLER_UID,
ANY_CALLER_PID);
SecurityException thrown = assertThrows(SecurityException.class,
() -> {
synchronized (ImfLock.class) {
- mController.addClient(invoker, mConnection, ANY_DISPLAY_ID,
+ mController.addClient(invoker, mFallbackConnection, ANY_DISPLAY_ID,
ANY_CALLER_UID, ANY_CALLER_PID);
}
});
@@ -111,9 +113,8 @@
public void testAddClient() throws Exception {
final var invoker = createInvoker(mClient, mHandler);
synchronized (ImfLock.class) {
- final var added = mController.addClient(invoker, mConnection, ANY_DISPLAY_ID,
- ANY_CALLER_UID,
- ANY_CALLER_PID);
+ final var added = mController.addClient(invoker, mFallbackConnection, ANY_DISPLAY_ID,
+ ANY_CALLER_UID, ANY_CALLER_PID);
verify(invoker.asBinder()).linkToDeath(any(IBinder.DeathRecipient.class), eq(0));
assertThat(mController.getClient(invoker.asBinder())).isSameInstanceAs(added);
@@ -127,8 +128,8 @@
ClientState added;
synchronized (ImfLock.class) {
mController.addClientControllerCallback(callback);
- added = mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, ANY_CALLER_UID,
- ANY_CALLER_PID);
+ added = mController.addClient(invoker, mFallbackConnection, ANY_DISPLAY_ID,
+ ANY_CALLER_UID, ANY_CALLER_PID);
assertThat(mController.getClient(invoker.asBinder())).isSameInstanceAs(added);
assertThat(mController.removeClient(mClient)).isTrue();
}
@@ -141,14 +142,14 @@
@Test
public void testVerifyClientAndPackageMatch() {
final var invoker = createInvoker(mClient, mHandler);
- when(mMockPackageManagerInternal.isSameApp(eq(SOME_PACKAGE_NAME), /* flags= */
- anyLong(), eq(ANY_CALLER_UID), /* userId= */ anyInt())).thenReturn(true);
+ when(mMockPackageManagerInternal.isSameApp(eq(SOME_PACKAGE_NAME), anyLong() /* flags */,
+ eq(ANY_CALLER_UID), anyInt() /* userId */)).thenReturn(true);
synchronized (ImfLock.class) {
- mController.addClient(invoker, mConnection, ANY_DISPLAY_ID, ANY_CALLER_UID,
+ mController.addClient(invoker, mFallbackConnection, ANY_DISPLAY_ID, ANY_CALLER_UID,
ANY_CALLER_PID);
- assertThat(
- mController.verifyClientAndPackageMatch(mClient, SOME_PACKAGE_NAME)).isTrue();
+ assertThat(mController.verifyClientAndPackageMatch(mClient, SOME_PACKAGE_NAME))
+ .isTrue();
}
}
@@ -171,7 +172,7 @@
private ClientState mRemoved;
@Override
- public void onClientRemoved(ClientState removed) {
+ public void onClientRemoved(@NonNull ClientState removed) {
mRemoved = removed;
mLatch.countDown();
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
index 3aeab09..05615f6 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -196,7 +196,7 @@
@RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
public void testApplyImeVisibility_hideImeFromTargetOnSecondaryDisplay() {
// Init a IME target client on the secondary display to show IME.
- mInputMethodManagerService.addClient(mMockInputMethodClient, mMockRemoteInputConnection,
+ mInputMethodManagerService.addClient(mMockInputMethodClient, mMockFallbackInputConnection,
10 /* selfReportedDisplayId */);
synchronized (ImfLock.class) {
setAttachedClientLocked(null);
@@ -283,7 +283,7 @@
softInputMode /* softInputMode */,
0 /* windowFlags */,
mEditorInfo /* editorInfo */,
- mMockRemoteInputConnection /* inputConnection */,
+ mMockFallbackInputConnection /* fallbackInputConnection */,
mMockRemoteAccessibilityInputConnection /* remoteAccessibilityInputConnection */,
mTargetSdkVersion /* unverifiedTargetSdkVersion */,
mUserId /* userId */,
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 6af4064..9ce86ca 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -116,7 +116,7 @@
@Mock protected IInputMethodClient mMockInputMethodClient;
@Mock protected IInputMethodSession mMockInputMethodSession;
@Mock protected IBinder mWindowToken;
- @Mock protected IRemoteInputConnection mMockRemoteInputConnection;
+ @Mock protected IRemoteInputConnection mMockFallbackInputConnection;
@Mock protected IRemoteAccessibilityInputConnection mMockRemoteAccessibilityInputConnection;
@Mock protected ImeOnBackInvokedDispatcher mMockImeOnBackInvokedDispatcher;
@Mock protected IInputMethodManager.Stub mMockIInputMethodManager;
@@ -300,7 +300,8 @@
lifecycle.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
// Call InputMethodManagerService#addClient() as a preparation to start interacting with it.
- mInputMethodManagerService.addClient(mMockInputMethodClient, mMockRemoteInputConnection, 0);
+ mInputMethodManagerService.addClient(mMockInputMethodClient, mMockFallbackInputConnection,
+ 0 /* selfReportedDisplayId */);
createSessionForClient(mMockInputMethodClient);
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java
index c958bd3..11abc94 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceWindowGainedFocusTest.java
@@ -316,7 +316,7 @@
softInputMode /* softInputMode */,
0 /* windowFlags */,
mEditorInfo /* editorInfo */,
- mMockRemoteInputConnection /* inputConnection */,
+ mMockFallbackInputConnection /* fallbackInputConnection */,
mMockRemoteAccessibilityInputConnection /* remoteAccessibilityInputConnection */,
mTargetSdkVersion /* unverifiedTargetSdkVersion */,
mUserId /* userId */,
diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 7d25acd..a421163 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -152,7 +152,7 @@
}
@Override
- AutomaticBrightnessController.Clock createClock(boolean isEnabled) {
+ AutomaticBrightnessController.Clock createClock() {
return new AutomaticBrightnessController.Clock() {
@Override
public long uptimeMillis() {
@@ -618,39 +618,46 @@
long increment = 500;
// set autobrightness to low
// t = 0
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
// t = 500
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
// t = 1000
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// t = 1500
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// t = 2000
// ensure that our reading is at 0.
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// t = 2500
// first 10000 lux sensor event reading
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
// t = 3000
// lux reading should still not yet be 10000.
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
@@ -659,45 +666,53 @@
// lux has been high (10000) for 1000ms.
// lux reading should be 10000
// short horizon (ambient lux) is high, long horizon is still not high
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
// t = 4000
// stay high
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
// t = 4500
Mockito.clearInvocations(mBrightnessMappingStrategy);
mClock.fastForward(increment);
// short horizon is high, long horizon is high too
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 10000,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
verify(mBrightnessMappingStrategy, times(1)).getBrightness(10000, null, -1);
assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
// t = 5000
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
// t = 5500
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertTrue(mController.getAmbientLux() > 0.0f);
assertTrue(mController.getAmbientLux() < 10000.0f);
// t = 6000
mClock.fastForward(increment);
// ambient lux goes to 0
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// only the values within the horizon should be kept
assertArrayEquals(new float[] {10000, 10000, 0, 0, 0}, mController.getLastSensorValues(),
EPSILON);
- assertArrayEquals(new long[] {4000, 4500, 5000, 5500, 6000},
+ assertArrayEquals(new long[]{4000 + ANDROID_SLEEP_TIME, 4500 + ANDROID_SLEEP_TIME,
+ 5000 + ANDROID_SLEEP_TIME, 5500 + ANDROID_SLEEP_TIME,
+ 6000 + ANDROID_SLEEP_TIME},
mController.getLastSensorTimestamps());
}
@@ -793,7 +808,8 @@
for (int i = 0; i < 1000; i++) {
lux += increment;
mClock.fastForward(increment);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
}
int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment + 1);
@@ -807,17 +823,17 @@
long sensorTimestamp = mClock.now();
for (int i = valuesCount - 1; i >= 1; i--) {
assertEquals(lux, sensorValues[i], EPSILON);
- assertEquals(sensorTimestamp, sensorTimestamps[i]);
+ assertEquals(sensorTimestamp + ANDROID_SLEEP_TIME, sensorTimestamps[i]);
lux -= increment;
sensorTimestamp -= increment;
}
assertEquals(lux, sensorValues[0], EPSILON);
- assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
+ assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG + ANDROID_SLEEP_TIME,
+ sensorTimestamps[0]);
}
@Test
public void testAmbientLuxBuffers_prunedBeyondLongHorizonExceptLatestValue() throws Exception {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
@@ -867,7 +883,8 @@
for (int i = 0; i < 20; i++) {
lux += increment1;
mClock.fastForward(increment1);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
}
int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment1 + 1);
@@ -877,7 +894,8 @@
for (int i = 0; i < initialCapacity - valuesCount; i++) {
lux += increment2;
mClock.fastForward(increment2);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
}
float[] sensorValues = mController.getLastSensorValues();
@@ -890,7 +908,7 @@
long sensorTimestamp = mClock.now();
for (int i = initialCapacity - 1; i >= 1; i--) {
assertEquals(lux, sensorValues[i], EPSILON);
- assertEquals(sensorTimestamp, sensorTimestamps[i]);
+ assertEquals(sensorTimestamp + ANDROID_SLEEP_TIME, sensorTimestamps[i]);
if (i >= valuesCount) {
lux -= increment2;
@@ -901,7 +919,8 @@
}
}
assertEquals(lux, sensorValues[0], EPSILON);
- assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
+ assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG + ANDROID_SLEEP_TIME,
+ sensorTimestamps[0]);
}
@Test
@@ -951,25 +970,29 @@
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 1000
// Lux isn't steady yet
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 1500
// Lux isn't steady yet
mClock.fastForward(500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 2500
// Lux is steady now
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
}
@@ -992,25 +1015,29 @@
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 2000
// Lux isn't steady yet
mClock.fastForward(2000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 2500
// Lux isn't steady yet
mClock.fastForward(500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 4500
// Lux is steady now
mClock.fastForward(2000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
}
@@ -1031,19 +1058,22 @@
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 500
// Lux isn't steady yet
mClock.fastForward(500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
// t = 1500
// Lux is steady now
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
}
@@ -1068,19 +1098,22 @@
// t = 0
// Initial lux
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1200,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 1000
// Lux isn't steady yet
mClock.fastForward(1000);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(1200, mController.getAmbientLux(), EPSILON);
// t = 2500
// Lux is steady now
mClock.fastForward(1500);
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 500,
+ (mClock.now() + ANDROID_SLEEP_TIME) * NANO_SECONDS_MULTIPLIER));
assertEquals(500, mController.getAmbientLux(), EPSILON);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index e0e4425..c151732 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -984,8 +984,7 @@
Handler handler = displayManager.getDisplayHandler();
waitForIdleHandler(handler);
- assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_BASIC_CHANGED,
- EVENT_DISPLAY_REFRESH_RATE_CHANGED);
+ assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_BASIC_CHANGED);
}
/**
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 aed1f98..db94958 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1066,7 +1066,6 @@
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true);
- when(mDisplayManagerFlagsMock.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession);
@@ -1172,7 +1171,6 @@
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true);
- when(mDisplayManagerFlagsMock.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(false);
mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
index 2ebb6c2a3..ef39167 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -240,7 +240,6 @@
@Test
public void selectStrategyDoesNotSelectDozeStrategyWhenOffloadSessionAutoBrightnessIsEnabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -378,7 +377,6 @@
@Test
public void selectStrategy_selectsAutomaticStrategyWhenValid() {
when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -409,7 +407,6 @@
@Test
public void selectStrategy_doesNotSelectAutomaticStrategyWhenStylusInUse() {
when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -536,7 +533,6 @@
@Test
public void setAllowAutoBrightnessWhileDozing_enabledWhenConfigAndOffloadSessionAreEnabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -550,7 +546,6 @@
@Test
public void setAllowAutoBrightnessWhileDozing_disabledWhenOffloadSessionFlagIsDisabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(false);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -564,7 +559,6 @@
@Test
public void setAllowAutoBrightnessWhileDozing_disabledWhenABWhileDozingConfigIsDisabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
when(mDisplayOffloadSession.allowAutoBrightnessInDoze()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
@@ -588,7 +582,6 @@
@Test
public void setAllowAutoBrightnessWhileDozing_EnabledWhenFlagsAreDisabled() {
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(true);
when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
true);
mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
@@ -600,11 +593,5 @@
mDisplayBrightnessStrategySelector
.setAllowAutoBrightnessWhileDozing(mDisplayOffloadSession);
assertTrue(mDisplayBrightnessStrategySelector.isAllowAutoBrightnessWhileDozing());
-
- when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(true);
- when(mDisplayManagerFlags.offloadControlsDozeAutoBrightness()).thenReturn(false);
- mDisplayBrightnessStrategySelector
- .setAllowAutoBrightnessWhileDozing(mDisplayOffloadSession);
- assertTrue(mDisplayBrightnessStrategySelector.isAllowAutoBrightnessWhileDozing());
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 6c73f0a..eda5e86 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -23,7 +23,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.PackageWatchdog.MITIGATION_RESULT_SKIPPED;
import static com.android.server.PackageWatchdog.MITIGATION_RESULT_SUCCESS;
@@ -34,8 +33,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import android.content.ContentResolver;
@@ -43,12 +40,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
-import android.crashrecovery.flags.Flags;
import android.os.RecoverySystem;
import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.platform.test.flag.junit.FlagsParameterization;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -59,14 +52,8 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
import org.mockito.Answers;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
@@ -75,34 +62,19 @@
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Test RescueParty.
*/
-@RunWith(Parameterized.class)
public class RescuePartyTest {
- @Rule
- public SetFlagsRule mSetFlagsRule;
private static final long CURRENT_NETWORK_TIME_MILLIS = 0L;
- private static final String FAKE_NATIVE_NAMESPACE1 = "native1";
- private static final String FAKE_NATIVE_NAMESPACE2 = "native2";
- private static final String[] FAKE_RESET_NATIVE_NAMESPACES =
- {FAKE_NATIVE_NAMESPACE1, FAKE_NATIVE_NAMESPACE2};
private static VersionedPackage sFailingPackage = new VersionedPackage("com.package.name", 1);
private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue";
- private static final String CALLING_PACKAGE1 = "com.package.name1";
- private static final String CALLING_PACKAGE2 = "com.package.name2";
- private static final String CALLING_PACKAGE3 = "com.package.name3";
private static final String PERSISTENT_PACKAGE = "com.persistent.package";
private static final String NON_PERSISTENT_PACKAGE = "com.nonpersistent.package";
- private static final String NAMESPACE1 = "namespace1";
- private static final String NAMESPACE2 = "namespace2";
- private static final String NAMESPACE3 = "namespace3";
- private static final String NAMESPACE4 = "namespace4";
private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
"persist.device_config.configuration.disable_rescue_party";
private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
@@ -126,21 +98,6 @@
// Mock only sysprop apis
private PackageWatchdog.BootThreshold mSpyBootThreshold;
- @Captor
- private ArgumentCaptor<DeviceConfig.MonitorCallback> mMonitorCallbackCaptor;
- @Captor
- private ArgumentCaptor<List<String>> mPackageListCaptor;
-
- @Parameters(name = "{0}")
- public static List<FlagsParameterization> getFlags() {
- return FlagsParameterization.allCombinationsOf(
- Flags.FLAG_RECOVERABILITY_DETECTION);
- }
-
- public RescuePartyTest(FlagsParameterization flags) {
- mSetFlagsRule = new SetFlagsRule(flags);
- }
-
@Before
public void setUp() throws Exception {
mSession =
@@ -419,25 +376,6 @@
}
- private void verifySettingsResets(int resetMode, String[] resetNamespaces,
- HashMap<String, Integer> configResetVerifiedTimesMap) {
- verifyOnlySettingsReset(resetMode);
- }
-
- private void verifyOnlySettingsReset(int resetMode) {
- verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null,
- resetMode, UserHandle.USER_SYSTEM));
- verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(),
- eq(resetMode), anyInt()));
- }
-
- private void verifyNoSettingsReset(int resetMode) {
- verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null,
- resetMode, UserHandle.USER_SYSTEM), never());
- verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(),
- eq(resetMode), anyInt()), never());
- }
-
private void noteBoot(int mitigationCount) {
RescuePartyObserver.getInstance(mMockContext).onExecuteBootLoopMitigation(mitigationCount);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
index 5ddd8a5..2e315ec 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
@@ -26,7 +26,10 @@
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.pm.PackageManagerInternal;
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
@@ -54,6 +57,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.List;
import java.util.Set;
@SmallTest
@@ -74,6 +78,7 @@
@Mock private WindowManagerInternal mWindowManager;
@Mock private MediaProjectionManager mProjectionManager;
@Mock private PackageManagerInternal mPackageManagerInternal;
+ @Mock private RoleManager mRoleManager;
private MediaProjectionInfo mMediaProjectionInfo;
@Captor
@@ -93,7 +98,8 @@
mSensitiveContentProtectionManagerService =
new SensitiveContentProtectionManagerService(mContext);
mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager,
- mPackageManagerInternal, new ArraySet<>(Set.of(mExemptedScreenRecorderPackage)));
+ mPackageManagerInternal, mRoleManager,
+ new ArraySet<>(Set.of(mExemptedScreenRecorderPackage)));
verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any());
mMediaPorjectionCallback = mMediaProjectionCallbackCaptor.getValue();
mMediaProjectionInfo =
@@ -152,7 +158,7 @@
String testAutofillService = mScreenRecorderPackage + "/com.example.SampleAutofillService";
int userId = Process.myUserHandle().getIdentifier();
Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.AUTOFILL_SERVICE, testAutofillService , userId);
+ Settings.Secure.AUTOFILL_SERVICE, testAutofillService, userId);
mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
@@ -169,6 +175,19 @@
verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
}
+ @Test
+ public void testAppStreamingRoleHolderExemption() {
+ when(mRoleManager.getRoleHoldersAsUser(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mMediaProjectionInfo.getUserHandle())).thenReturn(
+ List.of(mMediaProjectionInfo.getPackageName()));
+
+ mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
+ mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
+ mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+ }
+
private void mockDisabledViaDeveloperOption() {
Settings.Global.putInt(
mContext.getContentResolver(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
index 32135f1..3c6e18f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
@@ -33,6 +33,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
import android.content.pm.PackageManagerInternal;
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
@@ -67,6 +69,7 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.List;
import java.util.Set;
@SmallTest
@@ -116,6 +119,9 @@
private PackageManagerInternal mPackageManagerInternal;
@Mock
+ private RoleManager mRoleManager;
+
+ @Mock
private StatusBarNotification mNotification1;
@Mock
@@ -161,7 +167,8 @@
setupSensitiveNotification();
mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager,
- mPackageManagerInternal, new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE)));
+ mPackageManagerInternal, mRoleManager,
+ new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE)));
// Obtain useful mMediaProjectionCallback
verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any());
@@ -315,6 +322,18 @@
}
@Test
+ public void mediaProjectionOnStart_verifyExemptedAppStreamingPackage() {
+ MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo();
+ when(mRoleManager.getRoleHoldersAsUser(AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+ mediaProjectionInfo.getUserHandle())).thenReturn(
+ List.of(mediaProjectionInfo.getPackageName()));
+
+ mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
+
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+ }
+
+ @Test
public void mediaProjectionOnStart_verifyExemptedRecorderPackage() {
MediaProjectionInfo mediaProjectionInfo = createExemptMediaProjectionInfo();
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 fa58475..4b53f13 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -23,18 +23,11 @@
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;
@@ -44,14 +37,12 @@
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;
@@ -68,11 +59,9 @@
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;
/**
@@ -164,7 +153,7 @@
app.info.uid = packageUid;
// Exact value does not mater, it can be any state for which compaction is allowed.
app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
- app.mState.setSetAdj(899);
+ app.mState.setSetAdj(940);
app.mState.setCurAdj(940);
return app;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 1ef758c..340115a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -3337,6 +3337,108 @@
followUpTimeCaptor.capture());
}
+ /**
+ * For Perceptible Tasks adjustment, this solely unit-tests OomAdjuster -> onOtherActivity()
+ */
+ @SuppressWarnings("GuardedBy")
+ @Test
+ @EnableFlags(Flags.FLAG_PERCEPTIBLE_TASKS)
+ public void testPerceptibleAdjustment() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+
+ long now = mInjector.getUptimeMillis();
+
+ // GIVEN: perceptible adjustment is NOT enabled (perceptible stop time is not set)
+ // EXPECT: zero adjustment
+ // TLDR: App is not set as a perceptible task and hence no oom_adj boosting.
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.initialize(app, CACHED_APP_MIN_ADJ,
+ false, false, PROCESS_STATE_CACHED_ACTIVITY,
+ SCHED_GROUP_DEFAULT, 0, 0, PROCESS_STATE_IMPORTANT_FOREGROUND);
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.onOtherActivity(-1);
+ assertEquals(CACHED_APP_MIN_ADJ, mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.adj);
+
+ // GIVEN: perceptible adjustment is enabled (perceptible stop time is set) and
+ // elapsed time < PERCEPTIBLE_TASK_TIMEOUT
+ // EXPECT: adjustment to PERCEPTIBLE_MEDIUM_APP_ADJ
+ // TLDR: App is a perceptible task (e.g. opened from launcher) and has oom_adj boosting.
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.initialize(app, CACHED_APP_MIN_ADJ,
+ false, false, PROCESS_STATE_CACHED_ACTIVITY,
+ SCHED_GROUP_DEFAULT, 0, 0, PROCESS_STATE_IMPORTANT_FOREGROUND);
+ mInjector.reset();
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.onOtherActivity(now);
+ assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ,
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.adj);
+
+ // GIVEN: perceptible adjustment is enabled (perceptible stop time is set) and
+ // elapsed time > PERCEPTIBLE_TASK_TIMEOUT
+ // EXPECT: adjustment to PREVIOUS_APP_ADJ
+ // TLDR: App is a perceptible task (e.g. opened from launcher) and has oom_adj boosting, but
+ // time has elapsed and has dropped to a lower boosting of PREVIOUS_APP_ADJ
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.initialize(app, CACHED_APP_MIN_ADJ,
+ false, false, PROCESS_STATE_CACHED_ACTIVITY,
+ SCHED_GROUP_DEFAULT, 0, 0, PROCESS_STATE_IMPORTANT_FOREGROUND);
+ mInjector.jumpUptimeAheadTo(OomAdjuster.PERCEPTIBLE_TASK_TIMEOUT_MILLIS + 1000);
+ mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.onOtherActivity(0);
+ assertEquals(PREVIOUS_APP_ADJ, mService.mOomAdjuster.mTmpComputeOomAdjWindowCallback.adj);
+ }
+
+ /**
+ * For Perceptible Tasks adjustment, this tests overall adjustment flow.
+ */
+ @SuppressWarnings("GuardedBy")
+ @Test
+ @EnableFlags(Flags.FLAG_PERCEPTIBLE_TASKS)
+ public void testUpdateOomAdjPerceptible() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ WindowProcessController wpc = app.getWindowProcessController();
+
+ // Set uptime to be at least the timeout time + buffer, so that we don't end up with
+ // negative stopTime in our test input
+ mInjector.jumpUptimeAheadTo(OomAdjuster.PERCEPTIBLE_TASK_TIMEOUT_MILLIS + 60L * 1000L);
+ long now = mInjector.getUptimeMillis();
+ doReturn(true).when(wpc).hasActivities();
+
+ // GIVEN: perceptible adjustment is is enabled
+ // EXPECT: perceptible-act adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING)
+ .when(wpc).getActivityStateFlags();
+ doReturn(now).when(wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_IMPORTANT_BACKGROUND, PERCEPTIBLE_MEDIUM_APP_ADJ,
+ SCHED_GROUP_BACKGROUND, "perceptible-act");
+
+ // GIVEN: perceptible adjustment is is enabled and timeout has been reached
+ // EXPECT: stale-perceptible-act adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING)
+ .when(wpc).getActivityStateFlags();
+
+ doReturn(now - OomAdjuster.PERCEPTIBLE_TASK_TIMEOUT_MILLIS).when(
+ wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, PREVIOUS_APP_ADJ,
+ SCHED_GROUP_BACKGROUND, "stale-perceptible-act");
+
+ // GIVEN: perceptible adjustment is is disabled
+ // EXPECT: no perceptible adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING)
+ .when(wpc).getActivityStateFlags();
+ doReturn(Long.MIN_VALUE).when(wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_CACHED_ACTIVITY, CACHED_APP_MIN_ADJ,
+ SCHED_GROUP_BACKGROUND, "cch-act");
+
+ // GIVEN: perceptible app is in foreground
+ // EXPECT: no perceptible adjustment
+ doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_VISIBLE)
+ .when(wpc).getActivityStateFlags();
+ doReturn(now).when(wpc).getPerceptibleTaskStoppedTimeMillis();
+ updateOomAdj(app);
+ assertProcStates(app, PROCESS_STATE_TOP, VISIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT, "vis-activity");
+ }
+
@SuppressWarnings("GuardedBy")
@Test
public void testUpdateOomAdj_DoAll_Multiple_Provider_Retention() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/Android.bp b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/Android.bp
index 8eae9c7d..e030b3f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/Android.bp
+++ b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/Android.bp
@@ -32,18 +32,18 @@
static_libs: [
"androidx.test.core",
"androidx.test.runner",
+ "flag-junit",
"mockito-target-extended-minus-junit4",
"services.core",
"truth",
- "flag-junit",
] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), {
"true": ["service-crashrecovery-pre-jarjar"],
default: [],
}),
libs: [
- "android.test.mock.stubs.system",
"android.test.base.stubs.system",
+ "android.test.mock.stubs.system",
"android.test.runner.stubs.system",
],
@@ -55,7 +55,9 @@
certificate: "platform",
platform_apis: true,
test_suites: [
- "device-tests",
"automotive-tests",
+ "device-tests",
+ "mts-crashrecovery",
],
+ min_sdk_version: "36",
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidTest.xml b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidTest.xml
index 7b06ebe..5043c47 100644
--- a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidTest.xml
+++ b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidTest.xml
@@ -31,4 +31,9 @@
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
+
+ <!-- Only run this Tests if the Crashrecovery Mainline module is installed. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.crashrecovery" />
+ </object>
</configuration>
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobServiceContextTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobServiceContextTest.java
index 904545b..b4e8451 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobServiceContextTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobServiceContextTest.java
@@ -276,6 +276,7 @@
final int jobId = 123;
mJobServiceContext.setRunningJobLockedForTest(mMockJobStatus);
mJobServiceContext.setRunningCallbackLockedForTest(mMockJobCallback);
+ mJobServiceContext.mVerb = JobServiceContext.VERB_EXECUTING;
doReturn(jobId).when(mMockJobStatus).getJobId();
mJobServiceContext.doHandleAbandonedJob(mMockJobCallback, jobId);
@@ -296,7 +297,25 @@
mJobServiceContext.setRunningCallbackLockedForTest(mMockJobCallback);
mJobServiceContext.doHandleAbandonedJob(mMockJobCallback, jobId);
+ verify(mMockJobStatus, never()).setAbandoned(true);
+ mJobServiceContext.setRunningJobLockedForTest(mMockJobStatus);
+ doReturn(jobId).when(mMockJobStatus).getJobId();
+
+ mJobServiceContext.mVerb = JobServiceContext.VERB_BINDING;
+ mJobServiceContext.doHandleAbandonedJob(mMockJobCallback, jobId);
+ verify(mMockJobStatus, never()).setAbandoned(true);
+
+ mJobServiceContext.mVerb = JobServiceContext.VERB_STARTING;
+ mJobServiceContext.doHandleAbandonedJob(mMockJobCallback, jobId);
+ verify(mMockJobStatus, never()).setAbandoned(true);
+
+ mJobServiceContext.mVerb = JobServiceContext.VERB_STOPPING;
+ mJobServiceContext.doHandleAbandonedJob(mMockJobCallback, jobId);
+ verify(mMockJobStatus, never()).setAbandoned(true);
+
+ mJobServiceContext.mVerb = JobServiceContext.VERB_FINISHED;
+ mJobServiceContext.doHandleAbandonedJob(mMockJobCallback, jobId);
verify(mMockJobStatus, never()).setAbandoned(true);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index c6870ad..4e4b3df 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -295,15 +295,15 @@
}
private void setCharging() {
- doReturn(true).when(mJobSchedulerService).isBatteryCharging();
synchronized (mQuotaController.mLock) {
+ doReturn(true).when(mJobSchedulerService).isBatteryCharging();
mQuotaController.onBatteryStateChangedLocked();
}
}
private void setDischarging() {
- doReturn(false).when(mJobSchedulerService).isBatteryCharging();
synchronized (mQuotaController.mLock) {
+ doReturn(false).when(mJobSchedulerService).isBatteryCharging();
mQuotaController.onBatteryStateChangedLocked();
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
index 5a802d9..36b064b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
@@ -30,18 +30,18 @@
static_libs: [
"androidx.test.runner",
+ "flag-junit",
"mockito-target-extended-minus-junit4",
"services.core",
"truth",
- "flag-junit",
] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), {
"true": ["service-crashrecovery-pre-jarjar"],
default: [],
}),
libs: [
- "android.test.mock.stubs.system",
"android.test.base.stubs.system",
+ "android.test.mock.stubs.system",
"android.test.runner.stubs.system",
],
@@ -53,9 +53,11 @@
certificate: "platform",
platform_apis: true,
test_suites: [
- "device-tests",
"automotive-tests",
+ "device-tests",
+ "mts-crashrecovery",
],
+ min_sdk_version: "36",
}
test_module_config {
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidTest.xml b/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidTest.xml
index 635183c..6f6b017 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidTest.xml
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidTest.xml
@@ -31,4 +31,9 @@
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
+
+ <!-- Only run this Tests if the Crashrecovery Mainline module is installed. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.crashrecovery" />
+ </object>
</configuration>
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
index 347dc81..fb4d81a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
@@ -43,7 +43,6 @@
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
-import android.crashrecovery.flags.Flags;
import android.os.Handler;
import android.os.MessageQueue;
import android.os.SystemProperties;
@@ -273,7 +272,6 @@
@Test
public void healthCheckFailed_impactLevelLow_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -304,7 +302,6 @@
@Test
public void healthCheckFailed_impactLevelHigh_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -335,7 +332,6 @@
@Test
public void healthCheckFailed_impactLevelManualOnly_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -365,7 +361,6 @@
@Test
public void healthCheckFailed_impactLevelLowAndHigh_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -404,7 +399,6 @@
@Test
public void execute_impactLevelLow_nativeCrash_rollback()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -438,7 +432,6 @@
@Test
public void execute_impactLevelLow_rollbackFailedPackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -483,7 +476,6 @@
@Test
public void execute_impactLevelLow_rollbackAll()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -530,7 +522,6 @@
@Test
public void execute_impactLevelLowAndHigh_rollbackLow()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -578,7 +569,6 @@
@Test
public void execute_impactLevelHigh_rollbackHigh()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId2 = 2;
VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
@@ -612,7 +602,6 @@
*/
@Test
public void onBootLoop_impactLevelLow_onePackage() throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -637,7 +626,6 @@
@Test
public void onBootLoop_impactLevelHigh_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -662,7 +650,6 @@
@Test
public void onBootLoop_impactLevelHighDisableHighImpactRollback_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(true));
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -692,7 +679,6 @@
@Test
public void onBootLoop_impactLevelManualOnly_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -720,7 +706,6 @@
@Test
public void onBootLoop_impactLevelLowAndHigh_onePackage()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
@@ -757,7 +742,6 @@
@Test
public void executeBootLoopMitigation_impactLevelLow_rollbackAll()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -802,7 +786,6 @@
@Test
public void executeBootLoopMitigation_impactLevelLowAndHigh_rollbackLow()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -847,7 +830,6 @@
@Test
public void executeBootLoopMitigation_impactLevelHigh_rollbackHigh()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId2 = 2;
VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
@@ -882,7 +864,6 @@
@Test
public void execute_impactLevelLowAndManual_rollbackLowImpactOnly()
throws PackageManager.NameNotFoundException, InterruptedException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -928,7 +909,6 @@
@Test
public void execute_impactLevelManual_rollbackLowImpactOnly()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
@@ -962,7 +942,6 @@
@Test
public void executeBootLoopMitigation_impactLevelHighMultiplePackage_rollbackHigh()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
int rollbackId1 = 1;
VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
@@ -1008,7 +987,6 @@
@Test
public void executeBootLoopMitigation_impactLevelHighKillSwitchTrue_rollbackHigh()
throws PackageManager.NameNotFoundException {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(true));
int rollbackId1 = 1;
VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java
index b53f6fb..49c37f1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java
@@ -16,6 +16,7 @@
package com.android.server.wallpaper;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
import static android.app.WallpaperManager.ORIENTATION_LANDSCAPE;
import static android.app.WallpaperManager.ORIENTATION_UNKNOWN;
import static android.app.WallpaperManager.ORIENTATION_PORTRAIT;
@@ -23,13 +24,20 @@
import static android.app.WallpaperManager.ORIENTATION_SQUARE_PORTRAIT;
import static android.app.WallpaperManager.getOrientation;
import static android.app.WallpaperManager.getRotatedOrientation;
+import static android.os.UserHandle.USER_SYSTEM;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.window.flags.Flags.FLAG_MULTI_CROP;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
@@ -37,15 +45,29 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.util.Log;
import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
import androidx.test.runner.AndroidJUnit4;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.quality.Strictness;
+import java.io.File;
+import java.io.IOException;
import java.util.Comparator;
import java.util.List;
@@ -57,6 +79,7 @@
@RunWith(AndroidJUnit4.class)
@RequiresFlagsEnabled(FLAG_MULTI_CROP)
public class WallpaperCropperTest {
+ private static final String TAG = "WallpaperCropperTest";
@Mock
private WallpaperDisplayHelper mWallpaperDisplayHelper;
@@ -94,6 +117,8 @@
private static final List<List<Point>> ALL_FOLDABLE_DISPLAYS = List.of(
FOLDABLE_ONE, FOLDABLE_TWO, FOLDABLE_THREE, FOLDABLE_FOUR);
+ private static StaticMockitoSession sMockitoSession;
+
private SparseArray<Point> mDisplaySizes = new SparseArray<>();
private int mFolded = ORIENTATION_UNKNOWN;
private int mFoldedRotated = ORIENTATION_UNKNOWN;
@@ -103,12 +128,53 @@
private static final List<Integer> ALL_MODES = List.of(
WallpaperCropper.ADD, WallpaperCropper.REMOVE, WallpaperCropper.BALANCE);
+ private final SparseArray<File> mTempDirs = new SparseArray<>();
+
+ private final TemporaryFolder mFolder = new TemporaryFolder();
+
+ @Rule
+ public RuleChain rules = RuleChain.outerRule(mFolder);
+
+ @BeforeClass
+ public static void setUpClass() {
+ sMockitoSession = mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .spyStatic(WallpaperUtils.class)
+ .startMocking();
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ if (sMockitoSession != null) {
+ sMockitoSession.finishMocking();
+ sMockitoSession = null;
+ }
+ }
+
@Before
public void setUp() {
initMocks(this);
+ ExtendedMockito.doAnswer(invocation -> {
+ int userId = (invocation.getArgument(0));
+ return getWallpaperTestDir(userId);
+ }).when(() -> WallpaperUtils.getWallpaperDir(anyInt()));
+
mWallpaperCropper = new WallpaperCropper(mWallpaperDisplayHelper);
}
+ private File getWallpaperTestDir(int userId) {
+ File tempDir = mTempDirs.get(userId);
+ if (tempDir == null) {
+ try {
+ tempDir = mFolder.newFolder(String.valueOf(userId));
+ mTempDirs.append(userId, tempDir);
+ } catch (IOException e) {
+ Log.e(TAG, "getWallpaperTestDir failed at userId= " + userId);
+ }
+ }
+ return tempDir;
+ }
+
private void setUpWithDisplays(List<Point> displaySizes) {
mDisplaySizes = new SparseArray<>();
displaySizes.forEach(size -> {
@@ -632,6 +698,134 @@
}
}
+ // Test isWallpaperCompatibleForDisplay always return true for the default display.
+ @Test
+ public void isWallpaperCompatibleForDisplay_defaultDisplay_returnTrue()
+ throws Exception {
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 2560;
+ displayInfo.logicalHeight = 1044;
+ doReturn(displayInfo).when(mWallpaperDisplayHelper).getDisplayInfo(eq(DEFAULT_DISPLAY));
+ WallpaperData wallpaperData = createWallpaperData(/* isStockWallpaper = */ false,
+ new Point(100, 100));
+
+ assertThat(
+ mWallpaperCropper.isWallpaperCompatibleForDisplay(DEFAULT_DISPLAY,
+ wallpaperData)).isTrue();
+ }
+
+ // Test isWallpaperCompatibleForDisplay always return true for the stock wallpaper.
+ @Test
+ public void isWallpaperCompatibleForDisplay_stockWallpaper_returnTrue()
+ throws Exception {
+ final int displayId = 2;
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 2560;
+ displayInfo.logicalHeight = 1044;
+ doReturn(displayInfo).when(mWallpaperDisplayHelper).getDisplayInfo(eq(displayId));
+ WallpaperData wallpaperData = createWallpaperData(/* isStockWallpaper = */ true,
+ new Point(100, 100));
+
+ assertThat(
+ mWallpaperCropper.isWallpaperCompatibleForDisplay(displayId,
+ wallpaperData)).isTrue();
+ }
+
+ // Test isWallpaperCompatibleForDisplay wallpaper is suitable for the display and wallpaper
+ // aspect ratio meets the hard-coded aspect ratio.
+ @Test
+ public void isWallpaperCompatibleForDisplay_wallpaperSizeSuitableForDisplayAndMeetAspectRatio_returnTrue()
+ throws Exception {
+ final int displayId = 2;
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 2560;
+ displayInfo.logicalHeight = 1044;
+ doReturn(displayInfo).when(mWallpaperDisplayHelper).getDisplayInfo(eq(displayId));
+ WallpaperData wallpaperData = createWallpaperData(/* isStockWallpaper = */ false,
+ new Point(4000, 3000));
+
+ assertThat(
+ mWallpaperCropper.isWallpaperCompatibleForDisplay(displayId,
+ wallpaperData)).isTrue();
+ }
+
+ // Test isWallpaperCompatibleForDisplay wallpaper is not suitable for the display and wallpaper
+ // aspect ratio meets the hard-coded aspect ratio.
+ @Test
+ public void isWallpaperCompatibleForDisplay_wallpaperSizeNotSuitableForDisplayAndMeetAspectRatio_returnFalse()
+ throws Exception {
+ final int displayId = 2;
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 2560;
+ displayInfo.logicalHeight = 1044;
+ doReturn(displayInfo).when(mWallpaperDisplayHelper).getDisplayInfo(eq(displayId));
+ WallpaperData wallpaperData = createWallpaperData(/* isStockWallpaper = */ false,
+ new Point(1000, 500));
+
+ assertThat(
+ mWallpaperCropper.isWallpaperCompatibleForDisplay(displayId,
+ wallpaperData)).isFalse();
+ }
+
+ // Test isWallpaperCompatibleForDisplay wallpaper is suitable for the display and wallpaper
+ // aspect ratio doesn't meet the hard-coded aspect ratio.
+ @Test
+ public void isWallpaperCompatibleForDisplay_wallpaperSizeSuitableForDisplayAndDoNotMeetAspectRatio_returnFalse()
+ throws Exception {
+ final int displayId = 2;
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 2560;
+ displayInfo.logicalHeight = 1044;
+ doReturn(displayInfo).when(mWallpaperDisplayHelper).getDisplayInfo(eq(displayId));
+ WallpaperData wallpaperData = createWallpaperData(/* isStockWallpaper = */ false,
+ new Point(2000, 4000));
+
+ assertThat(
+ mWallpaperCropper.isWallpaperCompatibleForDisplay(displayId,
+ wallpaperData)).isFalse();
+ }
+
+ // Test isWallpaperCompatibleForDisplay, portrait display, wallpaper is suitable for the display
+ // and wallpaper aspect ratio doesn't meet the hard-coded aspect ratio.
+ @Test
+ public void isWallpaperCompatibleForDisplay_portraitDisplay_wallpaperSizeSuitableForDisplayAndMeetAspectRatio_returnTrue()
+ throws Exception {
+ final int displayId = 2;
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = 1044;
+ displayInfo.logicalHeight = 2560;
+ doReturn(displayInfo).when(mWallpaperDisplayHelper).getDisplayInfo(eq(displayId));
+ WallpaperData wallpaperData = createWallpaperData(/* isStockWallpaper = */ false,
+ new Point(2000, 4000));
+
+ assertThat(
+ mWallpaperCropper.isWallpaperCompatibleForDisplay(displayId,
+ wallpaperData)).isTrue();
+ }
+
+ private void mockDisplay(int displayId, Point displayResolution) {
+ final Display mockDisplay = mock(Display.class);
+ when(mockDisplay.getDisplayInfo(any(DisplayInfo.class))).thenAnswer(invocation -> {
+ DisplayInfo displayInfo = invocation.getArgument(0);
+ displayInfo.displayId = displayId;
+ displayInfo.logicalWidth = displayResolution.x;
+ displayInfo.logicalHeight = displayResolution.y;
+ return true;
+ });
+ }
+
+ private WallpaperData createWallpaperData(boolean isStockWallpaper, Point wallpaperSize)
+ throws Exception {
+ WallpaperData wallpaperData = new WallpaperData(USER_SYSTEM, FLAG_SYSTEM);
+ File wallpaperFile = wallpaperData.getWallpaperFile();
+ if (!isStockWallpaper) {
+ wallpaperFile.getParentFile().mkdirs();
+ wallpaperFile.createNewFile();
+ }
+ wallpaperData.cropHint.set(0, 0, wallpaperSize.x, wallpaperSize.y);
+ return wallpaperData;
+ }
+
private static Rect centerOf(Rect container, Point point) {
checkSubset(container, point);
int diffWidth = container.width() - point.x;
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index bc04fd9..bada337 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -123,6 +123,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.Map;
/**
* Tests for the {@link WallpaperManagerService} class.
@@ -258,6 +259,8 @@
spyOn(mIpm);
spyOn(mResources);
doReturn(true).when(mResources).getBoolean(eq(R.bool.config_isDesktopModeSupported));
+ doReturn(true).when(mResources).getBoolean(
+ eq(R.bool.config_canInternalDisplayHostDesktops));
mService = new TestWallpaperManagerService(sContext);
spyOn(mService);
mService.systemReady();
@@ -742,7 +745,9 @@
wallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ testDisplayId, true));
// WHEN display ID, 2, is ready.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
@@ -782,7 +787,9 @@
lockWallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ testDisplayId, true));
// WHEN display ID, 2, is ready.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
@@ -823,13 +830,15 @@
throws Exception {
final int testUserId = USER_SYSTEM;
mService.switchUser(testUserId, null);
+ mService.mLastWallpaper.connection.mWallpaper.cropHint.set(0, 0, 4000, 2250);
IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
mService.mFallbackWallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
- // GIVEN the wallpaper isn't compatible with display ID, 2
- mService.removeWallpaperCompatibleDisplayForTest(testDisplayId);
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ // Given the wallpaper is smaller thn the display resolution.
+ testDisplayId, false));
// WHEN display ID, 2, is ready.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
@@ -868,7 +877,10 @@
wallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ mService.mLastWallpaper.connection.mWallpaper.cropHint.set(0, 0, 4000, 2250);
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ testDisplayId, true));
// GIVEN wallpaper connections have been established for display ID, 2.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
@@ -906,7 +918,9 @@
lockWallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ testDisplayId, true));
// GIVEN wallpaper connections have been established for display ID, 2.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
@@ -940,9 +954,9 @@
mService.mFallbackWallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
- // GIVEN display ID, 2, is incompatible with the wallpaper.
- mService.removeWallpaperCompatibleDisplayForTest(testDisplayId);
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ testDisplayId, false));
// GIVEN wallpaper connections have been established for display ID, 2.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
@@ -989,7 +1003,9 @@
wallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ testDisplayId, true));
// GIVEN wallpaper connections have been established for displayID, 2.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
@@ -1023,7 +1039,9 @@
lockWallpaper.connection.mService = mockIWallpaperService;
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
- setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ testDisplayId, true));
// GIVEN wallpaper connections have been established for displayID, 2.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
@@ -1051,12 +1069,14 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
public void deviceBooted_multiDisplays_shouldHaveExpectedConnections() {
+ final int testUserId = USER_SYSTEM;
final int incompatibleDisplayId = 2;
final int compatibleDisplayId = 3;
- setUpDisplays(List.of(DEFAULT_DISPLAY, incompatibleDisplayId, compatibleDisplayId));
- mService.removeWallpaperCompatibleDisplayForTest(incompatibleDisplayId);
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ compatibleDisplayId, true,
+ incompatibleDisplayId, false));
- final int testUserId = USER_SYSTEM;
// After reboot, a switch user triggers the wallpapers initialization.
mService.switchUser(testUserId, null);
@@ -1087,15 +1107,18 @@
public void setWallpaperComponent_multiDisplays_displayBecomeCompatible_shouldHaveExpectedConnections() {
final int display2 = 2;
final int display3 = 3;
- setUpDisplays(List.of(DEFAULT_DISPLAY, display2, display3));
- mService.removeWallpaperCompatibleDisplayForTest(display2);
final int testUserId = USER_SYSTEM;
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ display2, false,
+ display3, true));
+
mService.switchUser(testUserId, null);
+ doReturn(true).when(mService.mWallpaperCropper).isWallpaperCompatibleForDisplay(
+ eq(display2), any());
// Switch to a test wallpaper and then image wallpaper later to simulate a wallpaper change.
mService.setWallpaperComponent(TEST_WALLPAPER_COMPONENT, sContext.getOpPackageName(),
FLAG_SYSTEM | FLAG_LOCK, testUserId);
- mService.addWallpaperCompatibleDisplayForTest(display2);
-
mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
FLAG_SYSTEM | FLAG_LOCK, testUserId);
@@ -1124,15 +1147,19 @@
public void setWallpaperComponent_multiDisplays_displayBecomeIncompatible_shouldHaveExpectedConnections() {
final int display2 = 2;
final int display3 = 3;
- setUpDisplays(List.of(DEFAULT_DISPLAY, display2, display3));
- mService.removeWallpaperCompatibleDisplayForTest(display2);
final int testUserId = USER_SYSTEM;
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ display2, true,
+ display3, true));
mService.switchUser(testUserId, null);
+ doReturn(false).when(mService.mWallpaperCropper).isWallpaperCompatibleForDisplay(
+ eq(display2), any());
+ doReturn(false).when(mService.mWallpaperCropper).isWallpaperCompatibleForDisplay(
+ eq(display3), any());
// Switch to a test wallpaper and then image wallpaper later to simulate a wallpaper change.
mService.setWallpaperComponent(TEST_WALLPAPER_COMPONENT, sContext.getOpPackageName(),
FLAG_SYSTEM | FLAG_LOCK, testUserId);
- mService.removeWallpaperCompatibleDisplayForTest(display3);
-
mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
FLAG_SYSTEM | FLAG_LOCK, testUserId);
@@ -1159,14 +1186,15 @@
public void setWallpaperComponent_systemAndLockWallpapers_multiDisplays_shouldHaveExpectedConnections() {
final int incompatibleDisplayId = 2;
final int compatibleDisplayId = 3;
- setUpDisplays(List.of(DEFAULT_DISPLAY, incompatibleDisplayId, compatibleDisplayId));
+ setUpDisplays(Map.of(
+ DEFAULT_DISPLAY, true,
+ incompatibleDisplayId, false,
+ compatibleDisplayId, true));
final int testUserId = USER_SYSTEM;
mService.switchUser(testUserId, null);
// Switch to a test wallpaper and then image wallpaper later to simulate a wallpaper change.
mService.setWallpaperComponent(TEST_WALLPAPER_COMPONENT, sContext.getOpPackageName(),
FLAG_SYSTEM | FLAG_LOCK, testUserId);
- mService.removeWallpaperCompatibleDisplayForTest(incompatibleDisplayId);
-
mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
FLAG_SYSTEM, testUserId);
@@ -1258,21 +1286,27 @@
* to return them. It also sets up the {@link WindowManagerInternal} to indicate that all
* displays support home.
*
- * @param displayIds A list of display IDs to create mock displays for.
+ * @param displayIdsToWallpaperCompatibility A map of display IDs to wallpaper compatibility.
*/
- private void setUpDisplays(List<Integer> displayIds) {
+ private void setUpDisplays(Map<Integer, Boolean> displayIdsToWallpaperCompatibility) {
+ spyOn(mService.mWallpaperCropper);
doReturn(true).when(sWindowManagerInternal).isHomeSupportedOnDisplay(anyInt());
- Display[] mockDisplays = new Display[displayIds.size()];
- for (int i = 0; i < displayIds.size(); i++) {
- final int displayId = displayIds.get(i);
+ Display[] mockDisplays = new Display[displayIdsToWallpaperCompatibility.size()];
+ int counter = 0;
+ for (Map.Entry<Integer, Boolean> entry : displayIdsToWallpaperCompatibility.entrySet()) {
+ final int displayId = entry.getKey();
+ final boolean compatibleWithWallpaper = entry.getValue();
final Display mockDisplay = mock(Display.class);
- mockDisplays[i] = mockDisplay;
+ mockDisplays[counter] = mockDisplay;
doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension();
doReturn(mockDisplay).when(mDisplayManager).getDisplay(eq(displayId));
doReturn(displayId).when(mockDisplay).getDisplayId();
doReturn(true).when(mockDisplay).hasAccess(anyInt());
- mService.addWallpaperCompatibleDisplayForTest(displayId);
+ doReturn(compatibleWithWallpaper).when(
+ mService.mWallpaperCropper).isWallpaperCompatibleForDisplay(eq(displayId),
+ any());
+ counter++;
}
doReturn(mockDisplays).when(mDisplayManager).getDisplays();
@@ -1295,6 +1329,4 @@
assertEquals(pfdContents, fileContents);
}
}
-
-
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java
index 8fc8c9f..6be9c6d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderPerfTest.java
@@ -48,6 +48,7 @@
import java.io.File;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
@@ -121,7 +122,7 @@
}
@Test
- public void getBatteryUsageStats_accumulated() {
+ public void getBatteryUsageStats_accumulated() throws IOException {
BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
.setMaxStatsAgeMs(0)
.includePowerStateData()
@@ -155,6 +156,8 @@
// Verify that all iterations produce the same result
assertThat(cpuConsumedPower).isEqualTo(expectedCpuPower);
}
+ stats.close();
+
state.resumeTiming();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
index 0e73329..978fd1a 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.annotation.SuppressLint;
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
import android.util.SparseArray;
@@ -280,6 +281,7 @@
.isEqualTo(new long[]{250, 300});
}
+ @SuppressLint("CheckResult")
private static long[] getDeviceStats(
AggregatedPowerStats stats, int powerComponentId,
int... states) {
@@ -290,6 +292,7 @@
return out;
}
+ @SuppressLint("CheckResult")
private static long[] getStateStats(
AggregatedPowerStats stats, int key, int... states) {
PowerComponentAggregatedPowerStats powerComponentStats =
@@ -299,6 +302,7 @@
return out;
}
+ @SuppressLint("CheckResult")
private static long[] getUidDeviceStats(
AggregatedPowerStats stats, int powerComponentId,
int uid, int... states) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
index 21e615f..58e9d1e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
import android.os.Handler;
@@ -166,6 +167,7 @@
return stats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY);
}
+ @SuppressLint("CheckResult")
private void assertPowerEstimate(
PowerComponentAggregatedPowerStats aggregatedStats,
int powerState, int screenState, double expectedPowerEstimate) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BasePowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BasePowerStatsProcessorTest.java
index cca6033..58784d7 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BasePowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BasePowerStatsProcessorTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.mock;
+import android.annotation.SuppressLint;
import android.os.BatteryConsumer;
import android.os.BatteryUsageStats;
import android.os.Process;
@@ -68,6 +69,7 @@
.setProcessorSupplier(() -> new BasePowerStatsProcessor(() -> 4000));
}
+ @SuppressLint("CheckResult")
@Test
public void processPowerStats() {
AggregatedPowerStats aggregatedPowerStats = prepareAggregatedPowerStats(true);
@@ -95,9 +97,11 @@
stats.getUidStats(uidStats, APP_UID1,
states(POWER_STATE_BATTERY, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
assertThat(statsLayout.getUidUsageDuration(uidStats)).isEqualTo(5000);
- stats.getUidStats(uidStats, APP_UID1,
+ boolean nonZero = stats.getUidStats(uidStats, APP_UID1,
states(POWER_STATE_BATTERY, SCREEN_STATE_OTHER, PROCESS_STATE_UNSPECIFIED));
- assertThat(statsLayout.getUidUsageDuration(uidStats)).isEqualTo(0);
+ if (nonZero) {
+ assertThat(statsLayout.getUidUsageDuration(uidStats)).isEqualTo(0);
+ }
stats.getUidStats(uidStats, APP_UID2,
states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
@@ -105,11 +109,14 @@
stats.getUidStats(uidStats, APP_UID2,
states(POWER_STATE_BATTERY, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
assertThat(statsLayout.getUidUsageDuration(uidStats)).isEqualTo(8500);
- stats.getUidStats(uidStats, APP_UID2,
+ nonZero = stats.getUidStats(uidStats, APP_UID2,
states(POWER_STATE_BATTERY, SCREEN_STATE_OTHER, PROCESS_STATE_UNSPECIFIED));
- assertThat(statsLayout.getUidUsageDuration(uidStats)).isEqualTo(0);
+ if (nonZero) {
+ assertThat(statsLayout.getUidUsageDuration(uidStats)).isEqualTo(0);
+ }
}
+ @SuppressLint("CheckResult")
@Test
public void fuelgaugeAvailable() {
AggregatedPowerStats aggregatedPowerStats = prepareAggregatedPowerStats(true);
@@ -138,6 +145,7 @@
assertThat(dischargeDuration).isWithin(5).of(6000);
}
+ @SuppressLint("CheckResult")
@Test
public void fuelgaugeUnavailable() {
AggregatedPowerStats aggregatedPowerStats = prepareAggregatedPowerStats(false);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
index 2ff7dde..e6e7f6e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
@@ -30,6 +30,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.annotation.SuppressLint;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.PersistableBundle;
@@ -74,6 +75,7 @@
}
}
+ @SuppressLint("CheckResult")
@Test
public void powerProfileModel() {
BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
@@ -138,12 +140,14 @@
assertThat(statsLayout.getUidPowerEstimate(uidStats))
.isWithin(PRECISION).of(expectedPower2);
- stats.getUidStats(uidStats, APP_UID2,
- states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
- assertThat(statsLayout.getUidPowerEstimate(uidStats))
- .isWithin(PRECISION).of(0);
+ if (stats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED))) {
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(0);
+ }
}
+ @SuppressLint("CheckResult")
@Test
public void energyConsumerModel() {
BinaryStatePowerStatsLayout
@@ -232,10 +236,11 @@
assertThat(statsLayout.getUidPowerEstimate(uidStats))
.isWithin(PRECISION).of(expectedPower2);
- stats.getUidStats(uidStats, APP_UID2,
- states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
- assertThat(statsLayout.getUidPowerEstimate(uidStats))
- .isWithin(PRECISION).of(0);
+ if (stats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED))) {
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(0);
+ }
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
index 6013186..6d7119d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
@@ -33,6 +33,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.UidTraffic;
@@ -161,6 +162,7 @@
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(true);
}
+ @SuppressLint("CheckResult")
@Test
public void powerProfileModel_mostlyDataTransfer() {
// No power monitoring hardware
@@ -262,6 +264,7 @@
.isWithin(PRECISION).of(expectedPower2 * 0.75);
}
+ @SuppressLint("CheckResult")
@Test
public void powerProfileModel_mostlyScan() {
// No power monitoring hardware
@@ -361,6 +364,7 @@
.isWithin(PRECISION).of(expectedPower2 * 0.75);
}
+ @SuppressLint("CheckResult")
@Test
public void consumedEnergyModel() {
when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
index 23642de..a959632 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
@@ -33,6 +33,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
@@ -117,6 +118,7 @@
mMonotonicClock = new MonotonicClock(0, mStatsRule.getMockClock());
}
+ @SuppressLint("CheckResult")
@Test
public void energyConsumerModel() {
when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
@@ -211,10 +213,11 @@
assertThat(statsLayout.getUidPowerEstimate(uidStats))
.isWithin(PRECISION).of(expectedPower2);
- stats.getUidStats(uidStats, APP_UID2,
- states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
- assertThat(statsLayout.getUidPowerEstimate(uidStats))
- .isWithin(PRECISION).of(0);
+ if (stats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED))) {
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(0);
+ }
}
private BatteryStats.HistoryItem buildHistoryItem(int timestamp, boolean stateOn,
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
index cb9d9b1..dcddf06 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
@@ -34,6 +34,7 @@
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.IntArray;
import android.util.LongArray;
import androidx.test.filters.SmallTest;
@@ -51,7 +52,6 @@
import org.junit.runner.RunWith;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -315,8 +315,12 @@
}
@Override
- void collectUids(Collection<Integer> uids) {
- uids.addAll(mUids);
+ IntArray getActiveUids() {
+ IntArray uids = new IntArray();
+ for (Integer uid : mUids) {
+ uids.add(uid);
+ }
+ return uids;
}
void verifyPowerEstimates() {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
index 42baba7..a421675 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
@@ -33,6 +33,7 @@
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.hardware.power.stats.EnergyConsumerAttribution;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
@@ -154,6 +155,7 @@
.isEqualTo(6000);
}
+ @SuppressLint("CheckResult")
@Test
public void processStats() throws Exception {
AggregatedPowerStats aggregatedPowerStats = createAggregatedPowerStats();
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
index c63267e..b4f2113 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
@@ -33,6 +33,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.location.GnssSignalQuality;
@@ -122,6 +123,7 @@
mHistoryItem.clear();
}
+ @SuppressLint("CheckResult")
@Test
public void powerProfileModel() {
// ODPM unsupported
@@ -206,12 +208,14 @@
assertThat(statsLayout.getUidPowerEstimate(uidStats))
.isWithin(PRECISION).of(0.51111);
- stats.getUidStats(uidStats, APP_UID2,
- states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
- assertThat(statsLayout.getUidPowerEstimate(uidStats))
- .isWithin(PRECISION).of(0);
+ if (stats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED))) {
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(0);
+ }
}
+ @SuppressLint("CheckResult")
@Test
public void initialStateGnssOn() {
// ODPM unsupported
@@ -285,12 +289,14 @@
assertThat(statsLayout.getUidPowerEstimate(uidStats))
.isWithin(PRECISION).of(0.51111);
- stats.getUidStats(uidStats, APP_UID2,
- states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
- assertThat(statsLayout.getUidPowerEstimate(uidStats))
- .isWithin(PRECISION).of(0);
+ if (stats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED))) {
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(0);
+ }
}
+ @SuppressLint("CheckResult")
@Test
public void energyConsumerModel() {
when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
@@ -386,10 +392,11 @@
assertThat(statsLayout.getUidPowerEstimate(uidStats))
.isWithin(PRECISION).of(expectedPower2);
- stats.getUidStats(uidStats, APP_UID2,
- states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
- assertThat(statsLayout.getUidPowerEstimate(uidStats))
- .isWithin(PRECISION).of(0);
+ if (stats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED))) {
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(0);
+ }
}
private BatteryStats.HistoryItem buildHistoryItemInitialStateGpsOn(long timestamp) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
index 6acd368..3dc4017 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
@@ -39,6 +39,7 @@
import static org.mockito.Mockito.when;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.power.stats.EnergyConsumerResult;
@@ -170,6 +171,7 @@
.thenAnswer(invocation -> invocation.getArgument(0));
}
+ @SuppressLint("CheckResult")
@Test
public void powerProfileModel() {
// No power monitoring hardware
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
index a232c0c..9abb06f 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertThrows;
+import android.annotation.SuppressLint;
import android.os.BatteryConsumer;
import androidx.test.filters.SmallTest;
@@ -124,6 +125,7 @@
assertThat(e.getMessage()).contains("40");
}
+ @SuppressLint("CheckResult")
@Test
public void multiStateStats_aggregation() {
MultiStateStats.Factory factory = makeFactory(true, true, false);
@@ -143,6 +145,8 @@
multiStateStats.increment(new long[]{200, 200}, 5000);
+ multiStateStats.increment(null, 6000); // No-op
+
long[] stats = new long[DIMENSION_COUNT];
multiStateStats.getStats(stats, new int[]{0, BatteryConsumer.PROCESS_STATE_FOREGROUND, 0});
// (400 - 100) * 0.5 + (600 - 400) * 0.5
@@ -157,9 +161,9 @@
// (400 - 100) * 0 + (600 - 400) * 0.5
assertThat(stats).isEqualTo(new long[]{100, 100});
- multiStateStats.getStats(stats, new int[]{1, BatteryConsumer.PROCESS_STATE_BACKGROUND, 0});
// Never been in this composite state
- assertThat(stats).isEqualTo(new long[]{0, 0});
+ assertThat(multiStateStats.getStats(stats,
+ new int[]{1, BatteryConsumer.PROCESS_STATE_BACKGROUND, 0})).isFalse();
}
@Test
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
index a20274f..2f742d7 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.power.stats.EnergyConsumerType;
@@ -159,6 +160,7 @@
mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem");
}
+ @SuppressLint("CheckResult")
@Test
public void copyEstimatesFromMobileRadioPowerStats() {
AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
index 1852165..31456a15 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
@@ -278,6 +279,7 @@
.of(expectedDozePowerEstimate);
}
+ @SuppressLint("CheckResult")
private void assertUidPowerEstimate(
PowerComponentAggregatedPowerStats aggregatedStats, int uid,
int powerState, int screenState, double expectedScreenPowerEstimate) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
index d972604..c2f01d1 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
@@ -33,6 +33,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.annotation.SuppressLint;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.input.InputSensorInfo;
@@ -91,6 +92,7 @@
List.of(sensor1, sensor2, sensor3));
}
+ @SuppressLint("CheckResult")
@Test
public void testPowerEstimation() {
PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java
index 8257d71..5ac7216 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java
@@ -31,6 +31,7 @@
import static org.mockito.Mockito.mock;
+import android.annotation.SuppressLint;
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
import android.os.Process;
@@ -123,6 +124,7 @@
return history;
}
+ @SuppressLint("CheckResult")
private void assertAggregatedPowerStats(AggregatedPowerStats aggregatedPowerStats) {
PowerComponentAggregatedPowerStats stats =
aggregatedPowerStats.getPowerComponentStats(POWER_COMPONENT_WAKELOCK);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
index bd92a84..e36056a 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
@@ -39,6 +39,7 @@
import static org.mockito.Mockito.when;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.power.stats.EnergyConsumerResult;
@@ -198,6 +199,7 @@
mBatteryStats = mStatsRule.getBatteryStats();
}
+ @SuppressLint("CheckResult")
@Test
public void powerProfileModel_powerController() {
when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
@@ -310,6 +312,7 @@
.isWithin(PRECISION).of(expectedPower2 * 0.75);
}
+ @SuppressLint("CheckResult")
@Test
public void consumedEnergyModel_powerController() {
when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
@@ -424,6 +427,7 @@
.isWithin(PRECISION).of(expectedPower2 * 0.75);
}
+ @SuppressLint("CheckResult")
@Test
public void powerProfileModel_noPowerController() {
when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(false);
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 834fea4..4531b39 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -199,6 +199,10 @@
<service android:name="com.android.server.job.MockBiasJobService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
+ <activity
+ android:name="android.app.Activity"
+ android:exported="false" />
+
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity"/>
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity2"/>
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity3"/>
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index 8dfd54f..42b84bd 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -46,12 +46,11 @@
import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_INPUT;
import static android.view.accessibility.AccessibilityNodeInfo.ROOT_NODE_ID;
-import static org.hamcrest.Matchers.hasItems;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.nullValue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -65,6 +64,7 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityService;
@@ -90,14 +90,20 @@
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.test.FakePermissionEnforcer;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.util.Pair;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import android.view.accessibility.IWindowSurfaceInfoCallback;
+import android.window.ScreenCapture;
import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
import com.android.server.accessibility.magnification.MagnificationProcessor;
@@ -105,6 +111,7 @@
import com.android.server.wm.WindowManagerInternal;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -121,6 +128,10 @@
* Tests for the AbstractAccessibilityServiceConnection
*/
public class AbstractAccessibilityServiceConnectionTest {
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private static final ComponentName COMPONENT_NAME = new ComponentName(
"com.android.server.accessibility", ".AbstractAccessibilityServiceConnectionTest");
private static final String PACKAGE_NAME1 = "com.android.server.accessibility1";
@@ -264,7 +275,7 @@
@Test
public void getCapabilities() {
- assertThat(mServiceConnection.getCapabilities(), is(A11Y_SERVICE_CAPABILITY));
+ assertThat(mServiceConnection.getCapabilities()).isEqualTo(A11Y_SERVICE_CAPABILITY);
}
@Test
@@ -329,7 +340,7 @@
0, null, 0);
mServiceConnection.setServiceInfo(serviceInfo);
- assertThat(mServiceConnection.canReceiveEventsLocked(), is(true));
+ assertThat(mServiceConnection.canReceiveEventsLocked()).isTrue();
}
@Test
@@ -348,9 +359,11 @@
mServiceConnection.getWindows();
assertEquals(2, allWindows.size());
- assertThat(allWindows.get(Display.DEFAULT_DISPLAY), is(mA11yWindowInfos));
+ assertThat(allWindows.get(Display.DEFAULT_DISPLAY))
+ .containsExactlyElementsIn(mA11yWindowInfos);
assertEquals(2, allWindows.get(Display.DEFAULT_DISPLAY).size());
- assertThat(allWindows.get(SECONDARY_DISPLAY_ID), is(mA11yWindowInfosOnSecondDisplay));
+ assertThat(allWindows.get(SECONDARY_DISPLAY_ID))
+ .containsExactlyElementsIn(mA11yWindowInfosOnSecondDisplay);
assertEquals(1, allWindows.get(SECONDARY_DISPLAY_ID).size());
}
@@ -358,12 +371,12 @@
public void getWindows_returnNull() {
// no canRetrieveWindows, should return null
when(mMockSecurityPolicy.canRetrieveWindowsLocked(mServiceConnection)).thenReturn(false);
- assertThat(mServiceConnection.getWindows(), is(nullValue()));
+ assertThat(mServiceConnection.getWindows()).isNull();
// no checkAccessibilityAccess, should return null
when(mMockSecurityPolicy.canRetrieveWindowsLocked(mServiceConnection)).thenReturn(true);
when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(false);
- assertThat(mServiceConnection.getWindows(), is(nullValue()));
+ assertThat(mServiceConnection.getWindows()).isNull();
}
@Test
@@ -378,19 +391,19 @@
@Test
public void getWindow() {
- assertThat(mServiceConnection.getWindow(WINDOWID), is(mA11yWindowInfos.get(0)));
+ assertThat(mServiceConnection.getWindow(WINDOWID)).isEqualTo(mA11yWindowInfos.get(0));
}
@Test
public void getWindow_returnNull() {
// no canRetrieveWindows, should return null
when(mMockSecurityPolicy.canRetrieveWindowsLocked(mServiceConnection)).thenReturn(false);
- assertThat(mServiceConnection.getWindow(WINDOWID), is(nullValue()));
+ assertThat(mServiceConnection.getWindow(WINDOWID)).isNull();
// no checkAccessibilityAccess, should return null
when(mMockSecurityPolicy.canRetrieveWindowsLocked(mServiceConnection)).thenReturn(true);
when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(false);
- assertThat(mServiceConnection.getWindow(WINDOWID), is(nullValue()));
+ assertThat(mServiceConnection.getWindow(WINDOWID)).isNull();
}
@Test
@@ -405,8 +418,8 @@
@Test
public void getWindow_onNonDefaultDisplay() {
- assertThat(mServiceConnection.getWindow(WINDOWID_ONSECONDDISPLAY),
- is(mA11yWindowInfosOnSecondDisplay.get(0)));
+ assertThat(mServiceConnection.getWindow(WINDOWID_ONSECONDDISPLAY))
+ .isEqualTo(mA11yWindowInfosOnSecondDisplay.get(0));
}
@Test
@@ -415,9 +428,9 @@
when(mMockSecurityPolicy.canGetAccessibilityNodeInfoLocked(
USER_ID, mServiceConnection, WINDOWID)).thenReturn(false);
for (int i = 0; i < mFindA11yNodesFunctions.length; i++) {
- assertThat(mFindA11yNodesFunctions[i].call(), is(nullValue()));
+ assertThat(mFindA11yNodesFunctions[i].call()).isNull();
}
- assertThat(mPerformA11yAction.call(), is(false));
+ assertThat(mPerformA11yAction.call()).isFalse();
verifyNoMoreInteractions(mMockIA11yInteractionConnection);
verify(mMockSecurityPolicy, never()).computeValidReportedPackages(any(), anyInt());
@@ -428,9 +441,9 @@
throws Exception {
when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(false);
for (int i = 0; i < mFindA11yNodesFunctions.length; i++) {
- assertThat(mFindA11yNodesFunctions[i].call(), is(nullValue()));
+ assertThat(mFindA11yNodesFunctions[i].call()).isNull();
}
- assertThat(mPerformA11yAction.call(), is(false));
+ assertThat(mPerformA11yAction.call()).isFalse();
verifyNoMoreInteractions(mMockIA11yInteractionConnection);
verify(mMockSecurityPolicy, never()).computeValidReportedPackages(any(), anyInt());
@@ -441,9 +454,9 @@
throws Exception {
when(mMockA11yWindowManager.getConnectionLocked(USER_ID, WINDOWID)).thenReturn(null);
for (int i = 0; i < mFindA11yNodesFunctions.length; i++) {
- assertThat(mFindA11yNodesFunctions[i].call(), is(nullValue()));
+ assertThat(mFindA11yNodesFunctions[i].call()).isNull();
}
- assertThat(mPerformA11yAction.call(), is(false));
+ assertThat(mPerformA11yAction.call()).isFalse();
verifyNoMoreInteractions(mMockIA11yInteractionConnection);
verify(mMockSecurityPolicy, never()).computeValidReportedPackages(any(), anyInt());
@@ -562,7 +575,7 @@
when(mMockFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable())
.thenReturn(true);
final boolean result = mServiceConnection.isFingerprintGestureDetectionAvailable();
- assertThat(result, is(true));
+ assertThat(result).isTrue();
}
@Test
@@ -573,14 +586,14 @@
// Return false if device does not support fingerprint
when(mMockPackageManager.hasSystemFeature(FEATURE_FINGERPRINT)).thenReturn(false);
boolean result = mServiceConnection.isFingerprintGestureDetectionAvailable();
- assertThat(result, is(false));
+ assertThat(result).isFalse();
// Return false if service does not have flag
when(mMockPackageManager.hasSystemFeature(FEATURE_FINGERPRINT)).thenReturn(true);
mSpyServiceInfo.flags = A11Y_SERVICE_FLAG & ~FLAG_REQUEST_FINGERPRINT_GESTURES;
mServiceConnection.setServiceInfo(mSpyServiceInfo);
result = mServiceConnection.isFingerprintGestureDetectionAvailable();
- assertThat(result, is(false));
+ assertThat(result).isFalse();
}
@Test
@@ -590,7 +603,7 @@
when(mMockMagnificationProcessor.getScale(displayId)).thenReturn(scale);
final float result = mServiceConnection.getMagnificationScale(displayId);
- assertThat(result, is(scale));
+ assertThat(result).isEqualTo(scale);
}
@Test
@@ -601,7 +614,7 @@
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final float result = mServiceConnection.getMagnificationScale(displayId);
- assertThat(result, is(1.0f));
+ assertThat(result).isEqualTo(1.0f);
}
@Test
@@ -616,7 +629,7 @@
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final Region result = mServiceConnection.getMagnificationRegion(displayId);
- assertThat(result.isEmpty(), is(true));
+ assertWithMessage("Non-empty region: " + result).that(result.isEmpty()).isTrue();
}
@Test
@@ -642,7 +655,7 @@
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final float result = mServiceConnection.getMagnificationCenterX(displayId);
- assertThat(result, is(0.0f));
+ assertThat(result).isEqualTo(0.0f);
}
@Test
@@ -654,7 +667,7 @@
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final float result = mServiceConnection.getMagnificationCenterY(displayId);
- assertThat(result, is(0.0f));
+ assertThat(result).isEqualTo(0.0f);
}
@Test
@@ -664,7 +677,7 @@
true);
final boolean result = mServiceConnection.resetMagnification(displayId, true);
- assertThat(result, is(true));
+ assertThat(result).isTrue();
}
@Test
@@ -675,7 +688,7 @@
when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
final boolean result = mServiceConnection.resetMagnification(displayId, true);
- assertThat(result, is(false));
+ assertThat(result).isFalse();
}
@Test
@@ -686,7 +699,7 @@
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final boolean result = mServiceConnection.resetMagnification(displayId, true);
- assertThat(result, is(false));
+ assertThat(result).isFalse();
}
@Test
@@ -765,6 +778,134 @@
== bundle.getInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS)));
}
+ private void setPreinstalledA11yTool(boolean isPreinstalledA11yTool) {
+ when(mSpyServiceInfo.getResolveInfo().serviceInfo.applicationInfo.isSystemApp())
+ .thenReturn(isPreinstalledA11yTool);
+ when(mSpyServiceInfo.isAccessibilityTool()).thenReturn(isPreinstalledA11yTool);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ALLOW_SECURE_SCREENSHOTS)
+ public void takeScreenshot_standardService_cannotCaptureSecureLayers() {
+ setPreinstalledA11yTool(false);
+
+ takeScreenshotOfDisplay();
+
+ final ArgumentCaptor<ScreenCapture.CaptureArgs> displayArgsCaptor =
+ ArgumentCaptor.forClass(ScreenCapture.CaptureArgs.class);
+ verify(mMockWindowManagerInternal).captureDisplay(
+ eq(Display.DEFAULT_DISPLAY), displayArgsCaptor.capture(), any());
+ assertThat(displayArgsCaptor.getValue().mCaptureSecureLayers).isFalse();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ALLOW_SECURE_SCREENSHOTS)
+ public void takeScreenshot_preinstalledA11yTool_canCaptureSecureLayers() {
+ setPreinstalledA11yTool(true);
+
+ takeScreenshotOfDisplay();
+
+ final ArgumentCaptor<ScreenCapture.CaptureArgs> displayArgsCaptor =
+ ArgumentCaptor.forClass(ScreenCapture.CaptureArgs.class);
+ verify(mMockWindowManagerInternal).captureDisplay(
+ anyInt(), displayArgsCaptor.capture(), any());
+ assertThat(displayArgsCaptor.getValue().mCaptureSecureLayers).isTrue();
+ }
+
+ private void takeScreenshotOfDisplay() {
+ when(mMockSecurityPolicy.canTakeScreenshotLocked(mServiceConnection)).thenReturn(true);
+ when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(true);
+
+ final DisplayManager displayManager = new DisplayManager(mMockContext);
+ when(mMockContext.getSystemService(Context.DISPLAY_SERVICE)).thenReturn(displayManager);
+
+ mServiceConnection.takeScreenshot(Display.DEFAULT_DISPLAY,
+ new RemoteCallback(mMockListener));
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ALLOW_SECURE_SCREENSHOTS)
+ public void takeScreenshotOfWindow_standardWindow_standardService_cannotCaptureSecureLayers()
+ throws Exception {
+ setPreinstalledA11yTool(false);
+
+ takeScreenshotOfWindow(/*windowFlags=*/0);
+
+ // Screenshot was allowed
+ final ArgumentCaptor<ScreenCapture.LayerCaptureArgs> layerArgsCaptor =
+ ArgumentCaptor.forClass(ScreenCapture.LayerCaptureArgs.class);
+ verify(mMockSystemSupport).performScreenCapture(layerArgsCaptor.capture(), any());
+ // ...without secure layers included
+ assertThat(layerArgsCaptor.getValue().mCaptureSecureLayers).isFalse();
+ // No error sent to callback
+ verifyZeroInteractions(mMockCallback);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ALLOW_SECURE_SCREENSHOTS)
+ public void takeScreenshotOfWindow_standardWindow_preinstalledA11yTool_canCaptureSecureLayers()
+ throws Exception {
+ setPreinstalledA11yTool(true);
+
+ takeScreenshotOfWindow(/*windowFlags=*/0);
+
+ // Screenshot was allowed
+ final ArgumentCaptor<ScreenCapture.LayerCaptureArgs> layerArgsCaptor =
+ ArgumentCaptor.forClass(ScreenCapture.LayerCaptureArgs.class);
+ verify(mMockSystemSupport).performScreenCapture(layerArgsCaptor.capture(), any());
+ // ...with secure layers included
+ assertThat(layerArgsCaptor.getValue().mCaptureSecureLayers).isTrue();
+ // No error sent to callback
+ verifyZeroInteractions(mMockCallback);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ALLOW_SECURE_SCREENSHOTS)
+ public void takeScreenshotOfWindow_secureWindow_standardService_sendsCallbackError()
+ throws Exception {
+ setPreinstalledA11yTool(false);
+
+ takeScreenshotOfWindow(WindowManager.LayoutParams.FLAG_SECURE);
+
+ // Screenshot was not allowed
+ verify(mMockSystemSupport, never()).performScreenCapture(any(), any());
+ // Error sent to callback
+ verify(mMockCallback).sendTakeScreenshotOfWindowError(
+ AccessibilityService.ERROR_TAKE_SCREENSHOT_SECURE_WINDOW, INTERACTION_ID);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ALLOW_SECURE_SCREENSHOTS)
+ public void takeScreenshotOfWindow_secureWindow_preinstalledA11yTool_canCaptureSecureLayers()
+ throws Exception {
+ setPreinstalledA11yTool(true);
+
+ takeScreenshotOfWindow(WindowManager.LayoutParams.FLAG_SECURE);
+
+ // Screenshot was allowed
+ final ArgumentCaptor<ScreenCapture.LayerCaptureArgs> layerArgsCaptor =
+ ArgumentCaptor.forClass(ScreenCapture.LayerCaptureArgs.class);
+ verify(mMockSystemSupport).performScreenCapture(layerArgsCaptor.capture(), any());
+ // ...with secure layers included
+ assertThat(layerArgsCaptor.getValue().mCaptureSecureLayers).isTrue();
+ // No error sent to callback
+ verifyZeroInteractions(mMockCallback);
+ }
+
+ private void takeScreenshotOfWindow(int windowFlags) throws Exception {
+ when(mMockSecurityPolicy.canTakeScreenshotLocked(mServiceConnection)).thenReturn(true);
+ when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(true);
+
+ mServiceConnection.takeScreenshotOfWindow(
+ WINDOWID, INTERACTION_ID, /*listener=*/null, mMockCallback);
+ final ArgumentCaptor<IWindowSurfaceInfoCallback> windowSurfaceCallbackCaptor =
+ ArgumentCaptor.forClass(IWindowSurfaceInfoCallback.class);
+ verify(mMockIA11yInteractionConnection).getWindowSurfaceInfo(
+ windowSurfaceCallbackCaptor.capture());
+ windowSurfaceCallbackCaptor.getValue().provideWindowSurfaceInfo(
+ windowFlags, /*appUid=*/0, new SurfaceControl());
+ }
+
private void updateServiceInfo(AccessibilityServiceInfo serviceInfo, int eventType,
int feedbackType, int flags, String[] packageNames, int notificationTimeout) {
serviceInfo.eventTypes = eventType;
@@ -837,8 +978,8 @@
ArgumentCaptor.forClass(AccessibilityNodeInfo.class);
verify(mMockCallback).setFindAccessibilityNodeInfoResult(captor.capture(),
eq(INTERACTION_ID));
- assertThat(captor.getValue().getActionList(),
- hasItems(AccessibilityAction.ACTION_CLICK, AccessibilityAction.ACTION_EXPAND));
+ assertThat(captor.getValue().getActionList()).containsAtLeast(
+ AccessibilityAction.ACTION_CLICK, AccessibilityAction.ACTION_EXPAND);
}
private static class TestAccessibilityServiceConnection
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
index 7f60caa..0745c68 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.platform.test.annotations.DisableFlags;
@@ -400,6 +401,46 @@
.isNotEqualTo(initialScheduledTime);
}
+ @Test
+ @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+ public void pauseButton_flagOn_clickNotTriggeredWhenPaused() {
+ injectFakeMouseActionHoverMoveEvent();
+
+ // Pause autoclick.
+ AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class);
+ when(mockAutoclickTypePanel.isPaused()).thenReturn(true);
+ mController.mAutoclickTypePanel = mockAutoclickTypePanel;
+
+ // Send hover move event.
+ MotionEvent hoverMove = MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 100,
+ /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+ /* x= */ 30f,
+ /* y= */ 0f,
+ /* metaState= */ 0);
+ hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+ mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+
+ // Verify there is not a pending click.
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isEqualTo(-1);
+
+ // Resume autoclick.
+ when(mockAutoclickTypePanel.isPaused()).thenReturn(false);
+
+ // Send initial move event again. Because this is the first recorded move, a click won't be
+ // scheduled.
+ injectFakeMouseActionHoverMoveEvent();
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isEqualTo(-1);
+
+ // Send move again to trigger click and verify there is now a pending click.
+ mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isNotEqualTo(-1);
+ }
+
private void injectFakeMouseActionHoverMoveEvent() {
MotionEvent event = getFakeMotionHoverMoveEvent();
event.setSource(InputDevice.SOURCE_MOUSE);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
index 00cc726..c60c4b6 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
@@ -21,6 +21,9 @@
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_SCROLL;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AutoclickType;
+import static com.android.server.accessibility.autoclick.AutoclickTypePanel.CORNER_BOTTOM_LEFT;
+import static com.android.server.accessibility.autoclick.AutoclickTypePanel.CORNER_BOTTOM_RIGHT;
+import static com.android.server.accessibility.autoclick.AutoclickTypePanel.CORNER_TOP_RIGHT;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.ClickPanelControllerInterface;
import static com.google.common.truth.Truth.assertThat;
@@ -30,6 +33,8 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
+import android.view.Gravity;
+import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
@@ -63,8 +68,11 @@
private LinearLayout mDoubleClickButton;
private LinearLayout mDragButton;
private LinearLayout mScrollButton;
+ private LinearLayout mPauseButton;
+ private LinearLayout mPositionButton;
private @AutoclickType int mActiveClickType = AUTOCLICK_TYPE_LEFT_CLICK;
+ private boolean mPaused;
private final ClickPanelControllerInterface clickPanelController =
new ClickPanelControllerInterface() {
@@ -74,7 +82,9 @@
}
@Override
- public void toggleAutoclickPause() {}
+ public void toggleAutoclickPause(boolean paused) {
+ mPaused = paused;
+ }
};
@Before
@@ -91,6 +101,8 @@
contentView.findViewById(R.id.accessibility_autoclick_double_click_layout);
mScrollButton = contentView.findViewById(R.id.accessibility_autoclick_scroll_layout);
mDragButton = contentView.findViewById(R.id.accessibility_autoclick_drag_layout);
+ mPauseButton = contentView.findViewById(R.id.accessibility_autoclick_pause_layout);
+ mPositionButton = contentView.findViewById(R.id.accessibility_autoclick_position_layout);
}
@Test
@@ -106,6 +118,7 @@
assertThat(mDoubleClickButton.getVisibility()).isEqualTo(View.GONE);
assertThat(mDragButton.getVisibility()).isEqualTo(View.GONE);
assertThat(mScrollButton.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mPauseButton.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
@@ -124,6 +137,9 @@
assertThat(mDoubleClickButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mDragButton.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mScrollButton.getVisibility()).isEqualTo(View.VISIBLE);
+
+ // Pause button is always visible.
+ assertThat(mPauseButton.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
@@ -142,6 +158,9 @@
assertThat(mLeftClickButton.getVisibility()).isEqualTo(View.GONE);
assertThat(mDoubleClickButton.getVisibility()).isEqualTo(View.GONE);
assertThat(mDragButton.getVisibility()).isEqualTo(View.GONE);
+
+ // Pause button is always visible.
+ assertThat(mPauseButton.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
@@ -166,9 +185,149 @@
assertThat(mActiveClickType).isEqualTo(AUTOCLICK_TYPE_SCROLL);
}
+ @Test
+ public void moveToNextCorner_positionButton_rotatesThroughAllPositions() {
+ // Define all positions in sequence
+ int[][] expectedPositions = {
+ {0, Gravity.END | Gravity.BOTTOM, /*x=*/ 15, /*y=*/ 90},
+ {1, Gravity.START | Gravity.BOTTOM, /*x=*/ 15, /*y=*/ 90},
+ {2, Gravity.START | Gravity.TOP, /*x=*/ 15, /*y=*/ 30},
+ {3, Gravity.END | Gravity.TOP, /*x=*/ 15, /*y=*/ 30},
+ {0, Gravity.END | Gravity.BOTTOM, /*x=*/ 15, /*y=*/ 90}
+ };
+
+ // Check initial position
+ verifyPanelPosition(expectedPositions[0]);
+
+ // Move through all corners.
+ for (int i = 1; i < expectedPositions.length; i++) {
+ mPositionButton.callOnClick();
+ verifyPanelPosition(expectedPositions[i]);
+ }
+ }
+
+ @Test
+ public void pauseButton_onClick() {
+ mPauseButton.callOnClick();
+ assertThat(mPaused).isTrue();
+ assertThat(mAutoclickTypePanel.isPaused()).isTrue();
+
+ mPauseButton.callOnClick();
+ assertThat(mPaused).isFalse();
+ assertThat(mAutoclickTypePanel.isPaused()).isFalse();
+ }
+
+ @Test
+ public void onTouch_dragMove_updatesPosition() {
+ View contentView = mAutoclickTypePanel.getContentViewForTesting();
+ WindowManager.LayoutParams params = mAutoclickTypePanel.getLayoutParamsForTesting();
+ int[] panelLocation = new int[2];
+ contentView.getLocationOnScreen(panelLocation);
+
+ // Define movement delta for both x and y directions.
+ int delta = 15;
+
+ // Dispatch initial down event.
+ float touchX = panelLocation[0] + 10;
+ float touchY = panelLocation[1] + 10;
+ MotionEvent downEvent = MotionEvent.obtain(
+ 0, 0,
+ MotionEvent.ACTION_DOWN, touchX, touchY, 0);
+ contentView.dispatchTouchEvent(downEvent);
+
+ // Create move event with delta, move from (x, y) to (x + delta, y + delta)
+ MotionEvent moveEvent = MotionEvent.obtain(
+ 0, 0,
+ MotionEvent.ACTION_MOVE, touchX + delta, touchY + delta, 0);
+ contentView.dispatchTouchEvent(moveEvent);
+
+ // Verify position update.
+ assertThat(mAutoclickTypePanel.getIsDraggingForTesting()).isTrue();
+ assertThat(params.gravity).isEqualTo(Gravity.LEFT | Gravity.TOP);
+ assertThat(params.x).isEqualTo(panelLocation[0] + delta);
+ assertThat(params.y).isEqualTo(panelLocation[1] + delta);
+ }
+
+ @Test
+ public void dragAndEndAtRight_snapsToRightSide() {
+ View contentView = mAutoclickTypePanel.getContentViewForTesting();
+ WindowManager.LayoutParams params = mAutoclickTypePanel.getLayoutParamsForTesting();
+ int[] panelLocation = new int[2];
+ contentView.getLocationOnScreen(panelLocation);
+
+ int screenWidth = mTestableContext.getResources().getDisplayMetrics().widthPixels;
+
+ // Verify initial corner is bottom-right.
+ assertThat(mAutoclickTypePanel.getCurrentCornerIndexForTesting())
+ .isEqualTo(CORNER_BOTTOM_RIGHT);
+
+ dispatchDragSequence(contentView,
+ /* startX =*/ panelLocation[0] + 10, /* startY =*/ panelLocation[1] + 10,
+ /* endX =*/ (float) (screenWidth * 3) / 4, /* endY =*/ panelLocation[1] + 10);
+
+ // Verify snapping to the right.
+ assertThat(params.gravity).isEqualTo(Gravity.END | Gravity.TOP);
+ assertThat(mAutoclickTypePanel.getCurrentCornerIndexForTesting())
+ .isEqualTo(CORNER_TOP_RIGHT);
+ }
+
+ @Test
+ public void dragAndEndAtLeft_snapsToLeftSide() {
+ View contentView = mAutoclickTypePanel.getContentViewForTesting();
+ WindowManager.LayoutParams params = mAutoclickTypePanel.getLayoutParamsForTesting();
+ int[] panelLocation = new int[2];
+ contentView.getLocationOnScreen(panelLocation);
+
+ int screenWidth = mTestableContext.getResources().getDisplayMetrics().widthPixels;
+
+ // Verify initial corner is bottom-right.
+ assertThat(mAutoclickTypePanel.getCurrentCornerIndexForTesting())
+ .isEqualTo(CORNER_BOTTOM_RIGHT);
+
+ dispatchDragSequence(contentView,
+ /* startX =*/ panelLocation[0] + 10, /* startY =*/ panelLocation[1] + 10,
+ /* endX =*/ (float) screenWidth / 4, /* endY =*/ panelLocation[1] + 10);
+
+ // Verify snapping to the left.
+ assertThat(params.gravity).isEqualTo(Gravity.START | Gravity.TOP);
+ assertThat(mAutoclickTypePanel.getCurrentCornerIndexForTesting())
+ .isEqualTo(CORNER_BOTTOM_LEFT);
+ }
+
+ // Helper method to handle drag event sequences
+ private void dispatchDragSequence(View view, float startX, float startY, float endX,
+ float endY) {
+ // Down event
+ MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, startX, startY,
+ 0);
+ view.dispatchTouchEvent(downEvent);
+
+ // Move event
+ MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, endX, endY, 0);
+ view.dispatchTouchEvent(moveEvent);
+
+ // Up event
+ MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, endX, endY, 0);
+ view.dispatchTouchEvent(upEvent);
+
+ // Clean up
+ downEvent.recycle();
+ moveEvent.recycle();
+ upEvent.recycle();
+ }
+
private void verifyButtonHasSelectedStyle(@NonNull LinearLayout button) {
GradientDrawable gradientDrawable = (GradientDrawable) button.getBackground();
assertThat(gradientDrawable.getColor().getDefaultColor())
.isEqualTo(mTestableContext.getColor(R.color.materialColorPrimary));
}
+
+ private void verifyPanelPosition(int[] expectedPosition) {
+ WindowManager.LayoutParams params = mAutoclickTypePanel.getLayoutParamsForTesting();
+ assertThat(mAutoclickTypePanel.getCurrentCornerIndexForTesting()).isEqualTo(
+ expectedPosition[0]);
+ assertThat(params.gravity).isEqualTo(expectedPosition[1]);
+ assertThat(params.x).isEqualTo(expectedPosition[2]);
+ assertThat(params.y).isEqualTo(expectedPosition[3]);
+ }
}
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 9f5dd93..5c126d1 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
@@ -311,8 +311,7 @@
mMockFullScreenMagnificationVibrationHelper,
mMockMagnificationLogger,
ViewConfiguration.get(mContext),
- mMockOneFingerPanningSettingsProvider,
- new MouseEventHandler(mFullScreenMagnificationController));
+ mMockOneFingerPanningSettingsProvider);
// OverscrollHandler is only supported on watches.
// @See config_enable_a11y_fullscreen_magnification_overscroll_handler
if (isWatch()) {
@@ -482,8 +481,8 @@
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
public void testDisablingTripleTap_removesInputLag() {
- mMgh = newInstance(/* detectSingleFingerTripleTap */ false,
- /* detectTwoFingerTripleTap */ true, /* detectShortcut */ true);
+ mMgh = newInstance(/* detectSingleFingerTripleTap= */ false,
+ /* detectTwoFingerTripleTap= */ true, /* detectShortcutTrigger= */ true);
goFromStateIdleTo(STATE_IDLE);
allowEventDelegation();
tap();
@@ -494,8 +493,8 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
public void testDisablingSingleFingerTripleTapAndTwoFingerTripleTap_removesInputLag() {
- mMgh = newInstance(/* detectSingleFingerTripleTap */ false,
- /* detectTwoFingerTripleTap */ false, /* detectShortcut */ true);
+ mMgh = newInstance(/* detectSingleFingerTripleTap= */ false,
+ /* detectTwoFingerTripleTap= */ false, /* detectShortcutTrigger= */ true);
goFromStateIdleTo(STATE_IDLE);
allowEventDelegation();
tap();
@@ -1420,12 +1419,6 @@
}
@Test
- @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
- public void testMouseMoveEventsDoNotMoveMagnifierViewport() {
- runMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_MOUSE);
- }
-
- @Test
public void testStylusMoveEventsDoNotMoveMagnifierViewport() {
runMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_STYLUS);
}
@@ -1441,7 +1434,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 5.6f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
+ DISPLAY_0, scale, centerX, centerY, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
@@ -1474,55 +1467,36 @@
}
@Test
- @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
- public void testMouseHoverMoveEventsDoNotMoveMagnifierViewport() {
- runHoverMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_MOUSE);
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
- public void testStylusHoverMoveEventsDoNotMoveMagnifierViewport() {
- runHoverMoveEventsDoNotMoveMagnifierViewport(InputDevice.SOURCE_STYLUS);
- }
-
- @Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void testMouseHoverMoveEventsMoveMagnifierViewport() {
runHoverMovesViewportTest(InputDevice.SOURCE_MOUSE);
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void testStylusHoverMoveEventsMoveMagnifierViewport() {
runHoverMovesViewportTest(InputDevice.SOURCE_STYLUS);
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void testMouseDownEventsDoNotMoveMagnifierViewport() {
runDownDoesNotMoveViewportTest(InputDevice.SOURCE_MOUSE);
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void testStylusDownEventsDoNotMoveMagnifierViewport() {
runDownDoesNotMoveViewportTest(InputDevice.SOURCE_STYLUS);
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void testMouseUpEventsDoNotMoveMagnifierViewport() {
runUpDoesNotMoveViewportTest(InputDevice.SOURCE_MOUSE);
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void testStylusUpEventsDoNotMoveMagnifierViewport() {
runUpDoesNotMoveViewportTest(InputDevice.SOURCE_STYLUS);
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void testMouseMoveEventsMoveMagnifierViewport() {
final EventCaptor eventCaptor = new EventCaptor();
mMgh.setNext(eventCaptor);
@@ -1533,7 +1507,7 @@
(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, true, /* animate= */ false, 1);
+ DISPLAY_0, scale, centerX, centerY, true, /* animate= */ false, 1);
MotionEvent event = mouseEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, InputDevice.SOURCE_MOUSE);
fastForward(20);
@@ -1574,7 +1548,7 @@
(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, true, /* animate= */ false, 1);
+ DISPLAY_0, scale, centerX, centerY, true, /* animate= */ false, 1);
// HOVER_MOVE should change magnifier viewport.
MotionEvent event = motionEvent(centerX + 20, centerY, ACTION_HOVER_MOVE);
@@ -1618,7 +1592,7 @@
(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, true, /* animate= */ false, 1);
+ DISPLAY_0, scale, centerX, centerY, true, /* animate= */ false, 1);
MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, source);
fastForward(20);
@@ -1652,7 +1626,7 @@
(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, true, /* animate= */ false, 1);
+ DISPLAY_0, scale, centerX, centerY, true, /* animate= */ false, 1);
MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, source);
fastForward(20);
@@ -1688,7 +1662,7 @@
(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, true, /* animate= */ false, 1);
+ DISPLAY_0, scale, centerX, centerY, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
@@ -1725,7 +1699,7 @@
(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, true, /* animate= */ false, 1);
+ DISPLAY_0, scale, centerX, centerY, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java
index 45c157d..203e655 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java
@@ -21,15 +21,11 @@
import static android.view.MotionEvent.ACTION_HOVER_MOVE;
import static android.view.MotionEvent.ACTION_UP;
-import static junit.framework.Assert.assertFalse;
-
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.testng.AssertJUnit.assertTrue;
import android.annotation.NonNull;
-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;
@@ -39,7 +35,6 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.server.accessibility.AccessibilityTraceManager;
-import com.android.server.accessibility.Flags;
import org.junit.Before;
import org.junit.Rule;
@@ -93,7 +88,6 @@
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void onMotionEvent_isFromMouse_handleMouseOrStylusEvent() {
final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
@@ -108,7 +102,6 @@
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
public void onMotionEvent_isFromStylus_handleMouseOrStylusEvent() {
final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
stylusEvent.setSource(InputDevice.SOURCE_STYLUS);
@@ -123,36 +116,6 @@
}
@Test
- @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
- public void onMotionEvent_isFromMouse_handleMouseOrStylusEventNotCalled() {
- final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
- mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
-
- mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0);
-
- try {
- assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled);
- } finally {
- mouseEvent.recycle();
- }
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE_BUGFIX)
- public void onMotionEvent_isFromStylus_handleMouseOrStylusEventNotCalled() {
- final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
- stylusEvent.setSource(InputDevice.SOURCE_STYLUS);
-
- mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0);
-
- try {
- assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled);
- } finally {
- stylusEvent.recycle();
- }
- }
-
- @Test
public void onMotionEvent_downEvent_handleInteractionStart() {
final MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0);
downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index e0023e5..30aa8ce 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1768,7 +1768,6 @@
}
@Test
- @Ignore // b/396073342
public void testCertificateDisclosure() throws Exception {
final int userId = CALLER_USER_HANDLE;
final UserHandle user = UserHandle.of(userId);
@@ -4613,7 +4612,6 @@
}
@Test
- @Ignore // b/396073342
public void testGetLastBugReportRequestTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4661,7 +4659,6 @@
}
@Test
- @Ignore // b/396073342
public void testGetLastNetworkLogRetrievalTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -6444,7 +6441,6 @@
}
@Test
- @Ignore // b/396073342
public void testGetOwnerInstalledCaCertsForDeviceOwner() throws Exception {
mServiceContext.packageName = mRealTestContext.getPackageName();
mServiceContext.applicationInfo = new ApplicationInfo();
@@ -6456,7 +6452,6 @@
}
@Test
- @Ignore // b/396073342
public void testGetOwnerInstalledCaCertsForProfileOwner() throws Exception {
mServiceContext.packageName = mRealTestContext.getPackageName();
mServiceContext.applicationInfo = new ApplicationInfo();
@@ -6469,7 +6464,6 @@
}
@Test
- @Ignore // b/396073342
public void testGetOwnerInstalledCaCertsForDelegate() throws Exception {
mServiceContext.packageName = mRealTestContext.getPackageName();
mServiceContext.applicationInfo = new ApplicationInfo();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index e5fac7a..00b0c55 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -263,6 +263,11 @@
}
@Override
+ public Context getApplicationContext() {
+ return this;
+ }
+
+ @Override
public PackageManager getPackageManager() {
return mMockSystemServices.packageManager;
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
index cf2c15c..b2d48a7 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
@@ -16,6 +16,7 @@
package com.android.server.hdmi;
+import static android.content.pm.PackageManager.FEATURE_HDMI_CEC;
import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
import static com.android.server.hdmi.HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP;
@@ -25,6 +26,7 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -122,6 +124,9 @@
@Before
public void setUp() throws RemoteException {
+ assumeTrue("Test requires FEATURE_HDMI_CEC",
+ InstrumentationRegistry.getTargetContext().getPackageManager()
+ .hasSystemFeature(FEATURE_HDMI_CEC));
MockitoAnnotations.initMocks(this);
mContextSpy = spy(new ContextWrapper(
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index 87c9db2..acbce36 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -354,14 +354,20 @@
@After
public void tearDown_baseServices() throws Exception {
- mStorage.closeDatabase();
+ if (mStorage != null) {
+ mStorage.closeDatabase();
+ }
File db = InstrumentationRegistry.getContext().getDatabasePath("locksettings.db");
assertTrue(!db.exists() || db.delete());
- File storageDir = mStorage.mStorageDir;
- assertTrue(FileUtils.deleteContents(storageDir));
+ if (mStorage != null) {
+ File storageDir = mStorage.mStorageDir;
+ assertTrue(FileUtils.deleteContents(storageDir));
+ }
- mPasswordSlotManager.cleanup();
+ if (mPasswordSlotManager != null) {
+ mPasswordSlotManager.cleanup();
+ }
}
protected void flushHandlerTasks() {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 02b86db..387b89a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -124,7 +124,9 @@
@After
public void tearDown() throws Exception {
- mStorage.closeDatabase();
+ if (mStorage != null) {
+ mStorage.closeDatabase();
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java
index 2faf6a2..2c2b937 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTests.java
@@ -49,7 +49,9 @@
@After
public void tearDown() throws Exception {
- mManager.cleanup();
+ if (mManager != null) {
+ mManager.cleanup();
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 1514de0..5add74e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -156,9 +156,12 @@
@After
public void tearDown() {
- mRecoverableKeyStoreDb.close();
- mDatabaseFile.delete();
-
+ if (mRecoverableKeyStoreDb != null) {
+ mRecoverableKeyStoreDb.close();
+ }
+ if (mDatabaseFile != null) {
+ mDatabaseFile.delete();
+ }
File file = new File(InstrumentationRegistry.getTargetContext().getFilesDir(),
SNAPSHOT_TOP_LEVEL_DIRECTORY);
FileUtils.deleteContentsAndDir(file);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
index c09e09c..46eaba7 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
@@ -117,8 +117,12 @@
@After
public void tearDown() {
- mRecoverableKeyStoreDb.close();
- mDatabaseFile.delete();
+ if (mRecoverableKeyStoreDb != null) {
+ mRecoverableKeyStoreDb.close();
+ }
+ if (mDatabaseFile != null) {
+ mDatabaseFile.delete();
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java
index 6413026..e6a6e36 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java
@@ -89,8 +89,12 @@
keyStore.load(/*param=*/ null);
keyStore.deleteEntry(WRAPPING_KEY_ALIAS);
- mRecoverableKeyStoreDb.close();
- mDatabaseFile.delete();
+ if (mRecoverableKeyStoreDb != null) {
+ mRecoverableKeyStoreDb.close();
+ }
+ if (mDatabaseFile != null) {
+ mDatabaseFile.delete();
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 7641fb9..878c838 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -230,9 +230,15 @@
@After
public void tearDown() {
- mRemoteLockscreenValidationSessionStorage.finishSession(mUserId);
- mRecoverableKeyStoreDb.close();
- mDatabaseFile.delete();
+ if (mRemoteLockscreenValidationSessionStorage != null) {
+ mRemoteLockscreenValidationSessionStorage.finishSession(mUserId);
+ }
+ if (mRecoverableKeyStoreDb != null) {
+ mRecoverableKeyStoreDb.close();
+ }
+ if (mDatabaseFile != null) {
+ mDatabaseFile.delete();
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
index bbd9223..fb98fab 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
@@ -36,8 +38,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class RecoverableKeyStoreDbHelperTest {
@@ -110,7 +110,9 @@
@After
public void tearDown() throws Exception {
- mDatabase.close();
+ if (mDatabase != null) {
+ mDatabase.close();
+ }
}
private void createV2Tables() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index 8bc14fc..a77d8bc 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -72,8 +72,12 @@
@After
public void tearDown() {
- mRecoverableKeyStoreDb.close();
- mDatabaseFile.delete();
+ if (mRecoverableKeyStoreDb != null) {
+ mRecoverableKeyStoreDb.close();
+ }
+ if (mDatabaseFile != null) {
+ mDatabaseFile.delete();
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayConstraintsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayConstraintsTests.java
index b2e296a..2912a07 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayConstraintsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayConstraintsTests.java
@@ -19,6 +19,7 @@
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.om.OverlayConstraint.TYPE_DEVICE_ID;
import static android.content.om.OverlayConstraint.TYPE_DISPLAY_ID;
+import static android.util.TypedValue.TYPE_STRING;
import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
@@ -28,6 +29,9 @@
import static org.testng.Assert.assertThrows;
+import android.app.Activity;
+import android.companion.virtual.VirtualDeviceManager;
+import android.content.Context;
import android.content.om.FabricatedOverlay;
import android.content.om.OverlayConstraint;
import android.content.om.OverlayIdentifier;
@@ -35,12 +39,12 @@
import android.content.om.OverlayManager;
import android.content.om.OverlayManagerTransaction;
import android.content.res.Flags;
+import android.content.res.Resources;
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.util.TypedValue;
+import android.view.Display;
+import android.virtualdevice.cts.common.VirtualDeviceRule;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
@@ -53,20 +57,28 @@
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeoutException;
@RunWith(JUnitParamsRunner.class)
public class OverlayConstraintsTests {
+ private static final String RESOURCE_NAME = "string/module_2_name";
+ private static final String RESOURCE_DEFAULT_VALUE = "module_2_name";
+ private static final String RESOURCE_OVERLAID_VALUE = "hello";
+ private static final long TIMEOUT_MILLIS = 2000L;
@Rule
- public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+ public final VirtualDeviceRule mVirtualDeviceRule = VirtualDeviceRule.createDefault();
private OverlayManager mOverlayManager;
private UserHandle mUserHandle;
private OverlayIdentifier mOverlayIdentifier = null;
+ private final String mPackageName = getApplicationContext().getPackageName();
@Before
public void setUp() throws Exception {
- mOverlayManager = getApplicationContext().getSystemService(OverlayManager.class);
+ final Context context = getApplicationContext();
+ mOverlayManager = context.getSystemService(OverlayManager.class);
mUserHandle = UserHandle.of(UserHandle.myUserId());
}
@@ -79,6 +91,7 @@
.build();
mOverlayManager.commit(transaction);
mOverlayIdentifier = null;
+ waitForResourceValue(RESOURCE_DEFAULT_VALUE, getApplicationContext());
}
}
@@ -161,13 +174,161 @@
List.of(new OverlayConstraint(TYPE_DISPLAY_ID, DEFAULT_DISPLAY))));
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_RRO_CONSTRAINTS)
+ public void enableOverlayWithoutConstraints_appliesOverlayWithoutConstraints()
+ throws Exception {
+ enableOverlay(Collections.emptyList());
+
+ // Assert than the overlay is applied for both default device context and virtual
+ // device context.
+ final Context context = getApplicationContext();
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, context);
+ VirtualDeviceManager.VirtualDevice virtualDevice =
+ mVirtualDeviceRule.createManagedVirtualDevice();
+ final Context deviceContext = context.createDeviceContext(virtualDevice.getDeviceId());
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, deviceContext);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_RRO_CONSTRAINTS)
+ public void enableOverlayWithConstraints_withTypeDeviceId_appliesOverlayWithConstraints()
+ throws Exception {
+ final int deviceId1 = mVirtualDeviceRule.createManagedVirtualDevice().getDeviceId();
+ final int deviceId2 = mVirtualDeviceRule.createManagedVirtualDevice().getDeviceId();
+ enableOverlay(List.of(new OverlayConstraint(TYPE_DEVICE_ID, deviceId1),
+ new OverlayConstraint(TYPE_DEVICE_ID, deviceId2)));
+
+ // Assert than the overlay is not applied for contexts not associated with the above
+ // devices.
+ final Context context = getApplicationContext();
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, context);
+ final int deviceId3 = mVirtualDeviceRule.createManagedVirtualDevice().getDeviceId();
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, context.createDeviceContext(deviceId3));
+
+ // Assert than the overlay is applied for contexts associated with the above devices.
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, context.createDeviceContext(deviceId1));
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, context.createDeviceContext(deviceId2));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_RRO_CONSTRAINTS)
+ public void enableOverlayWithConstraints_withTypeDisplayId_appliesOverlayWithConstraints()
+ throws Exception {
+ final Display display1 =
+ mVirtualDeviceRule.createManagedUnownedVirtualDisplay().getDisplay();
+ final Display display2 =
+ mVirtualDeviceRule.createManagedUnownedVirtualDisplay().getDisplay();
+ enableOverlay(List.of(new OverlayConstraint(TYPE_DISPLAY_ID, display1.getDisplayId()),
+ new OverlayConstraint(TYPE_DISPLAY_ID, display2.getDisplayId())));
+
+ // Assert than the overlay is not applied for contexts not associated with the above
+ // displays.
+ final Context context = getApplicationContext();
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, context);
+ final Display display3 =
+ mVirtualDeviceRule.createManagedUnownedVirtualDisplay().getDisplay();
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, context.createDisplayContext(display3));
+
+ // Assert than the overlay is applied for contexts associated with the above displays.
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, context.createDisplayContext(display1));
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, context.createDisplayContext(display2));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_RRO_CONSTRAINTS)
+ public void enableOverlayWithConstraints_withTypesDisplayIdAndDeviceId_appliesOverlayWithConstraints()
+ throws Exception {
+ final Display display1 =
+ mVirtualDeviceRule.createManagedUnownedVirtualDisplay().getDisplay();
+ final int deviceId1 = mVirtualDeviceRule.createManagedVirtualDevice().getDeviceId();
+ enableOverlay(List.of(new OverlayConstraint(TYPE_DISPLAY_ID, display1.getDisplayId()),
+ new OverlayConstraint(TYPE_DEVICE_ID, deviceId1)));
+
+ // Assert than the overlay is not applied for contexts not associated with the above
+ // display or device.
+ final Context context = getApplicationContext();
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, context);
+ final Display display2 =
+ mVirtualDeviceRule.createManagedUnownedVirtualDisplay().getDisplay();
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, context.createDisplayContext(display2));
+ final int deviceId2 = mVirtualDeviceRule.createManagedVirtualDevice().getDeviceId();
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, context.createDeviceContext(deviceId2));
+
+ // Assert than the overlay is applied for contexts associated with the above display or
+ // device.
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, context.createDisplayContext(display1));
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, context.createDeviceContext(deviceId1));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_RRO_CONSTRAINTS)
+ public void enableOverlayWithConstraints_withTypeDisplayId_appliesForActivityOnDisplay()
+ throws Exception {
+ final Display display =
+ mVirtualDeviceRule.createManagedUnownedVirtualDisplay(
+ VirtualDeviceRule.createTrustedVirtualDisplayConfigBuilder())
+ .getDisplay();
+ final Activity activityOnDefaultDisplay = mVirtualDeviceRule.startActivityOnDisplaySync(
+ DEFAULT_DISPLAY, Activity.class);
+ final Activity activityOnVirtualDisplay = mVirtualDeviceRule.startActivityOnDisplaySync(
+ display.getDisplayId(), Activity.class);
+
+ enableOverlay(List.of(new OverlayConstraint(TYPE_DISPLAY_ID, display.getDisplayId())));
+
+ // Assert than the overlay is not applied for any existing activity on the default display.
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, activityOnDefaultDisplay);
+ // Assert than the overlay is applied for any existing activity on the virtual display.
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, activityOnVirtualDisplay);
+
+ // Assert than the overlay is not applied for any new activity on the default display.
+ final Activity newActivityOnDefaultDisplay = mVirtualDeviceRule.startActivityOnDisplaySync(
+ DEFAULT_DISPLAY, Activity.class);
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, newActivityOnDefaultDisplay);
+ // Assert than the overlay is applied for any new activity on the virtual display.
+ final Activity newActivityOnVirtualDisplay = mVirtualDeviceRule.startActivityOnDisplaySync(
+ display.getDisplayId(), Activity.class);
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, newActivityOnVirtualDisplay);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_RRO_CONSTRAINTS)
+ public void enableOverlayWithConstraints_withTypeDeviceId_appliesForActivityOnDevice()
+ throws Exception {
+ final VirtualDeviceManager.VirtualDevice device =
+ mVirtualDeviceRule.createManagedVirtualDevice();
+ final Display display =
+ mVirtualDeviceRule.createManagedVirtualDisplay(device,
+ VirtualDeviceRule.createTrustedVirtualDisplayConfigBuilder())
+ .getDisplay();
+ final Activity activityOnDefaultDevice = mVirtualDeviceRule.startActivityOnDisplaySync(
+ DEFAULT_DISPLAY, Activity.class);
+ final Activity activityOnVirtualDevice = mVirtualDeviceRule.startActivityOnDisplaySync(
+ display.getDisplayId(), Activity.class);
+
+ enableOverlay(List.of(new OverlayConstraint(TYPE_DEVICE_ID, device.getDeviceId())));
+
+ // Assert than the overlay is not applied for any existing activity on the default device.
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, activityOnDefaultDevice);
+ // Assert than the overlay is applied for any existing activity on the virtual device.
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, activityOnVirtualDevice);
+
+ // Assert than the overlay is not applied for any new activity on the default device.
+ final Activity newActivityOnDefaultDevice = mVirtualDeviceRule.startActivityOnDisplaySync(
+ DEFAULT_DISPLAY, Activity.class);
+ ensureResourceValueStaysAt(RESOURCE_DEFAULT_VALUE, newActivityOnDefaultDevice);
+ // Assert than the overlay is applied for any new activity on the virtual device.
+ final Activity newActivityOnVirtualDevice = mVirtualDeviceRule.startActivityOnDisplaySync(
+ display.getDisplayId(), Activity.class);
+ waitForResourceValue(RESOURCE_OVERLAID_VALUE, newActivityOnVirtualDevice);
+ }
+
private FabricatedOverlay createFabricatedOverlay() {
- String packageName = getApplicationContext().getPackageName();
FabricatedOverlay fabricatedOverlay = new FabricatedOverlay.Builder(
- packageName, "testOverlay" /* name */, packageName)
+ mPackageName, "testOverlay" /* name */, mPackageName)
.build();
- fabricatedOverlay.setResourceValue("string/module_2_name" /* resourceName */,
- TypedValue.TYPE_STRING, "hello" /* value */, null /* configuration */);
+ fabricatedOverlay.setResourceValue(RESOURCE_NAME, TYPE_STRING, RESOURCE_OVERLAID_VALUE,
+ null /* configuration */);
return fabricatedOverlay;
}
@@ -183,6 +344,37 @@
mOverlayIdentifier = fabricatedOverlay.getIdentifier();
}
+ private static void waitForResourceValue(final String expectedValue, Context context)
+ throws TimeoutException {
+ final long endTime = System.currentTimeMillis() + TIMEOUT_MILLIS;
+ final Resources resources = context.getResources();
+ final int resourceId = getResourceId(context);
+ String resourceValue = null;
+ while (System.currentTimeMillis() < endTime) {
+ resourceValue = resources.getString(resourceId);
+ if (Objects.equals(resourceValue, expectedValue)) {
+ return;
+ }
+ }
+ throw new TimeoutException("Timed out waiting for '" + RESOURCE_NAME + "' value to equal '"
+ + expectedValue + "': current value is '" + resourceValue + "'");
+ }
+
+ private static void ensureResourceValueStaysAt(final String expectedValue, Context context) {
+ final long endTime = System.currentTimeMillis() + TIMEOUT_MILLIS;
+ final Resources resources = context.getResources();
+ final int resourceId = getResourceId(context);
+ String resourceValue;
+ while (System.currentTimeMillis() < endTime) {
+ resourceValue = resources.getString(resourceId);
+ assertEquals(expectedValue, resourceValue);
+ }
+ }
+
+ private static int getResourceId(Context context) {
+ return context.getResources().getIdentifier(RESOURCE_NAME, "", context.getPackageName());
+ }
+
private static List<OverlayConstraint>[] getAllConstraintLists() {
return new List[]{
Collections.emptyList(),
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 3ef360a..da14e45 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -95,8 +95,8 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
+import android.util.SparseArray;
-import com.android.internal.infra.AndroidFuture;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
@@ -110,6 +110,7 @@
import org.mockito.stubbing.Answer;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -149,6 +150,9 @@
protected static final String MAIN_ACTIVITY_CLASS = "MainActivity";
protected static final String PIN_CONFIRM_ACTIVITY_CLASS = "PinConfirmActivity";
+ private byte[] mBaseState;
+ protected final SparseArray<byte[]> mUserStates = new SparseArray<>();
+
// public for mockito
public class BaseContext extends MockContext {
@Override
@@ -287,6 +291,7 @@
final ServiceContext mContext;
IUidObserver mUidObserver;
+
public ShortcutServiceTestable(ServiceContext context, Looper looper) {
super(context, looper, /* onyForPackageManagerApis */ false);
mContext = context;
@@ -567,6 +572,58 @@
// During tests, WTF is fatal.
fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
}
+
+ @Override
+ void injectSaveBaseState() {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ saveBaseStateAsXml(baos);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ mBaseState = baos.toByteArray();
+ }
+
+ @Override
+ protected void injectLoadBaseState() {
+ if (mBaseState == null) {
+ return;
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(mBaseState);
+ try {
+ loadBaseStateAsXml(bais);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void injectSaveUser(@UserIdInt int userId) {
+ synchronized (mServiceLock) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ saveUserInternalLocked(userId, baos, /* forBackup= */ false);
+ cleanupDanglingBitmapDirectoriesLocked(userId);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ mUserStates.put(userId, baos.toByteArray());
+ }
+ }
+
+ @Override
+ protected ShortcutUser injectLoadUserLocked(@UserIdInt int userId) {
+ final byte[] userState = mUserStates.get(userId);
+ if (userState == null) {
+ return null;
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(userState);
+ try {
+ return loadUserInternal(userId, bais, /* forBackup= */ false);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
}
/** ShortcutManager with injection override methods. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index f536cae..ad1537e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -201,7 +201,7 @@
mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL + 50;
assertResetTimes(START_TIME + 4 * INTERVAL, START_TIME + 5 * INTERVAL);
- mService.saveBaseState();
+ mService.injectSaveBaseState();
dumpBaseStateFile();
@@ -261,7 +261,7 @@
// === Test for app side APIs ===
/** Test for {@link android.content.pm.ShortcutManager#getMaxShortcutCountForActivity()} */
- public void testGetMaxDynamicShortcutCount() {
+ public void disabled_testGetMaxDynamicShortcutCount() {
assertEquals(MAX_SHORTCUTS, mManager.getMaxShortcutCountForActivity());
}
@@ -793,7 +793,7 @@
assertEquals(2, mManager.getRemainingCallCount());
}
- public void testDeleteAllDynamicShortcuts() {
+ public void disabled_testDeleteAllDynamicShortcuts() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
final ShortcutInfo si2 = makeShortcut("shortcut2");
final ShortcutInfo si3 = makeShortcut("shortcut3");
@@ -1036,7 +1036,7 @@
*/
}
- public void testCleanupDanglingBitmaps() throws Exception {
+ public void disabled_testCleanupDanglingBitmaps() throws Exception {
assertBitmapDirectories(USER_10, EMPTY_STRINGS);
assertBitmapDirectories(USER_11, EMPTY_STRINGS);
@@ -1702,7 +1702,7 @@
"s2");
}
- public void testCachedShortcuts_accessShortcutsPermission() {
+ public void disabled_testCachedShortcuts_accessShortcutsPermission() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
@@ -1744,7 +1744,7 @@
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED), "s3");
}
- public void testCachedShortcuts_canPassShortcutLimit() {
+ public void disabled_testCachedShortcuts_canPassShortcutLimit() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=4");
@@ -2362,7 +2362,7 @@
* This is similar to the above test, except it used "disable" instead of "remove". It also
* does "enable".
*/
- public void testDisableAndEnableShortcuts() {
+ public void disabled_testDisableAndEnableShortcuts() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
@@ -2487,7 +2487,7 @@
});
}
- public void testDisableShortcuts_thenRepublish() {
+ public void disabled_testDisableShortcuts_thenRepublish() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
@@ -4230,7 +4230,7 @@
// TODO Check all other fields
}
- public void testCleanupPackage() {
+ public void disabled_testCleanupPackage() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s0_1"))));
@@ -4507,7 +4507,7 @@
mService.saveDirtyInfo();
}
- public void testCleanupPackage_republishManifests() {
+ public void disabled_testCleanupPackage_republishManifests() {
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
@@ -4847,7 +4847,7 @@
assertEquals(expected, spi.canRestoreTo(mService, pi, true));
}
- public void testCanRestoreTo() {
+ public void disabled_testCanRestoreTo() {
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sig1");
addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 10, "sig1", "sig2");
addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 10, "sig1");
@@ -5785,7 +5785,7 @@
checkBackupAndRestore_success(/*firstRestore=*/ true);
}
- public void testBackupAndRestore_restoreToSuperSetSignatures() {
+ public void disabled_testBackupAndRestore_restoreToSuperSetSignatures() {
prepareForBackupTest();
// Change package signatures.
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 3b32701..f5690b7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -54,9 +54,7 @@
import com.android.frameworks.servicestests.R;
import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
-import java.io.Writer;
import java.util.Locale;
/**
@@ -2358,12 +2356,10 @@
* can still be read.
*/
public void testLoadLegacySavedFile() throws Exception {
- final File path = mService.getUserFile(USER_10).getBaseFile();
- path.getParentFile().mkdirs();
- try (Writer w = new FileWriter(path)) {
- w.write(readTestAsset("shortcut/shortcut_legacy_file.xml"));
- };
+ final String legacyFile = readTestAsset("shortcut/shortcut_legacy_file.xml");
+ mUserStates.put(USER_10, legacyFile.getBytes());
initService();
+
mService.handleUnlockUser(USER_10);
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 5dea44d..67e85ff 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -4495,6 +4495,27 @@
}
@Test
+ public void testBubblePreference_sameVersionWithSAWPermission() throws Exception {
+ when(mAppOpsManager.noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(),
+ anyString(), eq(null), anyString())).thenReturn(MODE_ALLOWED);
+
+ final String xml = "<ranking version=\"4\">\n"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\">\n"
+ + "<channel id=\"someId\" name=\"hi\""
+ + " importance=\"3\"/>"
+ + "</package>"
+ + "</ranking>";
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+ assertEquals(BUBBLE_PREFERENCE_ALL, mHelper.getBubblePreference(PKG_O, UID_O));
+ assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O));
+ }
+
+ @Test
public void testBubblePreference_upgradeWithSAWThenUserOverride() throws Exception {
when(mAppOpsManager.noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(),
anyString(), eq(null), anyString())).thenReturn(MODE_ALLOWED);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 0ab11e0..f8387a4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -300,7 +300,7 @@
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
- return FlagsParameterization.allCombinationsOf(FLAG_MODES_UI, FLAG_BACKUP_RESTORE_LOGGING,
+ return FlagsParameterization.allCombinationsOf(FLAG_BACKUP_RESTORE_LOGGING,
com.android.server.notification.Flags.FLAG_FIX_CALLING_UID_FROM_CPS);
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java b/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java
index d5548a4..f091a65 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java
@@ -497,19 +497,19 @@
private VibratorController createEmptyVibratorController(int vibratorId) {
return new FakeVibratorControllerProvider(mTestLooper.getLooper())
- .newVibratorController(vibratorId, (id, vibrationId) -> {});
+ .newVibratorController(vibratorId, (id, vibrationId, stepId) -> {});
}
private VibratorController createBasicVibratorController(int vibratorId) {
FakeVibratorControllerProvider provider = createVibratorProviderWithEffects(
IVibrator.CAP_COMPOSE_EFFECTS);
- return provider.newVibratorController(vibratorId, (id, vibrationId) -> {});
+ return provider.newVibratorController(vibratorId, (id, vibrationId, stepId) -> {});
}
private VibratorController createPwleWithoutFrequenciesVibratorController(int vibratorId) {
FakeVibratorControllerProvider provider = createVibratorProviderWithEffects(
IVibrator.CAP_COMPOSE_EFFECTS, IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
- return provider.newVibratorController(vibratorId, (id, vibrationId) -> {});
+ return provider.newVibratorController(vibratorId, (id, vibrationId, stepId) -> {});
}
private VibratorController createPwleVibratorController(int vibratorId) {
@@ -519,7 +519,7 @@
provider.setMinFrequency(TEST_MIN_FREQUENCY);
provider.setFrequencyResolution(TEST_FREQUENCY_RESOLUTION);
provider.setMaxAmplitudes(TEST_AMPLITUDE_MAP);
- return provider.newVibratorController(vibratorId, (id, vibrationId) -> {});
+ return provider.newVibratorController(vibratorId, (id, vibrationId, stepId) -> {});
}
private VibratorController createPwleV2VibratorController(int vibratorId) {
@@ -538,7 +538,7 @@
provider.setMinEnvelopeEffectControlPointDurationMillis(
TEST_MIN_ENVELOPE_EFFECT_CONTROL_POINT_DURATION_MILLIS);
- return provider.newVibratorController(vibratorId, (id, vibrationId) -> {});
+ return provider.newVibratorController(vibratorId, (id, vibrationId, stepId) -> {});
}
private FakeVibratorControllerProvider createVibratorProviderWithEffects(int... capabilities) {
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
index 5f2af0a..42279e4 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -17,6 +17,9 @@
package com.android.server.vibrator;
import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationEffect.Composition.PRIMITIVE_CLICK;
+import static android.os.VibrationEffect.Composition.PRIMITIVE_SPIN;
+import static android.os.VibrationEffect.Composition.PRIMITIVE_TICK;
import static android.os.VibrationEffect.VibrationParameter.targetAmplitude;
import static android.os.VibrationEffect.VibrationParameter.targetFrequency;
@@ -66,7 +69,6 @@
import android.os.vibrator.VibrationEffectSegment;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -153,9 +155,10 @@
when(mPackageManagerInternalMock.getSystemUiServiceComponent())
.thenReturn(new ComponentName("", ""));
doAnswer(answer -> {
- mVibrationConductor.notifyVibratorComplete(answer.getArgument(0));
+ mVibrationConductor.notifyVibratorComplete(
+ answer.getArgument(0), answer.getArgument(2));
return null;
- }).when(mControllerCallbacks).onComplete(anyInt(), anyLong());
+ }).when(mControllerCallbacks).onComplete(anyInt(), anyLong(), anyLong());
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
@@ -190,7 +193,7 @@
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibration.id));
+ verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.IGNORED_UNSUPPORTED);
}
@@ -203,7 +206,7 @@
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibration.id));
+ verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.IGNORED_UNSUPPORTED);
}
@@ -217,7 +220,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
@@ -234,7 +237,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
@@ -254,7 +257,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(15L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
@@ -265,7 +268,7 @@
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
+ @EnableFlags(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
public void vibrate_singleWaveformWithAdaptiveHapticsScaling_scalesAmplitudesProperly() {
// No user settings scale.
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
@@ -291,7 +294,7 @@
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
+ @EnableFlags(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
public void vibrate_withVibrationParamsRequestStalling_timeoutRequestAndApplyNoScaling() {
// No user settings scale.
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
@@ -412,6 +415,7 @@
.isEqualTo(expectedOneShots(200L, 50L));
}
+ @EnableFlags(Flags.FLAG_FIX_VIBRATION_THREAD_CALLBACK_HANDLING)
@LargeTest
@Test
public void vibrate_singleVibratorRepeatingPatternWithZeroDurationSteps_repeatsEffectCorrectly()
@@ -443,6 +447,30 @@
.isEqualTo(expectedOneShots(200L, 150L, 300L, 150L, 300L));
}
+ @EnableFlags(Flags.FLAG_FIX_VIBRATION_THREAD_CALLBACK_HANDLING)
+ @Test
+ public void vibrate_singleVibratorPatternWithCallbackDelay_oldCallbacksIgnored() {
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
+ fakeVibrator.setCompletionCallbackDelay(100); // 100ms delay to notify service.
+ fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 200, 50, 400}, /* repeat= */ -1);
+ HalVibration vibration = startThreadAndDispatcher(effect);
+ waitForCompletion(800 + TEST_TIMEOUT_MILLIS); // 200 + 50 + 400 + 100ms delay
+
+ verifyCallbacksTriggered(vibration, Status.FINISHED);
+ assertThat(mControllers.get(VIBRATOR_ID).isVibrating()).isFalse();
+
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), eq(1L));
+ // Step id = 2 skipped by the 50ms OFF step after the 200ms ON step.
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), eq(3L));
+
+ // First callback ignored, did not cause the vibrator to turn back on during the 400ms step.
+ assertThat(fakeVibrator.getEffectSegments(vibration.id))
+ .isEqualTo(expectedOneShots(200L, 400L));
+ }
+
@Test
public void vibrate_singleVibratorRepeatingPwle_generatesLargestPwles() throws Exception {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
@@ -479,12 +507,12 @@
throws Exception {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- fakeVibrator.setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK);
+ fakeVibrator.setSupportedPrimitives(PRIMITIVE_CLICK);
fakeVibrator.setCompositionSizeMax(10);
VibrationEffect effect = VibrationEffect.startComposition()
// Very long delay so thread will be cancelled after first PWLE is triggered.
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1f, 100)
.compose();
VibrationEffect repeatingEffect = VibrationEffect.startComposition()
.repeatEffectIndefinitely(effect)
@@ -561,13 +589,12 @@
public void vibrate_singleVibratorPredefinedCancel_cancelsVibrationImmediately()
throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(PRIMITIVE_CLICK);
VibrationEffect effect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1f, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1f, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1f, 100)
.compose();
HalVibration vibration = startThreadAndDispatcher(effect);
@@ -591,7 +618,7 @@
}
@Test
- @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+ @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
public void vibrate_singleVibratorVendorEffectCancel_cancelsVibrationImmediately()
throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_PERFORM_VENDOR_EFFECTS);
@@ -657,7 +684,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
@@ -678,7 +705,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
@@ -695,13 +722,14 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(0L));
verify(mManagerHooks, never()).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks, never()).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, never())
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.IGNORED_UNSUPPORTED);
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibration.id).isEmpty());
}
@Test
- @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+ @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
public void vibrate_singleVibratorVendorEffect_runsVibration() {
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_PERFORM_VENDOR_EFFECTS);
@@ -712,7 +740,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID),
eq(PerformVendorEffectVibratorStep.VENDOR_EFFECT_MAX_DURATION_MS));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertThat(mControllers.get(VIBRATOR_ID).isVibrating()).isFalse();
@@ -725,24 +753,23 @@
public void vibrate_singleVibratorComposed_runsVibration() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- fakeVibrator.setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK,
- VibrationEffect.Composition.PRIMITIVE_TICK);
+ fakeVibrator.setSupportedPrimitives(PRIMITIVE_CLICK, PRIMITIVE_TICK);
VibrationEffect effect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
+ .addPrimitive(PRIMITIVE_CLICK, 1f)
+ .addPrimitive(PRIMITIVE_TICK, 0.5f)
.compose();
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(40L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
- expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0),
- expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, 0)),
+ expectedPrimitive(PRIMITIVE_CLICK, 1, 0),
+ expectedPrimitive(PRIMITIVE_TICK, 0.5f, 0)),
fakeVibrator.getEffectSegments(vibration.id));
}
@@ -750,14 +777,15 @@
@DisableFlags(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY)
public void vibrate_singleVibratorComposedAndNoCapability_triggersHalAndReturnsUnsupported() {
VibrationEffect effect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
+ .addPrimitive(PRIMITIVE_CLICK, 1f)
.compose();
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(0L));
verify(mManagerHooks, never()).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks, never()).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, never())
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.IGNORED_UNSUPPORTED);
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibration.id).isEmpty());
}
@@ -766,14 +794,15 @@
@EnableFlags(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY)
public void vibrate_singleVibratorComposedAndNoCapability_ignoresVibration() {
VibrationEffect effect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
+ .addPrimitive(PRIMITIVE_CLICK, 1f)
.compose();
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
verify(mManagerHooks, never()).noteVibratorOn(eq(UID), anyLong());
verify(mManagerHooks, never()).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks, never()).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, never())
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.IGNORED_UNSUPPORTED);
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibration.id).isEmpty());
}
@@ -782,34 +811,30 @@
public void vibrate_singleVibratorLargeComposition_splitsVibratorComposeCalls() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- fakeVibrator.setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK,
- VibrationEffect.Composition.PRIMITIVE_TICK,
- VibrationEffect.Composition.PRIMITIVE_SPIN);
+ fakeVibrator.setSupportedPrimitives(PRIMITIVE_CLICK, PRIMITIVE_TICK, PRIMITIVE_SPIN);
fakeVibrator.setCompositionSizeMax(2);
VibrationEffect effect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SPIN, 0.8f)
+ .addPrimitive(PRIMITIVE_CLICK, 1f)
+ .addPrimitive(PRIMITIVE_TICK, 0.5f)
+ .addPrimitive(PRIMITIVE_SPIN, 0.8f)
.compose();
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
verifyCallbacksTriggered(vibration, Status.FINISHED);
// Vibrator compose called twice.
- verify(mControllerCallbacks, times(2)).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, times(2))
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
assertEquals(3, fakeVibrator.getEffectSegments(vibration.id).size());
}
@Test
- @DisableFlags(android.os.vibrator.Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @DisableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void vibrate_singleVibratorComposedEffects_runsDifferentVibrations() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
- fakeVibrator.setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK,
- VibrationEffect.Composition.PRIMITIVE_TICK);
+ fakeVibrator.setSupportedPrimitives(PRIMITIVE_CLICK, PRIMITIVE_TICK);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS,
IVibrator.CAP_COMPOSE_PWLE_EFFECTS, IVibrator.CAP_AMPLITUDE_CONTROL);
fakeVibrator.setMinFrequency(100);
@@ -820,8 +845,8 @@
VibrationEffect effect = VibrationEffect.startComposition()
.addEffect(VibrationEffect.createOneShot(10, 100))
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
+ .addPrimitive(PRIMITIVE_CLICK, 1f)
+ .addPrimitive(PRIMITIVE_TICK, 0.5f)
.addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
.addEffect(VibrationEffect.startWaveform()
.addTransition(Duration.ofMillis(10),
@@ -836,13 +861,14 @@
// Use first duration the vibrator is turned on since we cannot estimate the clicks.
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(10L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks, times(5)).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, times(5))
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedOneShot(10),
- expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0),
- expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, 0),
+ expectedPrimitive(PRIMITIVE_CLICK, 1, 0),
+ expectedPrimitive(PRIMITIVE_TICK, 0.5f, 0),
expectedPrebaked(VibrationEffect.EFFECT_CLICK),
expectedRamp(/* startAmplitude= */ 0, /* endAmplitude= */ 0.5f,
/* startFrequencyHz= */ 150, /* endFrequencyHz= */ 100, /* duration= */ 10),
@@ -857,17 +883,15 @@
public void vibrate_singleVibratorComposedWithFallback_replacedInTheMiddleOfComposition() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
- fakeVibrator.setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK,
- VibrationEffect.Composition.PRIMITIVE_TICK);
+ fakeVibrator.setSupportedPrimitives(PRIMITIVE_CLICK, PRIMITIVE_TICK);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
VibrationEffect fallback = VibrationEffect.createOneShot(10, 100);
VibrationEffect effect = VibrationEffect.startComposition()
.addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
+ .addPrimitive(PRIMITIVE_CLICK, 1f)
.addEffect(VibrationEffect.get(VibrationEffect.EFFECT_TICK))
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
+ .addPrimitive(PRIMITIVE_TICK, 0.5f)
.compose();
HalVibration vibration = createVibration(CombinedVibration.createParallel(effect));
vibration.fillFallbacks(unused -> fallback);
@@ -877,7 +901,8 @@
// Use first duration the vibrator is turned on since we cannot estimate the clicks.
verify(mManagerHooks).noteVibratorOn(eq(UID), anyLong());
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks, times(4)).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, times(4))
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
@@ -894,7 +919,7 @@
}
@Test
- @EnableFlags(android.os.vibrator.Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void vibrate_singleVibratorPwle_runsComposePwleV2() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
@@ -915,7 +940,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(100L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
@@ -929,7 +954,7 @@
}
@Test
- @EnableFlags(android.os.vibrator.Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void vibrate_singleVibratorBasicPwle_runsComposePwleV2() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
@@ -951,7 +976,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(220L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
@@ -964,7 +989,7 @@
}
@Test
- @EnableFlags(android.os.vibrator.Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void vibrate_singleVibratorPwle_withInitialFrequency_runsComposePwleV2() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
@@ -987,7 +1012,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(100L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
@@ -1001,7 +1026,7 @@
}
@Test
- @EnableFlags(android.os.vibrator.Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void vibrate_singleVibratorPwle_TooManyControlPoints_splitsAndRunsComposePwleV2() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
@@ -1027,7 +1052,8 @@
verifyCallbacksTriggered(vibration, Status.FINISHED);
// Vibrator compose called 3 times with 2 segments instead of 2 times with 3 segments.
// Using best split points instead of max-packing PWLEs.
- verify(mControllerCallbacks, times(3)).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, times(3))
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
@@ -1043,7 +1069,7 @@
}
@Test
- @DisableFlags(android.os.vibrator.Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @DisableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void vibrate_singleVibratorPwle_runsComposePwle() {
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
@@ -1066,7 +1092,7 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(100L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
@@ -1109,7 +1135,8 @@
// Vibrator compose called 3 times with 2 segments instead of 2 times with 3 segments.
// Using best split points instead of max-packing PWLEs.
- verify(mControllerCallbacks, times(3)).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks, times(3))
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
assertEquals(6, fakeVibrator.getEffectSegments(vibration.id).size());
}
@@ -1160,8 +1187,8 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
- verify(mControllerCallbacks, never()).onComplete(eq(2), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks, never()).onComplete(eq(2), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
@@ -1183,9 +1210,9 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id));
- verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id));
- verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
@@ -1207,11 +1234,10 @@
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(3).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(4).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(4).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(4).setSupportedPrimitives(PRIMITIVE_CLICK);
VibrationEffect composed = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(PRIMITIVE_CLICK)
.compose();
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
@@ -1225,10 +1251,10 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id));
- verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id));
- verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id));
- verify(mControllerCallbacks).onComplete(eq(4), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks).onComplete(eq(4), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
@@ -1243,8 +1269,7 @@
assertEquals(Arrays.asList(expectedOneShot(20)),
mVibratorProviders.get(3).getEffectSegments(vibration.id));
assertEquals(expectedAmplitudes(1, 2), mVibratorProviders.get(3).getAmplitudes());
- assertEquals(Arrays.asList(
- expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0)),
+ assertEquals(Arrays.asList(expectedPrimitive(PRIMITIVE_CLICK, 1, 0)),
mVibratorProviders.get(4).getEffectSegments(vibration.id));
}
@@ -1253,12 +1278,11 @@
mockVibrators(1, 2, 3);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(2).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(2).setSupportedPrimitives(PRIMITIVE_CLICK);
mVibratorProviders.get(3).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
VibrationEffect composed = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(PRIMITIVE_CLICK)
.compose();
CombinedVibration effect = CombinedVibration.startSequential()
.addNext(3, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), /* delay= */ 50)
@@ -1268,10 +1292,10 @@
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- InOrder controllerVerifier = inOrder(mControllerCallbacks);
- controllerVerifier.verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id));
- controllerVerifier.verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id));
- controllerVerifier.verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id));
+ InOrder verifier = inOrder(mControllerCallbacks);
+ verifier.verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id), anyLong());
+ verifier.verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id), anyLong());
+ verifier.verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id), anyLong());
InOrder batteryVerifier = inOrder(mManagerHooks);
batteryVerifier.verify(mManagerHooks).noteVibratorOn(eq(UID), eq(20L));
@@ -1289,8 +1313,7 @@
assertEquals(Arrays.asList(expectedOneShot(10)),
mVibratorProviders.get(1).getEffectSegments(vibration.id));
assertEquals(expectedAmplitudes(100), mVibratorProviders.get(1).getAmplitudes());
- assertEquals(Arrays.asList(
- expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0)),
+ assertEquals(Arrays.asList(expectedPrimitive(PRIMITIVE_CLICK, 1, 0)),
mVibratorProviders.get(2).getEffectSegments(vibration.id));
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
mVibratorProviders.get(3).getEffectSegments(vibration.id));
@@ -1301,15 +1324,13 @@
int[] vibratorIds = new int[]{1, 2};
mockVibrators(vibratorIds);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(1).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(1).setSupportedPrimitives(PRIMITIVE_CLICK);
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(2).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(2).setSupportedPrimitives(PRIMITIVE_CLICK);
when(mManagerHooks.prepareSyncedVibration(anyLong(), eq(vibratorIds))).thenReturn(true);
VibrationEffect composed = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1, 100)
.compose();
CombinedVibration effect = CombinedVibration.createParallel(composed);
// We create the HalVibration here to obtain the vibration id and use it to mock the
@@ -1331,8 +1352,7 @@
verify(mManagerHooks, never()).cancelSyncedVibration();
verifyCallbacksTriggered(vibration, Status.FINISHED);
- VibrationEffectSegment expected = expectedPrimitive(
- VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 100);
+ VibrationEffectSegment expected = expectedPrimitive(PRIMITIVE_CLICK, 1, 100);
assertEquals(Arrays.asList(expected),
mVibratorProviders.get(1).getEffectSegments(vibration.id));
assertEquals(Arrays.asList(expected),
@@ -1345,12 +1365,11 @@
mockVibrators(vibratorIds);
mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
mVibratorProviders.get(4).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(4).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(4).setSupportedPrimitives(PRIMITIVE_CLICK);
when(mManagerHooks.prepareSyncedVibration(anyLong(), any())).thenReturn(true);
VibrationEffect composed = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(PRIMITIVE_CLICK)
.compose();
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
@@ -1463,9 +1482,9 @@
verify(mManagerHooks).noteVibratorOn(eq(UID), eq(80L));
verify(mManagerHooks).noteVibratorOff(eq(UID));
- verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id));
- verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id));
- verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(1), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks).onComplete(eq(2), eq(vibration.id), anyLong());
+ verify(mControllerCallbacks).onComplete(eq(3), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertFalse(mControllers.get(1).isVibrating());
assertFalse(mControllers.get(2).isVibrating());
@@ -1505,7 +1524,7 @@
waitForCompletion(rampDownDuration + TEST_TIMEOUT_MILLIS);
long completionTime = SystemClock.elapsedRealtime();
- verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibration.id);
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
// Vibration ends after duration, thread completed after ramp down
assertThat(vibrationEndTime - startTime).isAtLeast(expectedDuration);
assertThat(vibrationEndTime - startTime).isLessThan(expectedDuration + rampDownDuration);
@@ -1534,7 +1553,7 @@
waitForCompletion(TEST_TIMEOUT_MILLIS);
- verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibration.id);
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
assertThat(vibrationEndTime - startTime).isAtLeast(expectedDuration + callbackDelay);
}
@@ -1563,7 +1582,8 @@
waitForCompletion(callbackDelay + TEST_TIMEOUT_MILLIS);
long completionTime = SystemClock.elapsedRealtime();
- verify(mControllerCallbacks, never()).onComplete(VIBRATOR_ID, vibration.id);
+ verify(mControllerCallbacks, never())
+ .onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
// Vibration ends and thread completes after timeout, before the HAL callback
assertThat(vibrationEndTime - startTime).isAtLeast(expectedDuration + callbackTimeout);
assertThat(vibrationEndTime - startTime).isLessThan(expectedDuration + callbackDelay);
@@ -1639,15 +1659,14 @@
mockVibrators(1, 2);
mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(2).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(2).setSupportedPrimitives(PRIMITIVE_CLICK);
CombinedVibration effect = CombinedVibration.startParallel()
.addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
.addVibrator(2, VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1f, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1f, 100)
+ .addPrimitive(PRIMITIVE_CLICK, 1f, 100)
.compose())
.combine();
HalVibration vibration = startThreadAndDispatcher(effect);
@@ -1672,7 +1691,7 @@
}
@Test
- @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+ @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
public void vibrate_multipleVendorEffectCancel_cancelsVibrationImmediately() throws Exception {
mockVibrators(1, 2);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_PERFORM_VENDOR_EFFECTS);
@@ -1767,7 +1786,7 @@
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
// Duration extended for 5 + 5 + 5 + 15.
@@ -1847,7 +1866,7 @@
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
@@ -1856,7 +1875,7 @@
}
@Test
- @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+ @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
public void vibrate_vendorEffectWithRampDown_doesNotAddRampDown() {
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_PERFORM_VENDOR_EFFECTS);
@@ -1865,7 +1884,7 @@
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertThat(mVibratorProviders.get(VIBRATOR_ID).getVendorEffects(vibration.id))
@@ -1879,26 +1898,24 @@
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(PRIMITIVE_CLICK);
VibrationEffect effect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(PRIMITIVE_CLICK)
.compose();
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
- assertEquals(
- Arrays.asList(expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0)),
+ assertEquals(Arrays.asList(expectedPrimitive(PRIMITIVE_CLICK, 1, 0)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibration.id));
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getAmplitudes().isEmpty());
}
@Test
- @DisableFlags(android.os.vibrator.Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @DisableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void vibrate_pwleWithRampDown_doesNotAddRampDown() {
when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
@@ -1916,7 +1933,7 @@
HalVibration vibration = startThreadAndDispatcher(effect);
waitForCompletion();
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration.id), anyLong());
verifyCallbacksTriggered(vibration, Status.FINISHED);
assertEquals(Arrays.asList(expectedRamp(0, 1, 150, 150, 1)),
@@ -1928,8 +1945,7 @@
public void vibrate_multipleVibrations_withCancel() throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setSupportedEffects(
VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK);
- mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(PRIMITIVE_CLICK);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
IVibrator.CAP_COMPOSE_EFFECTS);
@@ -1940,7 +1956,7 @@
.repeatEffectIndefinitely(VibrationEffect.get(VibrationEffect.EFFECT_TICK))
.compose();
VibrationEffect effect3 = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(PRIMITIVE_CLICK)
.compose();
VibrationEffect effect4 = VibrationEffect.createOneShot(8000, 100);
VibrationEffect effect5 = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
@@ -1974,14 +1990,15 @@
assertFalse(mControllers.get(VIBRATOR_ID).isVibrating());
// Effect1
- verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibration1.id);
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration1.id), anyLong());
verifyCallbacksTriggered(vibration1, Status.FINISHED);
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
fakeVibrator.getEffectSegments(vibration1.id));
// Effect2: repeating, cancelled.
- verify(mControllerCallbacks, atLeast(2)).onComplete(VIBRATOR_ID, vibration2.id);
+ verify(mControllerCallbacks, atLeast(2))
+ .onComplete(eq(VIBRATOR_ID), eq(vibration2.id), anyLong());
verifyCallbacksTriggered(vibration2, Status.CANCELLED_BY_USER);
// The exact count of segments might vary, so just check that there's more than 2 and
@@ -1994,10 +2011,9 @@
}
// Effect3
- verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration3.id));
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibration3.id), anyLong());
verifyCallbacksTriggered(vibration3, Status.FINISHED);
- assertEquals(Arrays.asList(
- expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0)),
+ assertEquals(Arrays.asList(expectedPrimitive(PRIMITIVE_CLICK, 1, 0)),
fakeVibrator.getEffectSegments(vibration3.id));
// Effect4: cancelled quickly.
@@ -2014,8 +2030,7 @@
mockVibrators(1, 2, 3);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(2).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- mVibratorProviders.get(2).setSupportedPrimitives(
- VibrationEffect.Composition.PRIMITIVE_CLICK);
+ mVibratorProviders.get(2).setSupportedPrimitives(PRIMITIVE_CLICK);
mVibratorProviders.get(3).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
CombinedVibration effect = CombinedVibration.startSequential()
@@ -2029,8 +2044,7 @@
/* delay= */ TEST_TIMEOUT_MILLIS)
.addNext(2,
VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1,
- /* delay= */ TEST_TIMEOUT_MILLIS)
+ .addPrimitive(PRIMITIVE_CLICK, 1, /* delay= */ TEST_TIMEOUT_MILLIS)
.compose(),
/* delay= */ TEST_TIMEOUT_MILLIS)
.combine();
@@ -2051,8 +2065,7 @@
assertEquals(Arrays.asList(expectedOneShot(TEST_TIMEOUT_MILLIS)),
mVibratorProviders.get(1).getEffectSegments(vibration.id));
assertEquals(expectedAmplitudes(255), mVibratorProviders.get(1).getAmplitudes());
- assertEquals(Arrays.asList(expectedPrimitive(
- VibrationEffect.Composition.PRIMITIVE_CLICK, 1, TEST_TIMEOUT_MILLIS)),
+ assertEquals(Arrays.asList(expectedPrimitive(PRIMITIVE_CLICK, 1, TEST_TIMEOUT_MILLIS)),
mVibratorProviders.get(2).getEffectSegments(vibration.id));
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
mVibratorProviders.get(3).getEffectSegments(vibration.id));
@@ -2205,7 +2218,7 @@
private void verifyCallbacksTriggered(HalVibration vibration, Status expectedStatus) {
assertThat(vibration.getStatus()).isEqualTo(expectedStatus);
- verify(mManagerHooks).onVibrationThreadReleased(vibration.id);
+ verify(mManagerHooks).onVibrationThreadReleased(eq(vibration.id));
}
private static final class TestLooperAutoDispatcher extends Thread {
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java
index 0978f48..4df13de 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java
@@ -203,9 +203,10 @@
@Test
public void setAmplitude_vibratorVibrating_setsAmplitude() {
- when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));
+ when(mNativeWrapperMock.on(anyLong(), anyLong(), anyLong()))
+ .thenAnswer(args -> args.getArgument(0));
VibratorController controller = createController();
- controller.on(100, /* vibrationId= */ 1);
+ controller.on(100, 1, 1);
assertTrue(controller.isVibrating());
assertEquals(-1, controller.getCurrentAmplitude(), /* delta= */ 0);
@@ -215,81 +216,84 @@
@Test
public void on_withDuration_turnsVibratorOn() {
- when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));
+ when(mNativeWrapperMock.on(anyLong(), anyLong(), anyLong()))
+ .thenAnswer(args -> args.getArgument(0));
VibratorController controller = createController();
- controller.on(100, 10);
+ controller.on(100, 10, 20);
assertTrue(controller.isVibrating());
- verify(mNativeWrapperMock).on(eq(100L), eq(10L));
+ verify(mNativeWrapperMock).on(eq(100L), eq(10L), eq(20L));
}
@Test
public void on_withPrebaked_performsEffect() {
- when(mNativeWrapperMock.perform(anyLong(), anyLong(), anyLong())).thenReturn(10L);
+ when(mNativeWrapperMock.perform(anyLong(), anyLong(), anyLong(), anyLong()))
+ .thenReturn(10L);
VibratorController controller = createController();
PrebakedSegment prebaked = createPrebaked(VibrationEffect.EFFECT_CLICK,
VibrationEffect.EFFECT_STRENGTH_MEDIUM);
- assertEquals(10L, controller.on(prebaked, 11));
+ assertEquals(10L, controller.on(prebaked, 11, 23));
assertTrue(controller.isVibrating());
verify(mNativeWrapperMock).perform(eq((long) VibrationEffect.EFFECT_CLICK),
- eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), eq(11L));
+ eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), eq(11L), eq(23L));
}
@Test
public void on_withComposed_performsEffect() {
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- when(mNativeWrapperMock.compose(any(), anyLong())).thenReturn(15L);
+ when(mNativeWrapperMock.compose(any(), anyLong(), anyLong())).thenReturn(15L);
VibratorController controller = createController();
PrimitiveSegment[] primitives = new PrimitiveSegment[]{
new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10)
};
- assertEquals(15L, controller.on(primitives, 12));
+ assertEquals(15L, controller.on(primitives, 12, 34));
assertTrue(controller.isVibrating());
- verify(mNativeWrapperMock).compose(eq(primitives), eq(12L));
+ verify(mNativeWrapperMock).compose(eq(primitives), eq(12L), eq(34L));
}
@Test
public void on_withComposedPwle_performsEffect() {
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
- when(mNativeWrapperMock.composePwle(any(), anyInt(), anyLong())).thenReturn(15L);
+ when(mNativeWrapperMock.composePwle(any(), anyInt(), anyLong(), anyLong())).thenReturn(15L);
VibratorController controller = createController();
RampSegment[] primitives = new RampSegment[]{
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1,
/* startFrequencyHz= */ 100, /* endFrequencyHz= */ 200, /* duration= */ 10)
};
- assertEquals(15L, controller.on(primitives, 12));
+ assertEquals(15L, controller.on(primitives, 12, 45));
assertTrue(controller.isVibrating());
- verify(mNativeWrapperMock).composePwle(eq(primitives), eq(Braking.NONE), eq(12L));
+ verify(mNativeWrapperMock).composePwle(eq(primitives), eq(Braking.NONE), eq(12L), eq(45L));
}
@Test
public void on_withComposedPwleV2_performsEffect() {
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
- when(mNativeWrapperMock.composePwleV2(any(), anyLong())).thenReturn(15L);
+ when(mNativeWrapperMock.composePwleV2(any(), anyLong(), anyLong())).thenReturn(15L);
VibratorController controller = createController();
PwlePoint[] primitives = new PwlePoint[]{
new PwlePoint(/*amplitude=*/ 0, /*frequencyHz=*/ 100, /*timeMillis=*/ 0),
new PwlePoint(/*amplitude=*/ 1, /*frequencyHz=*/ 200, /*timeMillis=*/ 10)
};
- assertEquals(15L, controller.on(primitives, 12));
+ assertEquals(15L, controller.on(primitives, 12, 53));
assertTrue(controller.isVibrating());
- verify(mNativeWrapperMock).composePwleV2(eq(primitives), eq(12L));
+ verify(mNativeWrapperMock).composePwleV2(eq(primitives), eq(12L), eq(53L));
}
@Test
public void off_turnsOffVibrator() {
- when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));
+ when(mNativeWrapperMock.on(anyLong(), anyLong(), anyLong()))
+ .thenAnswer(args -> args.getArgument(0));
VibratorController controller = createController();
- controller.on(100, 1);
+ controller.on(100, 1, 1);
assertTrue(controller.isVibrating());
controller.off();
@@ -301,10 +305,11 @@
@Test
public void reset_turnsOffVibratorAndDisablesExternalControl() {
mockVibratorCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
- when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));
+ when(mNativeWrapperMock.on(anyLong(), anyLong(), anyLong()))
+ .thenAnswer(args -> args.getArgument(0));
VibratorController controller = createController();
- controller.on(100, 1);
+ controller.on(100, 1, 1);
assertTrue(controller.isVibrating());
controller.reset();
@@ -315,12 +320,13 @@
@Test
public void registerVibratorStateListener_callbacksAreTriggered() throws Exception {
- when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));
+ when(mNativeWrapperMock.on(anyLong(), anyLong(), anyLong()))
+ .thenAnswer(args -> args.getArgument(0));
VibratorController controller = createController();
controller.registerVibratorStateListener(mVibratorStateListenerMock);
- controller.on(10, 1);
- controller.on(100, 2);
+ controller.on(10, 1, 1);
+ controller.on(100, 2, 1);
controller.off();
controller.off();
@@ -334,19 +340,20 @@
@Test
public void unregisterVibratorStateListener_callbackNotTriggeredAfter() throws Exception {
- when(mNativeWrapperMock.on(anyLong(), anyLong())).thenAnswer(args -> args.getArgument(0));
+ when(mNativeWrapperMock.on(anyLong(), anyLong(), anyLong()))
+ .thenAnswer(args -> args.getArgument(0));
VibratorController controller = createController();
controller.registerVibratorStateListener(mVibratorStateListenerMock);
verify(mVibratorStateListenerMock).onVibrating(false);
- controller.on(10, 1);
+ controller.on(10, 1, 1);
verify(mVibratorStateListenerMock).onVibrating(true);
controller.unregisterVibratorStateListener(mVibratorStateListenerMock);
Mockito.clearInvocations(mVibratorStateListenerMock);
- controller.on(10, 1);
+ controller.on(10, 1, 1);
verifyNoMoreInteractions(mVibratorStateListenerMock);
}
diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java
index 3f34767..bd806b7 100644
--- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java
+++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java
@@ -118,11 +118,11 @@
}
@Override
- public long on(long milliseconds, long vibrationId) {
+ public long on(long milliseconds, long vibrationId, long stepId) {
recordEffectSegment(vibrationId, new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE,
/* frequencyHz= */ 0, (int) milliseconds));
applyLatency(mOnLatency);
- scheduleListener(milliseconds, vibrationId);
+ scheduleListener(milliseconds, vibrationId, stepId);
return milliseconds;
}
@@ -139,7 +139,7 @@
}
@Override
- public long perform(long effect, long strength, long vibrationId) {
+ public long perform(long effect, long strength, long vibrationId, long stepId) {
if (mSupportedEffects == null
|| Arrays.binarySearch(mSupportedEffects, (int) effect) < 0) {
return 0;
@@ -147,13 +147,13 @@
recordEffectSegment(vibrationId,
new PrebakedSegment((int) effect, false, (int) strength));
applyLatency(mOnLatency);
- scheduleListener(EFFECT_DURATION, vibrationId);
+ scheduleListener(EFFECT_DURATION, vibrationId, stepId);
return EFFECT_DURATION;
}
@Override
public long performVendorEffect(Parcel vendorData, long strength, float scale,
- float adaptiveScale, long vibrationId) {
+ float adaptiveScale, long vibrationId, long stepId) {
if ((mCapabilities & IVibrator.CAP_PERFORM_VENDOR_EFFECTS) == 0) {
return 0;
}
@@ -161,13 +161,13 @@
recordVendorEffect(vibrationId,
new VibrationEffect.VendorEffect(bundle, (int) strength, scale, adaptiveScale));
applyLatency(mOnLatency);
- scheduleListener(mVendorEffectDuration, vibrationId);
+ scheduleListener(mVendorEffectDuration, vibrationId, stepId);
// HAL has unknown duration for vendor effects.
return Long.MAX_VALUE;
}
@Override
- public long compose(PrimitiveSegment[] primitives, long vibrationId) {
+ public long compose(PrimitiveSegment[] primitives, long vibrationId, long stepId) {
if (mSupportedPrimitives == null) {
return 0;
}
@@ -182,12 +182,13 @@
recordEffectSegment(vibrationId, primitive);
}
applyLatency(mOnLatency);
- scheduleListener(duration, vibrationId);
+ scheduleListener(duration, vibrationId, stepId);
return duration;
}
@Override
- public long composePwle(RampSegment[] primitives, int braking, long vibrationId) {
+ public long composePwle(RampSegment[] primitives, int braking, long vibrationId,
+ long stepId) {
long duration = 0;
for (RampSegment primitive : primitives) {
duration += primitive.getDuration();
@@ -195,19 +196,19 @@
}
recordBraking(vibrationId, braking);
applyLatency(mOnLatency);
- scheduleListener(duration, vibrationId);
+ scheduleListener(duration, vibrationId, stepId);
return duration;
}
@Override
- public long composePwleV2(PwlePoint[] pwlePoints, long vibrationId) {
+ public long composePwleV2(PwlePoint[] pwlePoints, long vibrationId, long stepId) {
long duration = 0;
for (PwlePoint pwlePoint: pwlePoints) {
duration += pwlePoint.getTimeMillis();
recordEffectPwlePoint(vibrationId, pwlePoint);
}
applyLatency(mOnLatency);
- scheduleListener(duration, vibrationId);
+ scheduleListener(duration, vibrationId, stepId);
return duration;
}
@@ -263,8 +264,8 @@
}
}
- private void scheduleListener(long vibrationDuration, long vibrationId) {
- mHandler.postDelayed(() -> listener.onComplete(vibratorId, vibrationId),
+ private void scheduleListener(long vibrationDuration, long vibrationId, long stepId) {
+ mHandler.postDelayed(() -> listener.onComplete(vibratorId, vibrationId, stepId),
vibrationDuration + mCompletionCallbackDelay);
}
}
diff --git a/services/tests/wmtests/res/values/styles.xml b/services/tests/wmtests/res/values/styles.xml
index 6857ff99..6ded2b5 100644
--- a/services/tests/wmtests/res/values/styles.xml
+++ b/services/tests/wmtests/res/values/styles.xml
@@ -21,4 +21,14 @@
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
+
+ <style name="ActivityWindowStyleTest">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowShowWallpaper">true</item>
+ <item name="android:windowNoDisplay">true</item>
+ <item name="android:windowDisablePreview">true</item>
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+ <item name="android:windowSplashScreenBehavior">icon_preferred</item>
+ </style>
</resources>
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
index 8e2cea7..6d8a487 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
@@ -244,9 +244,6 @@
{"Meta + L -> Lock Homescreen", new int[]{META_KEY, KeyEvent.KEYCODE_L},
KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN, KeyEvent.KEYCODE_L,
META_ON},
- {"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N},
- KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES, KeyEvent.KEYCODE_N,
- META_ON | CTRL_ON},
{"Meta + Ctrl + DPAD_DOWN -> Enter desktop mode",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_DOWN},
KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE,
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index 32a3b7f..22c86eb 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -272,6 +272,19 @@
}
@Test
+ public void powerPress_withoutDreamManagerInternal_doesNotCrash() {
+ when(mDisplayPolicy.isAwake()).thenReturn(true);
+ mDreamManagerInternal = null;
+ initPhoneWindowManager();
+
+ // Power button pressed.
+ int eventTime = 0;
+ mPhoneWindowManager.powerPress(eventTime, 1, 0);
+
+ // verify no crash
+ }
+
+ @Test
public void powerPress_hubOrDreamOrSleep_hubAvailableLocks() {
when(mDisplayPolicy.isAwake()).thenReturn(true);
mContext.getTestablePermissions().setPermission(android.Manifest.permission.DEVICE_POWER,
@@ -352,5 +365,10 @@
WindowWakeUpPolicy getWindowWakeUpPolicy() {
return mock(WindowWakeUpPolicy.class);
}
+
+ @Override
+ DreamManagerInternal getDreamManagerInternal() {
+ return mDreamManagerInternal;
+ }
}
}
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 280e432..301a754 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -56,8 +56,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_PIP;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
@@ -921,12 +919,6 @@
// animation and AR#takeSceneTransitionInfo also clear the AR#mPendingOptions
assertNull(activity.takeSceneTransitionInfo());
assertNull(activity.getOptions());
-
- final AppTransition appTransition = activity.mDisplayContent.mAppTransition;
- spyOn(appTransition);
- activity.applyOptionsAnimation();
-
- verify(appTransition).overridePendingAppTransitionRemote(any());
}
@Test
@@ -992,6 +984,27 @@
assertEquals(persistentSavedState, activity.getPersistentSavedState());
}
+ @Test
+ public void testReadWindowStyle() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setActivityTheme(
+ com.android.frameworks.wmtests.R.style.ActivityWindowStyleTest).build();
+ assertTrue(activity.isNoDisplay());
+ assertTrue("Fill parent because showWallpaper", activity.mStyleFillsParent);
+
+ final ActivityRecord.WindowStyle style = mAtm.getWindowStyle(
+ activity.packageName, activity.info.theme, activity.mUserId);
+ assertNotNull(style);
+ assertTrue(style.isTranslucent());
+ assertTrue(style.isFloating());
+ assertTrue(style.showWallpaper());
+ assertTrue(style.noDisplay());
+ assertTrue(style.disablePreview());
+ assertTrue(style.optOutEdgeToEdge());
+ assertEquals(1 /* icon_preferred */, style.mSplashScreenBehavior);
+ assertEquals(style.noDisplay(), mAtm.mInternal.isNoDisplay(activity.packageName,
+ activity.info.theme, activity.mUserId));
+ }
+
/**
* Verify that activity finish request is not performed if activity is finishing or is in
* incorrect state.
@@ -1169,7 +1182,6 @@
FINISH_RESULT_REQUESTED, activity.finishIfPossible("test", false /* oomAdj */));
assertEquals(PAUSING, activity.getState());
verify(activity).setVisibility(eq(false));
- verify(activity.mDisplayContent).prepareAppTransition(eq(TRANSIT_CLOSE));
}
/**
@@ -1216,7 +1228,6 @@
activity.finishIfPossible("test", false /* oomAdj */);
verify(activity).setVisibility(eq(false));
- verify(activity.mDisplayContent).prepareAppTransition(eq(TRANSIT_CLOSE));
verify(activity.mDisplayContent, never()).executeAppTransition();
}
@@ -1233,7 +1244,6 @@
activity.finishIfPossible("test", false /* oomAdj */);
verify(activity, atLeast(1)).setVisibility(eq(false));
- verify(activity.mDisplayContent).prepareAppTransition(eq(TRANSIT_CLOSE));
verify(activity.mDisplayContent).executeAppTransition();
}
@@ -1254,7 +1264,6 @@
activity.finishIfPossible("test", false /* oomAdj */);
- verify(activity.mDisplayContent, never()).prepareAppTransition(eq(TRANSIT_CLOSE));
assertFalse(activity.inTransition());
// finishIfPossible -> completeFinishing -> addToFinishingAndWaitForIdle
@@ -2636,10 +2645,6 @@
@Presubmit
public void testGetOrientation() {
mDisplayContent.setIgnoreOrientationRequest(false);
- // ActivityBuilder will resume top activities and cause the activity been added into
- // opening apps list. Since this test is focus on the effect of visible on getting
- // orientation, we skip app transition to avoid interference.
- doNothing().when(mDisplayContent).prepareAppTransition(anyInt());
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
activity.setVisible(true);
@@ -2904,7 +2909,6 @@
sources.add(activity2);
doReturn(true).when(activity2).okToAnimate();
doReturn(true).when(activity2).isAnimating();
- assertTrue(activity2.applyAnimation(null, TRANSIT_OLD_ACTIVITY_OPEN, true, false, sources));
}
@Test
public void testTrackingStartingWindowThroughTrampoline() {
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 fbb123e..e081971 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -294,6 +294,14 @@
backNavigationInfo = startBackNavigation();
assertThat(typeToString(backNavigationInfo.getType()))
.isEqualTo(typeToString(BackNavigationInfo.TYPE_CROSS_ACTIVITY));
+
+ // reset drawing status, test previous activity has no process.
+ backNavigationInfo.onBackNavigationFinished(false);
+ mBackNavigationController.clearBackAnimations(true);
+ doReturn(false).when(testCase.recordBack).hasProcess();
+ backNavigationInfo = startBackNavigation();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index d5b9751..a99bc49 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -37,7 +37,6 @@
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
-import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
@@ -56,6 +55,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -63,9 +63,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -1742,8 +1739,6 @@
public void testFixedRotationWithPip() {
final DisplayContent displayContent = mDefaultDisplay;
displayContent.setIgnoreOrientationRequest(false);
- // Unblock the condition in PinnedTaskController#continueOrientationChangeIfNeeded.
- doNothing().when(displayContent).prepareAppTransition(anyInt());
// Make resume-top really update the activity state.
setBooted(mAtm);
clearInvocations(mWm);
@@ -1826,7 +1821,7 @@
.setTask(nonTopVisible.getTask()).setVisible(false)
.setActivityTheme(android.R.style.Theme_Translucent).build();
final TestTransitionPlayer player = registerTestTransitionPlayer();
- mDisplayContent.requestTransitionAndLegacyPrepare(WindowManager.TRANSIT_OPEN, 0);
+ mDisplayContent.requestTransitionAndLegacyPrepare(WindowManager.TRANSIT_OPEN, 0, null);
translucentTop.setVisibility(true);
mDisplayContent.updateOrientation();
assertEquals("Non-top visible activity must be portrait",
@@ -2373,33 +2368,6 @@
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
- public void testShowImeScreenshot() {
- final Task rootTask = createTask(mDisplayContent);
- final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
- final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
- final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
- activity).build();
- task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE);
- doReturn(true).when(task).okToAnimate();
- ArrayList<WindowContainer> sources = new ArrayList<>();
- sources.add(activity);
-
- mDisplayContent.setImeLayeringTarget(win);
- spyOn(mDisplayContent);
-
- // Expecting the IME screenshot only be attached when performing task closing transition.
- task.applyAnimation(null, TRANSIT_OLD_TASK_CLOSE, false /* enter */,
- false /* isVoiceInteraction */, sources);
- verify(mDisplayContent).showImeScreenshot();
-
- clearInvocations(mDisplayContent);
- activity.applyAnimation(null, TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE, false /* enter */,
- false /* isVoiceInteraction */, sources);
- verify(mDisplayContent, never()).showImeScreenshot();
- }
-
- @SetupWindows(addWindows = W_INPUT_METHOD)
- @Test
public void testShowImeScreenshot_removeCurSnapshotBeforeCreateNext() {
final Task rootTask = createTask(mDisplayContent);
final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
@@ -2427,32 +2395,6 @@
@UseTestDisplay(addWindows = {W_INPUT_METHOD})
@Test
- public void testRemoveImeScreenshot_whenTargetSurfaceWasInvisible() {
- final Task rootTask = createTask(mDisplayContent);
- final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
- final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
- final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
- activity).build();
- win.onSurfaceShownChanged(true);
- makeWindowVisible(win, mDisplayContent.mInputMethodWindow);
- task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE);
- doReturn(true).when(task).okToAnimate();
- ArrayList<WindowContainer> sources = new ArrayList<>();
- sources.add(activity);
-
- mDisplayContent.setImeLayeringTarget(win);
- mDisplayContent.setImeInputTarget(win);
- mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true);
- task.applyAnimation(null, TRANSIT_OLD_TASK_CLOSE, false /* enter */,
- false /* isVoiceInteraction */, sources);
- assertNotNull(mDisplayContent.mImeScreenshot);
-
- win.onSurfaceShownChanged(false);
- assertNull(mDisplayContent.mImeScreenshot);
- }
-
- @UseTestDisplay(addWindows = {W_INPUT_METHOD})
- @Test
public void testRemoveImeScreenshot_whenWindowRemoveImmediately() {
final Task rootTask = createTask(mDisplayContent);
final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
@@ -2751,55 +2693,77 @@
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
- public void testImeChildWindowFocusWhenImeLayeringTargetChanges() {
- final WindowState imeChildWindow = newWindowBuilder("imeChildWindow",
+ public void testImeChildWindowFocusWhenImeParentWindowChanges() {
+ final var imeChildWindow = newWindowBuilder("imeChildWindow",
TYPE_APPLICATION_ATTACHED_DIALOG).setParent(mImeWindow).build();
- makeWindowVisibleAndDrawn(imeChildWindow, mImeWindow);
- assertTrue(imeChildWindow.canReceiveKeys());
- mDisplayContent.setInputMethodWindowLocked(mImeWindow);
-
- // Verify imeChildWindow can be focused window if the next IME target requests IME visible.
- final WindowState imeAppTarget = newWindowBuilder("imeAppTarget",
- TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
- mDisplayContent.setImeLayeringTarget(imeAppTarget);
- spyOn(imeAppTarget);
- doReturn(true).when(imeAppTarget).isRequestedVisible(ime());
- assertEquals(imeChildWindow, mDisplayContent.findFocusedWindow());
-
- // Verify imeChildWindow doesn't be focused window if the next IME target does not
- // request IME visible.
- final WindowState nextImeAppTarget = newWindowBuilder("nextImeAppTarget",
- TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
- mDisplayContent.setImeLayeringTarget(nextImeAppTarget);
- assertNotEquals(imeChildWindow, mDisplayContent.findFocusedWindow());
+ doTestImeWindowFocusWhenImeParentWindowChanged(imeChildWindow);
}
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
- public void testImeMenuDialogFocusWhenImeLayeringTargetChanges() {
- final WindowState imeMenuDialog = newWindowBuilder("imeMenuDialog",
+ public void testImeDialogWindowFocusWhenImeParentWindowChanges() {
+ final var imeDialogWindow = newWindowBuilder("imeMenuDialog",
TYPE_INPUT_METHOD_DIALOG).build();
- makeWindowVisibleAndDrawn(imeMenuDialog, mImeWindow);
- assertTrue(imeMenuDialog.canReceiveKeys());
+ doTestImeWindowFocusWhenImeParentWindowChanged(imeDialogWindow);
+ }
+
+ @SetupWindows(addWindows = W_INPUT_METHOD)
+ @Test
+ public void testImeWindowFocusWhenImeParentWindowChanges() {
+ // Verify focusable, non-child IME windows.
+ final var otherImeWindow = newWindowBuilder("otherImeWindow",
+ TYPE_INPUT_METHOD).build();
+ doTestImeWindowFocusWhenImeParentWindowChanged(otherImeWindow);
+ }
+
+ private void doTestImeWindowFocusWhenImeParentWindowChanged(@NonNull WindowState window) {
+ makeWindowVisibleAndDrawn(window, mImeWindow);
+ assertTrue("Window canReceiveKeys", window.canReceiveKeys());
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
- // Verify imeMenuDialog can be focused window if the next IME target requests IME visible.
+ // Verify window can be focused if the IME parent is visible and the IME is visible.
final WindowState imeAppTarget = newWindowBuilder("imeAppTarget",
TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
mDisplayContent.setImeLayeringTarget(imeAppTarget);
- imeAppTarget.setRequestedVisibleTypes(ime());
- assertEquals(imeMenuDialog, mDisplayContent.findFocusedWindow());
+ mDisplayContent.updateImeInputAndControlTarget(imeAppTarget);
+ final var imeProvider = mDisplayContent.getInsetsStateController().getImeSourceProvider();
+ imeProvider.setImeShowing(true);
+ final var imeParentWindow = mDisplayContent.getImeParentWindow();
+ assertNotNull("IME parent window is not null", imeParentWindow);
+ assertTrue("IME parent window is visible", imeParentWindow.isVisibleRequested());
+ assertTrue("IME is visible", imeProvider.isImeShowing());
+ assertEquals("Window is the focused one", window, mDisplayContent.findFocusedWindow());
- // Verify imeMenuDialog doesn't be focused window if the next IME target is closing.
+ // Verify window can't be focused if the IME parent is not visible.
final WindowState nextImeAppTarget = newWindowBuilder("nextImeAppTarget",
TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
makeWindowVisibleAndDrawn(nextImeAppTarget);
- // Even if the app still requests IME, the ime dialog should not gain focus if the target
- // app is invisible.
- nextImeAppTarget.setRequestedVisibleTypes(ime());
- nextImeAppTarget.mActivityRecord.setVisibility(false);
+ // Change layering target but keep input target (and thus imeParent) the same.
mDisplayContent.setImeLayeringTarget(nextImeAppTarget);
- assertNotEquals(imeMenuDialog, mDisplayContent.findFocusedWindow());
+ // IME parent window is not visible, occluded by new layering target.
+ imeParentWindow.setVisibleRequested(false);
+ assertEquals("IME parent window did not change", imeParentWindow,
+ mDisplayContent.getImeParentWindow());
+ assertFalse("IME parent window is not visible", imeParentWindow.isVisibleRequested());
+ assertTrue("IME is visible", imeProvider.isImeShowing());
+ assertNotEquals("Window is not the focused one when imeParent is not visible", window,
+ mDisplayContent.findFocusedWindow());
+
+ // Verify window can be focused if the IME is not visible.
+ mDisplayContent.updateImeInputAndControlTarget(nextImeAppTarget);
+ imeProvider.setImeShowing(false);
+ final var nextImeParentWindow = mDisplayContent.getImeParentWindow();
+ assertNotNull("Next IME parent window is not null", nextImeParentWindow);
+ assertNotEquals("IME parent window changed", imeParentWindow, nextImeParentWindow);
+ assertTrue("Next IME parent window is visible", nextImeParentWindow.isVisibleRequested());
+ assertFalse("IME is not visible", imeProvider.isImeShowing());
+ if (window.isChildWindow()) {
+ assertNotEquals("Child window is not the focused on when the IME is not visible",
+ window, mDisplayContent.findFocusedWindow());
+ } else {
+ assertEquals("Window is the focused one when the IME is not visible",
+ window, mDisplayContent.findFocusedWindow());
+ }
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java
index db90c28..2d4101e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PresentationControllerTests.java
@@ -17,17 +17,21 @@
package com.android.server.wm;
import static android.view.Display.FLAG_PRESENTATION;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.window.flags.Flags.FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
+import android.annotation.NonNull;
import android.graphics.Rect;
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;
import android.view.DisplayInfo;
@@ -41,6 +45,7 @@
import androidx.test.filters.SmallTest;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,35 +58,100 @@
@RunWith(WindowTestRunner.class)
public class PresentationControllerTests extends WindowTestsBase {
+ TestTransitionPlayer mPlayer;
+
+ @Before
+ public void setUp() {
+ mPlayer = registerTestTransitionPlayer();
+ }
+
@EnableFlags(FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS)
@Test
- public void testPresentationHidesActivitiesBehind() {
+ public void testPresentationShowAndHide() {
+ final DisplayContent dc = createPresentationDisplay();
+ final ActivityRecord activity = createActivityRecord(createTask(dc));
+ assertTrue(activity.isVisible());
+
+ // Add a presentation window, which requests the activity to stop.
+ final WindowState window = addPresentationWindow(100000, dc.mDisplayId);
+ assertFalse(activity.isVisibleRequested());
+ assertTrue(activity.isVisible());
+ final Transition addTransition = window.mTransitionController.getCollectingTransition();
+ assertEquals(TRANSIT_OPEN, addTransition.mType);
+ assertTrue(addTransition.isInTransition(window));
+ assertTrue(addTransition.isInTransition(activity));
+
+ // Completing the transition makes the activity invisible.
+ completeTransition(addTransition, /*abortSync=*/ true);
+ assertFalse(activity.isVisible());
+
+ // Remove a Presentation window, which requests the activity to be resumed back.
+ window.removeIfPossible();
+ final Transition removeTransition = window.mTransitionController.getCollectingTransition();
+ assertEquals(TRANSIT_CLOSE, removeTransition.mType);
+ assertTrue(removeTransition.isInTransition(window));
+ assertTrue(removeTransition.isInTransition(activity));
+ assertTrue(activity.isVisibleRequested());
+ assertFalse(activity.isVisible());
+
+ // Completing the transition makes the activity visible.
+ completeTransition(removeTransition, /*abortSync=*/ false);
+ assertTrue(activity.isVisible());
+ }
+
+ @DisableFlags(FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS)
+ @Test
+ public void testPresentationShowAndHide_flagDisabled() {
+ final DisplayContent dc = createPresentationDisplay();
+ final ActivityRecord activity = createActivityRecord(createTask(dc));
+ assertTrue(activity.isVisible());
+
+ final WindowState window = addPresentationWindow(100000, dc.mDisplayId);
+ assertFalse(window.mTransitionController.isCollecting());
+ assertTrue(activity.isVisibleRequested());
+ assertTrue(activity.isVisible());
+
+ window.removeIfPossible();
+ assertFalse(window.mTransitionController.isCollecting());
+ assertTrue(activity.isVisibleRequested());
+ assertTrue(activity.isVisible());
+ assertFalse(window.isAttached());
+ }
+
+ private WindowState addPresentationWindow(int uid, int displayId) {
+ final Session session = createTestSession(mAtm, 1234 /* pid */, uid);
+ final int userId = UserHandle.getUserId(uid);
+ doReturn(true).when(mWm.mUmInternal).isUserVisible(eq(userId), eq(displayId));
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.TYPE_PRESENTATION);
+ final IWindow clientWindow = new TestIWindow();
+ final int res = mWm.addWindow(session, clientWindow, params, View.VISIBLE, displayId,
+ userId, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
+ new InsetsSourceControl.Array(), new Rect(), new float[1]);
+ assertTrue(res >= WindowManagerGlobal.ADD_OKAY);
+ final WindowState window = mWm.windowForClientLocked(session, clientWindow, false);
+ window.mHasSurface = true;
+ return window;
+ }
+
+ private DisplayContent createPresentationDisplay() {
final DisplayInfo displayInfo = new DisplayInfo();
displayInfo.copyFrom(mDisplayInfo);
displayInfo.flags = FLAG_PRESENTATION;
final DisplayContent dc = createNewDisplay(displayInfo);
final int displayId = dc.getDisplayId();
doReturn(dc).when(mWm.mRoot).getDisplayContentOrCreate(displayId);
- final ActivityRecord activity = createActivityRecord(createTask(dc));
- assertTrue(activity.isVisible());
+ return dc;
+ }
- doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());
- final int uid = 100000; // uid for non-system user
- final Session session = createTestSession(mAtm, 1234 /* pid */, uid);
- final int userId = UserHandle.getUserId(uid);
- doReturn(false).when(mWm.mUmInternal).isUserVisible(eq(userId), eq(displayId));
- final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.TYPE_PRESENTATION);
-
- final IWindow clientWindow = new TestIWindow();
- final int result = mWm.addWindow(session, clientWindow, params, View.VISIBLE, displayId,
- userId, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
- new InsetsSourceControl.Array(), new Rect(), new float[1]);
- assertTrue(result >= WindowManagerGlobal.ADD_OKAY);
- assertFalse(activity.isVisible());
-
- final WindowState window = mWm.windowForClientLocked(session, clientWindow, false);
- window.removeImmediately();
- assertTrue(activity.isVisible());
+ private void completeTransition(@NonNull Transition transition, boolean abortSync) {
+ final ActionChain chain = ActionChain.testFinish(transition);
+ if (abortSync) {
+ // Forcefully finishing the active sync for testing purpose.
+ mWm.mSyncEngine.abort(transition.getSyncId());
+ } else {
+ transition.onTransactionReady(transition.getSyncId(), mTransaction);
+ }
+ transition.finishTransition(chain);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 59335d3..3776b036 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -98,6 +98,7 @@
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.testutils.StubTransaction;
import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.window.flags.Flags;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
@@ -263,7 +264,7 @@
final DisplayManagerGlobal dmg = DisplayManagerGlobal.getInstance();
spyOn(dmg);
doNothing().when(dmg).registerDisplayListener(
- any(), any(Executor.class), anyLong(), anyString());
+ any(), any(Executor.class), anyLong(), anyString(), anyBoolean());
doNothing().when(dmg).registerTopologyListener(any(Executor.class), any(), anyString());
}
@@ -657,6 +658,13 @@
AppWarnings appWarnings = getAppWarningsLocked();
spyOn(appWarnings);
doNothing().when(appWarnings).onStartActivity(any());
+
+ if (Flags.trackSystemUiContextBeforeWms()) {
+ final Context uiContext = getUiContext();
+ spyOn(uiContext);
+ doNothing().when(uiContext).registerComponentCallbacks(any());
+ doNothing().when(uiContext).unregisterComponentCallbacks(any());
+ }
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index ccce57a..b1525cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -30,6 +30,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -39,6 +40,7 @@
import android.view.DisplayInfo;
import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry;
+import com.android.window.flags.Flags;
class TestDisplayContent extends DisplayContent {
@@ -79,6 +81,13 @@
WindowTestsBase.suppressInsetsAnimation(insetsPolicy.getPermanentControlTarget());
WindowTestsBase.suppressInsetsAnimation(insetsPolicy.getTransientControlTarget());
+ if (Flags.trackSystemUiContextBeforeWms()) {
+ final Context uiContext = getDisplayUiContext();
+ spyOn(uiContext);
+ doNothing().when(uiContext).registerComponentCallbacks(any());
+ doNothing().when(uiContext).unregisterComponentCallbacks(any());
+ }
+
// For devices that set the sysprop ro.bootanim.set_orientation_<display_id>
// See DisplayRotation#readDefaultDisplayRotation for context.
// Without that, meaning of height and width in context of the tests can be swapped if
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 2ee34d3..c0cb09f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -82,8 +82,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -104,7 +102,6 @@
import androidx.test.filters.SmallTest;
import com.android.internal.graphics.ColorUtils;
-import com.android.window.flags.Flags;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -683,7 +680,7 @@
app.onStartingWindowDrawn();
// The task appeared event should be deferred until transition ready.
assertFalse(task.taskAppearedReady());
- testPlayer.onTransactionReady(app.getSyncTransaction());
+ testPlayer.onTransactionReady();
assertTrue(task.taskAppearedReady());
assertTrue(playerProc.isRunningRemoteTransition());
assertTrue(controller.mRemotePlayer.reportRunning(delegateProc.getThread()));
@@ -1162,7 +1159,8 @@
screenDecor.updateSurfacePosition(mMockT);
assertEquals(prevPos, screenDecor.mLastSurfacePosition);
- final SurfaceControl.Transaction startTransaction = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction startTransaction = mTransaction;
+ clearInvocations(startTransaction);
final SurfaceControl.TransactionCommittedListener transactionCommittedListener =
onRotationTransactionReady(player, startTransaction);
@@ -1213,7 +1211,8 @@
assertFalse(statusBar.mToken.inTransition());
assertTrue(app.getTask().inTransition());
- final SurfaceControl.Transaction startTransaction = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction startTransaction = mTransaction;
+ clearInvocations(startTransaction);
final SurfaceControl leash = statusBar.mToken.getAnimationLeash();
doReturn(true).when(leash).isValid();
final SurfaceControl.TransactionCommittedListener transactionCommittedListener =
@@ -1287,7 +1286,8 @@
// Avoid DeviceStateController disturbing the test by triggering another rotation change.
doReturn(false).when(mDisplayContent).updateRotationUnchecked();
- onRotationTransactionReady(player, mWm.mTransactionFactory.get()).onTransactionCommitted();
+ clearInvocations(mTransaction);
+ onRotationTransactionReady(player, mTransaction).onTransactionCommitted();
assertEquals(ROTATION_ANIMATION_SEAMLESS, player.mLastReady.getChange(
mDisplayContent.mRemoteToken.toWindowContainerToken()).getRotationAnimation());
spyOn(navBarInsetsProvider);
@@ -1350,7 +1350,7 @@
mDisplayContent.setFixedRotationLaunchingAppUnchecked(home);
doReturn(true).when(home).hasFixedRotationTransform(any());
player.startTransition();
- player.onTransactionReady(mDisplayContent.getSyncTransaction());
+ player.onTransactionReady();
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
final RemoteDisplayChangeController displayChangeController = mDisplayContent
@@ -2009,21 +2009,6 @@
assertEquals(expectedBackgroundColor, info.getChanges().get(1).getBackgroundColor());
}
- @DisableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
- @Test
- public void testOverrideAnimationOptionsToInfoIfNecessary_disableAnimOptionsPerChange() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
- TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
- .makeCommonAnimOptions("testPackage");
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
- null /* finishCallback */);
-
- mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo);
-
- assertEquals(options, mInfo.getAnimationOptions());
- }
-
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_fromStyleAnimOptions() {
ActivityRecord r = initializeOverrideAnimationOptionsTest();
@@ -2049,7 +2034,6 @@
options, activityChange.getAnimationOptions());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_sceneAnimOptions() {
ActivityRecord r = initializeOverrideAnimationOptionsTest();
@@ -2075,7 +2059,6 @@
options, activityChange.getAnimationOptions());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_crossProfileAnimOptions() {
ActivityRecord r = initializeOverrideAnimationOptionsTest();
@@ -2103,7 +2086,6 @@
assertTrue(activityChange.hasFlags(FLAG_CROSS_PROFILE_OWNER_THUMBNAIL));
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_customAnimOptions() {
ActivityRecord r = initializeOverrideAnimationOptionsTest();
@@ -2136,7 +2118,6 @@
options.getBackgroundColor(), activityChange.getBackgroundColor());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_haveTaskFragmentAnimParams() {
ActivityRecord r = initializeOverrideAnimationOptionsTest();
@@ -2185,7 +2166,6 @@
options.getBackgroundColor(), activityChange.getBackgroundColor());
}
- @EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_customAnimOptionsWithTaskOverride() {
ActivityRecord r = initializeOverrideAnimationOptionsTest();
@@ -2415,7 +2395,6 @@
}
@Test
- @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS)
public void testMoveDisplayToTop() {
// Set up two displays, each of which has a task.
DisplayContent otherDisplay = createNewDisplay();
@@ -3071,8 +3050,11 @@
TestTransitionPlayer player, SurfaceControl.Transaction startTransaction) {
final ArgumentCaptor<SurfaceControl.TransactionCommittedListener> listenerCaptor =
ArgumentCaptor.forClass(SurfaceControl.TransactionCommittedListener.class);
- player.onTransactionReady(startTransaction);
- verify(startTransaction).addTransactionCommittedListener(any(), listenerCaptor.capture());
+ player.onTransactionReady();
+ // The startTransaction is from mWm.mTransactionFactory.get() in SyncGroup#finishNow.
+ // 2 times are from SyncGroup#finishNow and AsyncRotationController#setupStartTransaction.
+ verify(startTransaction, times(2)).addTransactionCommittedListener(
+ any(), listenerCaptor.capture());
return listenerCaptor.getValue();
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index cee98fb..4f310de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -30,8 +30,6 @@
import static android.view.WindowInsets.Type.systemOverlays;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -1121,7 +1119,6 @@
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
activity).build();
- task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE);
spyOn(win);
doReturn(true).when(task).okToAnimate();
ArrayList<WindowContainer> sources = new ArrayList<>();
@@ -1130,8 +1127,6 @@
// Simulate the task applying the exit transition, verify the main window of the task
// will be set the frozen insets state before the animation starts
activity.setVisibility(false);
- task.applyAnimation(null, TRANSIT_OLD_TASK_CLOSE, false /* enter */,
- false /* isVoiceInteraction */, sources);
verify(win).freezeInsetsState();
// Simulate the task transition finished.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 7f9e591..c641685 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -861,11 +861,9 @@
/** Creates a {@link DisplayContent} and adds it to the system. */
private DisplayContent createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy,
@Nullable SettingsEntry overrideSettings) {
- final DisplayContent display =
- new TestDisplayContent.Builder(mAtm, info)
- .setOverrideSettings(overrideSettings)
- .build();
- final DisplayContent dc = display.mDisplayContent;
+ final DisplayContent dc = new TestDisplayContent.Builder(mAtm, info)
+ .setOverrideSettings(overrideSettings)
+ .build();
// this display can show IME.
dc.mWmService.mDisplayWindowSettings.setDisplayImePolicy(dc, imePolicy);
return dc;
@@ -2161,13 +2159,14 @@
mOrganizer.startTransition(mLastTransit.getToken(), null);
}
- void onTransactionReady(SurfaceControl.Transaction t) {
- mLastTransit.onTransactionReady(mLastTransit.getSyncId(), t);
+ void onTransactionReady() {
+ // SyncGroup#finishNow -> Transition#onTransactionReady.
+ mController.mSyncEngine.abort(mLastTransit.getSyncId());
}
void start() {
startTransition();
- onTransactionReady(mock(SurfaceControl.Transaction.class));
+ onTransactionReady();
}
public void finish() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/WindowStyleCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/WindowStyleCacheTest.java
new file mode 100644
index 0000000..57a3401
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/WindowStyleCacheTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.utils;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.policy.AttributeCache;
+
+import org.junit.Test;
+
+/**
+ * Build/Install/Run:
+ * atest WmTests:WindowStyleCacheTest
+ */
+@SmallTest
+@Presubmit
+public class WindowStyleCacheTest {
+
+ @Test
+ public void testCache() {
+ final Context context = getInstrumentation().getContext();
+ AttributeCache.init(context);
+ final WindowStyleCache<TestStyle> cache = new WindowStyleCache<>(TestStyle::new);
+ final String packageName = context.getPackageName();
+ final int theme = com.android.frameworks.wmtests.R.style.ActivityWindowStyleTest;
+ final int userId = context.getUserId();
+ final TestStyle style = cache.get(packageName, theme, userId);
+ assertNotNull(style);
+ assertSame(style, cache.get(packageName, theme, userId));
+
+ cache.invalidatePackage(packageName);
+ assertNotSame(style, cache.get(packageName, theme, userId));
+ }
+
+ private static class TestStyle {
+ TestStyle(TypedArray array) {
+ }
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index ec4f7e1..4395b76 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -52,6 +52,7 @@
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.usb.UsbServiceDumpProto;
@@ -694,6 +695,11 @@
return (getCurrentFunctions() & UsbManager.usbFunctionsFromString(function)) != 0;
}
+ @Override
+ public boolean isUvcGadgetSupportEnabled() {
+ return SystemProperties.getBoolean("ro.usb.uvc.enabled", false);
+ }
+
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
@Override
public long getCurrentFunctions() {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java b/services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java
index 49ad461..df43ed9 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java
@@ -24,7 +24,6 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.telephony.flags.Flags;
import java.util.ArrayList;
import java.util.List;
@@ -119,28 +118,18 @@
private boolean checkCallStatus() {
List<SubscriptionInfo> infoList = mSubscriptionManager.getActiveSubscriptionInfoList();
if (infoList == null) return false;
- if (!Flags.enforceTelephonyFeatureMapping()) {
- return infoList.stream()
- .filter(s -> (s.getSubscriptionId()
- != SubscriptionManager.INVALID_SUBSCRIPTION_ID))
- .anyMatch(s -> isCallOngoingFromState(
- mTelephonyManager
- .createForSubscriptionId(s.getSubscriptionId())
- .getCallStateForSubscription()));
- } else {
- return infoList.stream()
- .filter(s -> (s.getSubscriptionId()
- != SubscriptionManager.INVALID_SUBSCRIPTION_ID))
- .anyMatch(s -> {
- try {
- return isCallOngoingFromState(mTelephonyManager
- .createForSubscriptionId(s.getSubscriptionId())
- .getCallStateForSubscription());
- } catch (UnsupportedOperationException e) {
- return false;
- }
- });
- }
+ return infoList.stream()
+ .filter(s -> (s.getSubscriptionId()
+ != SubscriptionManager.INVALID_SUBSCRIPTION_ID))
+ .anyMatch(s -> {
+ try {
+ return isCallOngoingFromState(mTelephonyManager
+ .createForSubscriptionId(s.getSubscriptionId())
+ .getCallStateForSubscription());
+ } catch (UnsupportedOperationException e) {
+ return false;
+ }
+ });
}
private void updateTelephonyListeners() {
diff --git a/startop/OWNERS b/startop/OWNERS
index 11d5ad0..3414a74 100644
--- a/startop/OWNERS
+++ b/startop/OWNERS
@@ -1,2 +1 @@
include platform/art:/OWNERS
-keunyoung@google.com
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1a932859..58833e8 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9786,7 +9786,6 @@
* <p>
* This config is empty by default.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE =
"carrier_supported_satellite_services_per_provider_bundle";
@@ -9826,7 +9825,6 @@
*
* The default value is false.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_SATELLITE_ATTACH_SUPPORTED_BOOL =
"satellite_attach_supported_bool";
@@ -9848,7 +9846,6 @@
* <p>
* The default value is 180 seconds.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT =
"satellite_connection_hysteresis_sec_int";
@@ -9863,7 +9860,6 @@
* See SignalStrength#MAX_LTE_RSRP and SignalStrength#MIN_LTE_RSRP. Any signal level outside
* these boundaries is considered invalid.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY =
"ntn_lte_rsrp_thresholds_int_array";
@@ -9883,7 +9879,6 @@
* This key is considered invalid if the format is violated. If the key is invalid or
* not configured, a default value set will apply.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY =
"ntn_lte_rsrq_thresholds_int_array";
@@ -9901,7 +9896,6 @@
* This key is considered invalid if the format is violated. If the key is invalid or
* not configured, a default value set will apply.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY =
"ntn_lte_rssnr_thresholds_int_array";
@@ -9926,7 +9920,6 @@
* If the key is invalid or not configured, a default value (RSRP = 1 << 0) will apply.
*
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT =
"parameters_used_for_ntn_lte_signal_bar_int";
@@ -10018,7 +10011,6 @@
*
* The default value is 7 days.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT =
"satellite_entitlement_status_refresh_days_int";
@@ -10029,7 +10021,6 @@
*
* The default value is false.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final String KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL =
"satellite_entitlement_supported_bool";
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 0c324e6..7de0a2a 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -209,7 +209,6 @@
/**
* MMS service
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int SERVICE_TYPE_MMS = 6;
/** @hide */
@@ -713,7 +712,6 @@
*
* @return {@code true} if network is a non-terrestrial network else {@code false}.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public boolean isNonTerrestrialNetwork() {
return mIsNonTerrestrialNetwork;
}
@@ -1198,7 +1196,6 @@
* else {@code false}.
* @return The builder.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public @NonNull Builder setIsNonTerrestrialNetwork(boolean isNonTerrestrialNetwork) {
mIsNonTerrestrialNetwork = isNonTerrestrialNetwork;
return this;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 127bbff..35dd8b2 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -16,7 +16,6 @@
package android.telephony;
-import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -36,7 +35,6 @@
import android.telephony.NetworkRegistrationInfo.NRState;
import android.text.TextUtils;
-import com.android.internal.telephony.flags.Flags;
import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
@@ -2262,7 +2260,6 @@
*
* @return {@code true} if device is connected to a non-terrestrial network else {@code false}.
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public boolean isUsingNonTerrestrialNetwork() {
synchronized (mNetworkRegistrationInfos) {
for (NetworkRegistrationInfo nri : mNetworkRegistrationInfos) {
diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java
index bb4ce6e..4411873 100644
--- a/telephony/java/android/telephony/TelephonyDisplayInfo.java
+++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java
@@ -16,15 +16,12 @@
package android.telephony;
-import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.OverrideNetworkType;
-import com.android.internal.telephony.flags.Flags;
-
import java.util.Objects;
/**
@@ -97,10 +94,8 @@
private final boolean mIsRoaming;
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
private final boolean mIsNtn;
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
private final boolean mIsSatelliteConstrainedData;
/**
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 22624e2..7eb1eb9 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -126,7 +126,6 @@
/** APN type for ENTERPRISE. */
public static final int TYPE_ENTERPRISE = ApnTypes.ENTERPRISE;
/** APN type for RCS (Rich Communication Services). */
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int TYPE_RCS = ApnTypes.RCS;
/** APN type for OEM_PAID networks (Automotive PANS) */
@FlaggedApi(Flags.FLAG_OEM_PAID_PRIVATE)
@@ -379,7 +378,6 @@
* modem components or carriers. Non-system apps should use the integer variants instead.
* @hide
*/
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@SystemApi
public static final String TYPE_RCS_STRING = "rcs";
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 100690d..1309654 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -755,7 +755,6 @@
* @hide
*/
@SystemApi
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2;
/**
@@ -1574,7 +1573,6 @@
* @hide
*/
@SystemApi
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1;
/**
@@ -1584,7 +1582,6 @@
* @hide
*/
@SystemApi
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2;
/** @hide */
@@ -2757,7 +2754,6 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void requestAttachEnabledForCarrier(int subId, boolean enableSatellite,
@NonNull @CallbackExecutor Executor executor,
@SatelliteResult @NonNull Consumer<Integer> resultListener) {
@@ -2794,7 +2790,6 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void requestIsAttachEnabledForCarrier(int subId,
@NonNull @CallbackExecutor Executor executor,
@NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
@@ -2822,7 +2817,6 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void addAttachRestrictionForCarrier(int subId,
@SatelliteCommunicationRestrictionReason int reason,
@NonNull @CallbackExecutor Executor executor,
@@ -2870,7 +2864,6 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
public void removeAttachRestrictionForCarrier(int subId,
@SatelliteCommunicationRestrictionReason int reason,
@NonNull @CallbackExecutor Executor executor,
@@ -2918,7 +2911,6 @@
@SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@SatelliteCommunicationRestrictionReason
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid subscription ID");
@@ -3317,7 +3309,6 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
@NonNull public List<String> getSatellitePlmnsForCarrier(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid subscription ID");
diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/transitions/flicker/LaunchTaskPortrait.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/transitions/flicker/LaunchTaskPortrait.kt
new file mode 100644
index 0000000..c82ce8a
--- /dev/null
+++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/transitions/flicker/LaunchTaskPortrait.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.service.transitions.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.server.wm.flicker.service.transitions.scenarios.LaunchTask
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class LaunchTaskPortrait : LaunchTask(Rotation.ROTATION_0) {
+ @ExpectedScenarios(["TASK_TRANSITION_SCENARIO", "OPEN_NEW_TASK_APP_SCENARIO"])
+ @Test
+ override fun openNewTask() = super.openNewTask()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig()
+ .use(FlickerServiceConfig.DEFAULT)
+ .use(TASK_TRANSITION_SCENARIO)
+ .use(OPEN_NEW_TASK_APP_SCENARIO)
+ }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/transitions/scenarios/LaunchTask.kt b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/transitions/scenarios/LaunchTask.kt
new file mode 100644
index 0000000..147477d
--- /dev/null
+++ b/tests/FlickerTests/FlickerService/src/com/android/server/wm/flicker/service/transitions/scenarios/LaunchTask.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.service.transitions.scenarios
+
+import android.app.Instrumentation
+import android.tools.Rotation
+import android.tools.flicker.AssertionInvocationGroup
+import android.tools.flicker.assertors.assertions.AppWindowCoversFullScreenAtStart
+import android.tools.flicker.assertors.assertions.AppWindowOnTopAtEnd
+import android.tools.flicker.assertors.assertions.AppWindowOnTopAtStart
+import android.tools.flicker.assertors.assertions.BackgroundShowsInTransition
+import android.tools.flicker.assertors.assertions.LayerBecomesInvisible
+import android.tools.flicker.assertors.assertions.LayerBecomesVisible
+import android.tools.flicker.assertors.assertions.LayerIsNeverVisible
+import android.tools.flicker.assertors.assertions.AppWindowIsNeverVisible
+import android.tools.flicker.config.AssertionTemplates
+import android.tools.flicker.config.FlickerConfigEntry
+import android.tools.flicker.config.ScenarioId
+import android.tools.flicker.config.appclose.Components.CLOSING_APPS
+import android.tools.flicker.config.appclose.Components.CLOSING_CHANGES
+import android.tools.flicker.config.applaunch.Components.OPENING_CHANGES
+import android.tools.flicker.config.common.Components.LAUNCHER
+import android.tools.flicker.config.common.Components.WALLPAPER
+import android.tools.flicker.extractors.TaggedCujTransitionMatcher
+import android.tools.flicker.extractors.TaggedScenarioExtractorBuilder
+import android.tools.flicker.rules.ChangeDisplayOrientationRule
+import android.tools.traces.events.CujType
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+
+
+/**
+ * This tests performs a transition between tasks
+ */
+abstract class LaunchTask(val rotation: Rotation = Rotation.ROTATION_0) {
+ protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val wmHelper = WindowManagerStateHelper(instrumentation)
+ private val device = UiDevice.getInstance(instrumentation)
+ private val tapl = LauncherInstrumentation()
+
+ private val launchNewTaskApp = NewTasksAppHelper(instrumentation)
+
+ @Before
+ fun setup() {
+ tapl.setEnableRotation(true)
+ ChangeDisplayOrientationRule.setRotation(rotation)
+ tapl.setExpectedRotation(rotation.value)
+ launchNewTaskApp.launchViaIntent(wmHelper)
+ }
+
+ @Test
+ open fun openNewTask() {
+ launchNewTaskApp.openNewTask(device, wmHelper)
+ }
+
+ @After
+ fun tearDown() {
+ launchNewTaskApp.exit(wmHelper)
+ }
+
+ companion object {
+ /**
+ * General task transition scenario that can be reused for any trace
+ */
+ val TASK_TRANSITION_SCENARIO =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("TASK_TRANSITION_SCENARIO"),
+ extractor = TaggedScenarioExtractorBuilder()
+ .setTargetTag(CujType.CUJ_DEFAULT_TASK_TO_TASK_ANIMATION)
+ .setTransitionMatcher(
+ TaggedCujTransitionMatcher(associatedTransitionRequired = true)
+ )
+ .build(),
+ assertions = listOf(
+ // Opening changes replace the closing ones
+ LayerBecomesInvisible(CLOSING_CHANGES),
+ AppWindowOnTopAtStart(CLOSING_CHANGES),
+ LayerBecomesVisible(OPENING_CHANGES),
+ AppWindowOnTopAtEnd(OPENING_CHANGES),
+
+ // There is a background color and it's covering the transition area
+ BackgroundShowsInTransition(CLOSING_CHANGES)
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING })
+ )
+
+ /**
+ * Scenario that is making assertions that are valid for the new task app but that do not
+ * apply to other task transitions in general
+ */
+ val OPEN_NEW_TASK_APP_SCENARIO =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("OPEN_NEW_TASK_APP_SCENARIO"),
+ extractor = TaggedScenarioExtractorBuilder()
+ .setTargetTag(CujType.CUJ_DEFAULT_TASK_TO_TASK_ANIMATION)
+ .setTransitionMatcher(
+ TaggedCujTransitionMatcher(associatedTransitionRequired = true)
+ )
+ .build(),
+ assertions = AssertionTemplates.COMMON_ASSERTIONS +
+ listOf(
+ // Wallpaper and launcher never visible
+ LayerIsNeverVisible(WALLPAPER, mustExist = true),
+ LayerIsNeverVisible(LAUNCHER, mustExist = true),
+ AppWindowIsNeverVisible(LAUNCHER, mustExist = true),
+ // App window covers the display at start
+ AppWindowCoversFullScreenAtStart(CLOSING_APPS)
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING })
+ )
+ }
+}
\ No newline at end of file
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index a2f6f00..eac4267 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -160,7 +160,7 @@
testLooper = TestLooper()
service =
InputManagerService(object : InputManagerService.Injector(
- context, testLooper.looper, uEventManager) {
+ context, testLooper.looper, testLooper.looper, uEventManager) {
override fun getNativeService(
service: InputManagerService?
): NativeInputManagerService {
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index 88e8496..c666fb7 100644
--- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -207,7 +207,7 @@
private fun setupKeyGestureController() {
keyGestureController =
- KeyGestureController(context, testLooper.looper, inputDataStore)
+ KeyGestureController(context, testLooper.looper, testLooper.looper, inputDataStore)
Mockito.`when`(iInputManager.getAppLaunchBookmarks())
.thenReturn(keyGestureController.appLaunchBookmarks)
keyGestureController.systemRunning()
@@ -371,18 +371,6 @@
intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
),
TestData(
- "META + CTRL + N -> Open Notes",
- intArrayOf(
- KeyEvent.KEYCODE_META_LEFT,
- KeyEvent.KEYCODE_CTRL_LEFT,
- KeyEvent.KEYCODE_N
- ),
- KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES,
- intArrayOf(KeyEvent.KEYCODE_N),
- KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
- intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
- ),
- TestData(
"META + S -> Take Screenshot",
intArrayOf(
KeyEvent.KEYCODE_META_LEFT,
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
index e294da1..3556406 100644
--- a/tests/Internal/Android.bp
+++ b/tests/Internal/Android.bp
@@ -45,6 +45,7 @@
"junit",
"androidx.test.rules",
"platform-test-annotations",
+ "truth",
],
manifest: "ApplicationSharedMemoryTest32/AndroidManifest.xml",
test_config: "ApplicationSharedMemoryTest32/AndroidTest.xml",
diff --git a/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java b/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java
index d03ad5c..5ce0ede 100644
--- a/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java
+++ b/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java
@@ -16,24 +16,24 @@
package com.android.internal.os;
-import java.io.IOException;
+import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.fail;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-import org.junit.Before;
import java.io.FileDescriptor;
+import java.io.IOException;
/** Tests for {@link TimeoutRecord}. */
@SmallTest
@@ -77,6 +77,8 @@
try {
instance.setLatestNetworkTimeUnixEpochMillisAtZeroElapsedRealtimeMillis(17);
fail("Attempted mutation in an app process should throw");
+ instance.writeSystemFeaturesCache(new int[] {1, 2, 3, 4, 5});
+ fail("Attempted feature mutation in an app process should throw");
} catch (Exception expected) {
}
}
@@ -121,4 +123,56 @@
} catch (Exception expected) {
}
}
+
+ /** If system feature caching is enabled, it should be auto-written into app shared memory. */
+ @Test
+ public void canReadSystemFeatures() throws IOException {
+ assumeTrue(android.content.pm.Flags.cacheSdkSystemFeatures());
+ ApplicationSharedMemory instance = ApplicationSharedMemory.getInstance();
+ assertThat(instance.readSystemFeaturesCache()).isNotEmpty();
+ }
+
+ @Test
+ public void systemFeaturesShareMemory() throws IOException {
+ ApplicationSharedMemory instance1 = ApplicationSharedMemory.create();
+
+ int[] featureVersions = new int[] {1, 2, 3, 4, 5};
+ instance1.writeSystemFeaturesCache(featureVersions);
+ assertThat(featureVersions).isEqualTo(instance1.readSystemFeaturesCache());
+
+ ApplicationSharedMemory instance2 =
+ ApplicationSharedMemory.fromFileDescriptor(
+ instance1.getReadOnlyFileDescriptor(), /* mutable= */ false);
+ assertThat(featureVersions).isEqualTo(instance2.readSystemFeaturesCache());
+ }
+
+ @Test
+ public void systemFeaturesAreWriteOnce() throws IOException {
+ ApplicationSharedMemory instance1 = ApplicationSharedMemory.create();
+
+ try {
+ instance1.writeSystemFeaturesCache(new int[5000]);
+ fail("Cannot write an overly large system feature version buffer.");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ int[] featureVersions = new int[] {1, 2, 3, 4, 5};
+ instance1.writeSystemFeaturesCache(featureVersions);
+
+ int[] newFeatureVersions = new int[] {1, 2, 3, 4, 5, 6, 7};
+ try {
+ instance1.writeSystemFeaturesCache(newFeatureVersions);
+ fail("Cannot update system features after first write.");
+ } catch (IllegalStateException expected) {
+ }
+
+ ApplicationSharedMemory instance2 =
+ ApplicationSharedMemory.fromFileDescriptor(
+ instance1.getReadOnlyFileDescriptor(), /* mutable= */ false);
+ try {
+ instance2.writeSystemFeaturesCache(newFeatureVersions);
+ fail("Cannot update system features for read-only ashmem.");
+ } catch (IllegalStateException expected) {
+ }
+ }
}
diff --git a/tests/PackageWatchdog/Android.bp b/tests/PackageWatchdog/Android.bp
index 8be74eacc..16c6e3b 100644
--- a/tests/PackageWatchdog/Android.bp
+++ b/tests/PackageWatchdog/Android.bp
@@ -26,12 +26,13 @@
name: "PackageWatchdogTest",
srcs: ["src/**/*.java"],
static_libs: [
- "junit",
- "mockito-target-extended-minus-junit4",
+ "PlatformProperties",
+ "androidx.test.rules",
+ "androidx.test.runner",
"flag-junit",
"frameworks-base-testutils",
- "androidx.test.rules",
- "PlatformProperties",
+ "junit",
+ "mockito-target-extended-minus-junit4",
"services.core",
"services.net",
"truth",
@@ -49,5 +50,9 @@
"libstaticjvmtiagent",
],
platform_apis: true,
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "mts-crashrecovery",
+ ],
+ min_sdk_version: "36",
}
diff --git a/tests/PackageWatchdog/AndroidManifest.xml b/tests/PackageWatchdog/AndroidManifest.xml
index 540edb4..334d50f 100644
--- a/tests/PackageWatchdog/AndroidManifest.xml
+++ b/tests/PackageWatchdog/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tests.packagewatchdog" >
+ package="com.android.server" >
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
@@ -23,6 +23,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.tests.packagewatchdog"
- android:label="PackageWatchdog Test"/>
+ android:targetPackage="com.android.server"
+ android:label="PackageWatchdog Test"/>
</manifest>
diff --git a/tests/PackageWatchdog/AndroidTest.xml b/tests/PackageWatchdog/AndroidTest.xml
new file mode 100644
index 0000000..45a88cd
--- /dev/null
+++ b/tests/PackageWatchdog/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?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.
+ -->
+<configuration description="Runs PackageWatchdog Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="PackageWatchdogTest.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-tag" value="PackageWatchdogTest" />
+
+ <!-- Only run this tests in MTS if the Crashrecovery Mainline module is installed. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.crashrecovery" />
+ </object>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.server" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
index 4c16a75..c2ab055 100644
--- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
@@ -133,7 +133,6 @@
@Before
public void setUp() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
MockitoAnnotations.initMocks(this);
new File(InstrumentationRegistry.getContext().getFilesDir(),
"package-watchdog.xml").delete();
@@ -766,8 +765,6 @@
watchdog.notifyPackageFailure(packages, failureReason);
}
mTestLooper.dispatchAll();
- if (Flags.recoverabilityDetection()) {
- moveTimeForwardAndDispatch(watchdog.DEFAULT_MITIGATION_WINDOW_MS);
- }
+ moveTimeForwardAndDispatch(watchdog.DEFAULT_MITIGATION_WINDOW_MS);
}
}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 1c50cb1..b827484 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -150,7 +150,6 @@
@Before
public void setUp() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
MockitoAnnotations.initMocks(this);
new File(InstrumentationRegistry.getContext().getFilesDir(),
"package-watchdog.xml").delete();
@@ -480,60 +479,6 @@
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
}
-
- /**
- * Test package failure and notifies only least impact observers.
- */
- @Test
- public void testPackageFailureNotifyAllDifferentImpacts() throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- PackageWatchdog watchdog = createWatchdog();
- TestObserver observerNone = new TestObserver(OBSERVER_NAME_1,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_0);
- TestObserver observerHigh = new TestObserver(OBSERVER_NAME_2,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
- TestObserver observerMid = new TestObserver(OBSERVER_NAME_3,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
- TestObserver observerLow = new TestObserver(OBSERVER_NAME_4,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
-
- // Start observing for all impact observers
- watchdog.registerHealthObserver(mTestExecutor, observerNone);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B, APP_C, APP_D),
- SHORT_DURATION, observerNone);
- watchdog.registerHealthObserver(mTestExecutor, observerHigh);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B, APP_C), SHORT_DURATION,
- observerHigh);
- watchdog.registerHealthObserver(mTestExecutor, observerMid);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B), SHORT_DURATION,
- observerMid);
- watchdog.registerHealthObserver(mTestExecutor, observerLow);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observerLow);
-
- // Then fail all apps above the threshold
- raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
- new VersionedPackage(APP_B, VERSION_CODE),
- new VersionedPackage(APP_C, VERSION_CODE),
- new VersionedPackage(APP_D, VERSION_CODE)),
- PackageWatchdog.FAILURE_REASON_UNKNOWN);
-
- // Verify least impact observers are notifed of package failures
- List<String> observerNonePackages = observerNone.mMitigatedPackages;
- List<String> observerHighPackages = observerHigh.mMitigatedPackages;
- List<String> observerMidPackages = observerMid.mMitigatedPackages;
- List<String> observerLowPackages = observerLow.mMitigatedPackages;
-
- // APP_D failure observed by only observerNone is not caught cos its impact is none
- assertThat(observerNonePackages).isEmpty();
- // APP_C failure is caught by observerHigh cos it's the lowest impact observer
- assertThat(observerHighPackages).containsExactly(APP_C);
- // APP_B failure is caught by observerMid cos it's the lowest impact observer
- assertThat(observerMidPackages).containsExactly(APP_B);
- // APP_A failure is caught by observerLow cos it's the lowest impact observer
- assertThat(observerLowPackages).containsExactly(APP_A);
- }
-
@Test
public void testPackageFailureNotifyAllDifferentImpactsRecoverability() throws Exception {
PackageWatchdog watchdog = createWatchdog();
@@ -583,84 +528,6 @@
assertThat(observerLowPackages).containsExactly(APP_A);
}
- /**
- * Test package failure and least impact observers are notified successively.
- * State transistions:
- *
- * <ul>
- * <li>(observer1:low, observer2:mid) -> {observer1}
- * <li>(observer1:high, observer2:mid) -> {observer2}
- * <li>(observer1:high, observer2:none) -> {observer1}
- * <li>(observer1:none, observer2:none) -> {}
- * <ul>
- */
- @Test
- public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- PackageWatchdog watchdog = createWatchdog();
- TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
- TestObserver observerSecond = new TestObserver(OBSERVER_NAME_2,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
-
- // Start observing for observerFirst and observerSecond with failure handling
- watchdog.registerHealthObserver(mTestExecutor, observerFirst);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observerFirst);
- watchdog.registerHealthObserver(mTestExecutor, observerSecond);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observerSecond);
-
- // Then fail APP_A above the threshold
- raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
- PackageWatchdog.FAILURE_REASON_UNKNOWN);
-
- // Verify only observerFirst is notifed
- assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
- assertThat(observerSecond.mMitigatedPackages).isEmpty();
-
- // After observerFirst handles failure, next action it has is high impact
- observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_100;
- observerFirst.mMitigatedPackages.clear();
- observerSecond.mMitigatedPackages.clear();
-
- // Then fail APP_A again above the threshold
- raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
- PackageWatchdog.FAILURE_REASON_UNKNOWN);
-
- // Verify only observerSecond is notifed cos it has least impact
- assertThat(observerSecond.mMitigatedPackages).containsExactly(APP_A);
- assertThat(observerFirst.mMitigatedPackages).isEmpty();
-
- // After observerSecond handles failure, it has no further actions
- observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
- observerFirst.mMitigatedPackages.clear();
- observerSecond.mMitigatedPackages.clear();
-
- // Then fail APP_A again above the threshold
- raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
- PackageWatchdog.FAILURE_REASON_UNKNOWN);
-
- // Verify only observerFirst is notifed cos it has the only action
- assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
- assertThat(observerSecond.mMitigatedPackages).isEmpty();
-
- // After observerFirst handles failure, it too has no further actions
- observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
- observerFirst.mMitigatedPackages.clear();
- observerSecond.mMitigatedPackages.clear();
-
- // Then fail APP_A again above the threshold
- raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
- PackageWatchdog.FAILURE_REASON_UNKNOWN);
-
- // Verify no observer is notified cos no actions left
- assertThat(observerFirst.mMitigatedPackages).isEmpty();
- assertThat(observerSecond.mMitigatedPackages).isEmpty();
- }
-
@Test
public void testPackageFailureNotifyLeastImpactSuccessivelyRecoverability() throws Exception {
PackageWatchdog watchdog = createWatchdog();
@@ -727,34 +594,6 @@
assertThat(observerSecond.mMitigatedPackages).isEmpty();
}
- /**
- * Test package failure and notifies only one observer even with observer impact tie.
- */
- @Test
- public void testPackageFailureNotifyOneSameImpact() throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- PackageWatchdog watchdog = createWatchdog();
- TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
- TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
-
- // Start observing for observer1 and observer2 with failure handling
- watchdog.registerHealthObserver(mTestExecutor, observer2);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer2);
- watchdog.registerHealthObserver(mTestExecutor, observer1);
- watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
-
- // Then fail APP_A above the threshold
- raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
- PackageWatchdog.FAILURE_REASON_UNKNOWN);
-
- // Verify only one observer is notifed
- assertThat(observer1.mMitigatedPackages).containsExactly(APP_A);
- assertThat(observer2.mMitigatedPackages).isEmpty();
- }
-
@Test
public void testPackageFailureNotifyOneSameImpactRecoverabilityDetection() throws Exception {
PackageWatchdog watchdog = createWatchdog();
@@ -1015,27 +854,6 @@
@Test
@RequiresFlagsDisabled(Flags.FLAG_REFACTOR_CRASHRECOVERY)
- public void testNetworkStackFailure() {
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- final PackageWatchdog wd = createWatchdog();
-
- // Start observing with failure handling
- TestObserver observer = new TestObserver(OBSERVER_NAME_1,
- PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
- wd.startExplicitHealthCheck(Collections.singletonList(APP_A), SHORT_DURATION, observer);
-
- // Notify of NetworkStack failure
- mConnectivityModuleCallbackCaptor.getValue().onNetworkStackFailure(APP_A);
-
- // Run handler so package failures are dispatched to observers
- mTestLooper.dispatchAll();
-
- // Verify the NetworkStack observer is notified
- assertThat(observer.mMitigatedPackages).containsExactly(APP_A);
- }
-
- @Test
- @RequiresFlagsDisabled(Flags.FLAG_REFACTOR_CRASHRECOVERY)
public void testNetworkStackFailureRecoverabilityDetection() {
final PackageWatchdog wd = createWatchdog();
@@ -1270,21 +1088,6 @@
assertThat(persistentObserver.mHealthCheckFailedPackages).isEmpty();
}
-
- /** Ensure that boot loop mitigation is done when the number of boots meets the threshold. */
- @Test
- public void testBootLoopDetection_meetsThreshold() {
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- PackageWatchdog watchdog = createWatchdog();
- TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
- watchdog.registerHealthObserver(mTestExecutor, bootObserver);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
- watchdog.noteBoot();
- }
- mTestLooper.dispatchAll();
- assertThat(bootObserver.mitigatedBootLoop()).isTrue();
- }
-
@Test
public void testBootLoopDetection_meetsThresholdRecoverability() {
PackageWatchdog watchdog = createWatchdog();
@@ -1330,27 +1133,6 @@
assertThat(bootObserver.mitigatedBootLoop()).isFalse();
}
- /**
- * Ensure that boot loop mitigation is done for the observer with the lowest user impact
- */
- @Test
- public void testBootLoopMitigationDoneForLowestUserImpact() {
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- PackageWatchdog watchdog = createWatchdog();
- TestObserver bootObserver1 = new TestObserver(OBSERVER_NAME_1);
- bootObserver1.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
- TestObserver bootObserver2 = new TestObserver(OBSERVER_NAME_2);
- bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
- watchdog.registerHealthObserver(mTestExecutor, bootObserver1);
- watchdog.registerHealthObserver(mTestExecutor, bootObserver2);
- for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
- watchdog.noteBoot();
- }
- mTestLooper.dispatchAll();
- assertThat(bootObserver1.mitigatedBootLoop()).isTrue();
- assertThat(bootObserver2.mitigatedBootLoop()).isFalse();
- }
-
@Test
public void testBootLoopMitigationDoneForLowestUserImpactRecoverability() {
PackageWatchdog watchdog = createWatchdog();
@@ -1368,32 +1150,6 @@
assertThat(bootObserver2.mitigatedBootLoop()).isFalse();
}
- /**
- * Ensure that the correct mitigation counts are sent to the boot loop observer.
- */
- @Test
- public void testMultipleBootLoopMitigation() {
- mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
- PackageWatchdog watchdog = createWatchdog();
- TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
- watchdog.registerHealthObserver(mTestExecutor, bootObserver);
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; j++) {
- watchdog.noteBoot();
- }
- }
-
- moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; j++) {
- watchdog.noteBoot();
- }
- }
- mTestLooper.dispatchAll();
- assertThat(bootObserver.mBootMitigationCounts).isEqualTo(List.of(1, 2, 3, 4, 1, 2, 3, 4));
- }
-
@Test
public void testMultipleBootLoopMitigationRecoverabilityLowImpact() {
PackageWatchdog watchdog = createWatchdog();
@@ -1800,9 +1556,7 @@
watchdog.notifyPackageFailure(packages, failureReason);
}
mTestLooper.dispatchAll();
- if (Flags.recoverabilityDetection()) {
- moveTimeForwardAndDispatch(watchdog.DEFAULT_MITIGATION_WINDOW_MS);
- }
+ moveTimeForwardAndDispatch(watchdog.DEFAULT_MITIGATION_WINDOW_MS);
}
private PackageWatchdog createWatchdog() {
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
index a0fcfc5..1e41886 100644
--- a/tests/SoundTriggerTestApp/OWNERS
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -1,2 +1 @@
include /media/java/android/media/soundtrigger/OWNERS
-mdooley@google.com
diff --git a/tests/Tracing/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java
index be0c7da..e62a89b 100644
--- a/tests/Tracing/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java
+++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java
@@ -19,6 +19,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.endsWith;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.times;
@@ -157,13 +158,15 @@
cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out,
FileDescriptor.err, new String[] { "logcat", "enable", "MY_GROUP" });
- Mockito.verify(mProtoLogConfigurationService).enableProtoLogToLogcat("MY_GROUP");
+ Mockito.verify(mProtoLogConfigurationService)
+ .enableProtoLogToLogcat(Mockito.any(), eq("MY_GROUP"));
cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out,
FileDescriptor.err,
new String[] { "logcat", "enable", "MY_GROUP", "MY_OTHER_GROUP" });
Mockito.verify(mProtoLogConfigurationService)
- .enableProtoLogToLogcat("MY_GROUP", "MY_OTHER_GROUP");
+ .enableProtoLogToLogcat(Mockito.any(),
+ eq("MY_GROUP"), eq("MY_OTHER_GROUP"));
}
@Test
@@ -173,13 +176,15 @@
cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out,
FileDescriptor.err, new String[] { "logcat", "disable", "MY_GROUP" });
- Mockito.verify(mProtoLogConfigurationService).disableProtoLogToLogcat("MY_GROUP");
+ Mockito.verify(mProtoLogConfigurationService)
+ .disableProtoLogToLogcat(Mockito.any(), eq("MY_GROUP"));
cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out,
FileDescriptor.err,
new String[] { "logcat", "disable", "MY_GROUP", "MY_OTHER_GROUP" });
Mockito.verify(mProtoLogConfigurationService)
- .disableProtoLogToLogcat("MY_GROUP", "MY_OTHER_GROUP");
+ .disableProtoLogToLogcat(Mockito.any(),
+ eq("MY_GROUP"), eq("MY_OTHER_GROUP"));
}
@Test
diff --git a/tests/Tracing/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java
index 3be7251..1f3f91e 100644
--- a/tests/Tracing/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java
+++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java
@@ -62,6 +62,7 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.List;
/**
@@ -234,7 +235,7 @@
service.registerClient(mMockClient, args);
Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
- service.enableProtoLogToLogcat(TEST_GROUP);
+ service.enableProtoLogToLogcat(Mockito.mock(PrintWriter.class), TEST_GROUP);
Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue();
Mockito.verify(mMockClient).toggleLogcat(eq(true),
@@ -251,7 +252,7 @@
service.registerClient(mMockClient, args);
Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue();
- service.disableProtoLogToLogcat(TEST_GROUP);
+ service.disableProtoLogToLogcat(Mockito.mock(PrintWriter.class), TEST_GROUP);
Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
Mockito.verify(mMockClient).toggleLogcat(eq(false),
@@ -269,7 +270,7 @@
service.registerClient(mMockClient, args);
Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
- service.enableProtoLogToLogcat(OTHER_TEST_GROUP);
+ service.enableProtoLogToLogcat(Mockito.mock(PrintWriter.class), OTHER_TEST_GROUP);
Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isFalse();
Mockito.verify(mMockClient, never()).toggleLogcat(anyBoolean(), any());
@@ -280,7 +281,7 @@
final ProtoLogConfigurationService service = new ProtoLogConfigurationServiceImpl();
Truth.assertThat(service.getGroups()).asList().doesNotContain(TEST_GROUP);
- service.enableProtoLogToLogcat(TEST_GROUP);
+ service.enableProtoLogToLogcat(Mockito.mock(PrintWriter.class), TEST_GROUP);
Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue();
final RegisterClientArgs args = new RegisterClientArgs();
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index 1273826..8cd89ce 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -273,7 +273,7 @@
messages.add(message);
}
- // Repost all Messages back to the queuewith a new time.
+ // Repost all Messages back to the queue with a new time.
while (true) {
Message message = messages.poll();
if (message == null) {
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index ff4d8ef..0a5cb1f 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -2649,6 +2649,10 @@
".mpg", ".mpeg", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", ".wma", ".wmv",
".webm", ".mkv"});
+ if (options_.no_compress_fonts) {
+ options_.extensions_to_not_compress.insert({".ttf", ".otf", ".ttc"});
+ }
+
// Turn off auto versioning for static-libs.
if (context.GetPackageType() == PackageType::kStaticLib) {
options_.no_auto_version = true;
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 2f17853..9779788 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -78,6 +78,7 @@
bool use_sparse_encoding = false;
std::unordered_set<std::string> extensions_to_not_compress;
std::optional<std::regex> regex_to_not_compress;
+ bool no_compress_fonts = false;
FeatureFlagValues feature_flag_values;
// Static lib options.
@@ -300,6 +301,14 @@
"use the '$' symbol for end of line. Uses a case-sensitive ECMAScript"
"regular expression grammar.",
&no_compress_regex);
+ AddOptionalSwitch("--no-compress-fonts",
+ "Do not compress files with common extensions for fonts.\n"
+ "This allows loading fonts directly from the APK, without needing to\n"
+ "decompress them first. Loading fonts will be faster and use less memory.\n"
+ "The downside is that the APK will be larger.\n"
+ "Passing this flag is functionally equivalent to passing the following flags:\n"
+ "-0 .ttf -0 .otf -0 .ttc",
+ &options_.no_compress_fonts);
AddOptionalSwitch("--warn-manifest-validation",
"Treat manifest validation errors as warnings.",
&options_.manifest_fixer_options.warn_validation);
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index a2dc8f8..41f8e250 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -98,6 +98,7 @@
WriteFile(GetTestPath("assets/test.txt"), content);
WriteFile(GetTestPath("assets/test.hello.txt"), content);
WriteFile(GetTestPath("assets/test.hello.xml"), content);
+ WriteFile(GetTestPath("assets/fonts/myfont.ttf"), content);
const std::string out_apk = GetTestPath("out.apk");
std::vector<std::string> link_args = {
@@ -136,6 +137,10 @@
file = zip->FindFile("assets/test.hello.xml");
ASSERT_THAT(file, Ne(nullptr));
EXPECT_FALSE(file->WasCompressed());
+
+ file = zip->FindFile("assets/fonts/myfont.ttf");
+ ASSERT_THAT(file, Ne(nullptr));
+ EXPECT_TRUE(file->WasCompressed());
}
TEST_F(LinkTest, NoCompressResources) {
@@ -182,6 +187,42 @@
EXPECT_FALSE(file->WasCompressed());
}
+TEST_F(LinkTest, NoCompressFonts) {
+ StdErrDiagnostics diag;
+ std::string content(500, 'a');
+ const std::string compiled_files_dir = GetTestPath("compiled");
+ ASSERT_TRUE(CompileFile(GetTestPath("res/raw/test.txt"), content, compiled_files_dir, &diag));
+ WriteFile(GetTestPath("assets/fonts/myfont1.ttf"), content);
+ WriteFile(GetTestPath("assets/fonts/myfont2.ttf"), content);
+
+ const std::string out_apk = GetTestPath("out.apk");
+ std::vector<std::string> link_args = {
+ "--manifest", GetDefaultManifest(),
+ "-o", out_apk,
+ "--no-compress-fonts",
+ "-A", GetTestPath("assets")
+ };
+
+ ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
+
+ std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+ ASSERT_THAT(apk, Ne(nullptr));
+ io::IFileCollection* zip = apk->GetFileCollection();
+ ASSERT_THAT(zip, Ne(nullptr));
+
+ auto file = zip->FindFile("res/raw/test.txt");
+ ASSERT_THAT(file, Ne(nullptr));
+ EXPECT_TRUE(file->WasCompressed());
+
+ file = zip->FindFile("assets/fonts/myfont1.ttf");
+ ASSERT_THAT(file, Ne(nullptr));
+ EXPECT_FALSE(file->WasCompressed());
+
+ file = zip->FindFile("assets/fonts/myfont2.ttf");
+ ASSERT_THAT(file, Ne(nullptr));
+ EXPECT_FALSE(file->WasCompressed());
+}
+
TEST_F(LinkTest, OverlayStyles) {
StdErrDiagnostics diag;
const std::string compiled_files_dir = GetTestPath("compiled");
diff --git a/tools/aapt2/link/FlaggedResources_test.cpp b/tools/aapt2/link/FlaggedResources_test.cpp
index adf711e..7bea96c 100644
--- a/tools/aapt2/link/FlaggedResources_test.cpp
+++ b/tools/aapt2/link/FlaggedResources_test.cpp
@@ -169,4 +169,18 @@
ASSERT_TRUE(output.contains("test.package.readWriteFlag"));
}
+TEST_F(FlaggedResourcesTest, ReadWriteFlagInPathFails) {
+ test::TestDiagnosticsImpl diag;
+ const std::string compiled_files_dir = GetTestPath("compiled");
+ ASSERT_FALSE(CompileFile(GetTestPath("res/values/flag(!test.package.rwFlag)/bools.xml"),
+ R"(<resources>
+ <bool name="bool1">false</bool>
+ </resources>)",
+ compiled_files_dir, &diag,
+ {"--feature-flags", "test.package.rwFlag=false"}));
+
+ ASSERT_TRUE(diag.GetLog().contains(
+ "Only read only flags may be used with resources: test.package.rwFlag"));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index 5c3dfdc..6bdbaae 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -3,6 +3,8 @@
## Version 2.20
- Too many features, bug fixes, and improvements to list since the last minor version update in
2017. This README will be updated more frequently in the future.
+- Added a new flag `--no-compress-fonts`. This can significantly speed up loading fonts from APK
+ assets, at the cost of increasing the storage size of the APK.
## Version 2.19
- Added navigation resource type.