Merge "Fix missed rename: freeform _initial_bounds_scale -> desktop_mode_initial_bounds_scale." into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index fa11278..a42adad 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -173,6 +173,11 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+cc_aconfig_library {
+ name: "com.android.window.flags.window-aconfig_flags_c_lib",
+ aconfig_declarations: "com.android.window.flags.window-aconfig",
+}
+
// DeviceStateManager
aconfig_declarations {
name: "android.hardware.devicestate.feature.flags-aconfig",
diff --git a/Ravenwood.bp b/Ravenwood.bp
index 74382a6..3ab0934 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -270,6 +270,7 @@
],
jni_libs: [
"libandroid_runtime",
+ "libravenwood_runtime",
],
}
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
index 2ace602..d80d3c8 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
@@ -18,6 +18,8 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.window.flags.Flags.windowSessionRelayoutInfo;
+
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
@@ -35,6 +37,7 @@
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.WindowRelayoutResult;
import android.widget.LinearLayout;
import android.window.ClientWindowFrames;
@@ -128,7 +131,8 @@
final MergedConfiguration mOutMergedConfiguration = new MergedConfiguration();
final InsetsState mOutInsetsState = new InsetsState();
final InsetsSourceControl.Array mOutControls = new InsetsSourceControl.Array();
- final Bundle mOutBundle = new Bundle();
+ final Bundle mOutBundle = windowSessionRelayoutInfo() ? null : new Bundle();
+ final WindowRelayoutResult mOutRelayoutResult;
final IWindow mWindow;
final View mView;
final WindowManager.LayoutParams mParams;
@@ -148,16 +152,26 @@
mHeight = mView.getMeasuredHeight();
mOutSurfaceControl = mView.getViewRootImpl().getSurfaceControl();
mViewVisibility = visibilitySupplier;
+ mOutRelayoutResult = windowSessionRelayoutInfo()
+ ? new WindowRelayoutResult(mOutFrames, mOutMergedConfiguration,
+ mOutSurfaceControl, mOutInsetsState, mOutControls)
+ : null;
}
void runBenchmark(BenchmarkState state) throws RemoteException {
final IWindowSession session = WindowManagerGlobal.getWindowSession();
while (state.keepRunning()) {
mRelayoutSeq++;
- session.relayout(mWindow, mParams, mWidth, mHeight,
- mViewVisibility.getAsInt(), mFlags, mRelayoutSeq, 0 /* lastSyncSeqId */,
- mOutFrames, mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState,
- mOutControls, mOutBundle);
+ if (windowSessionRelayoutInfo()) {
+ session.relayout(mWindow, mParams, mWidth, mHeight,
+ mViewVisibility.getAsInt(), mFlags, mRelayoutSeq, 0 /* lastSyncSeqId */,
+ mOutRelayoutResult);
+ } else {
+ session.relayoutLegacy(mWindow, mParams, mWidth, mHeight,
+ mViewVisibility.getAsInt(), mFlags, mRelayoutSeq, 0 /* lastSyncSeqId */,
+ mOutFrames, mOutMergedConfiguration, mOutSurfaceControl,
+ mOutInsetsState, mOutControls, mOutBundle);
+ }
}
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
index e649485..e82df12 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
@@ -41,10 +41,10 @@
]
},
{
- "name": "CtsHostsideNetworkTests",
+ "name": "CtsHostsideNetworkPolicyTests",
"options": [
- {"include-filter": "com.android.cts.net.HostsideRestrictBackgroundNetworkTests#testMeteredNetworkAccess_expeditedJob"},
- {"include-filter": "com.android.cts.net.HostsideRestrictBackgroundNetworkTests#testNonMeteredNetworkAccess_expeditedJob"}
+ {"include-filter": "com.android.cts.netpolicy.HostsideRestrictBackgroundNetworkTests#testMeteredNetworkAccess_expeditedJob"},
+ {"include-filter": "com.android.cts.netpolicy.HostsideRestrictBackgroundNetworkTests#testNonMeteredNetworkAccess_expeditedJob"}
]
},
{
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 7a39610..eb12ada 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -107,22 +107,25 @@
private static final long MIN_ADJUST_CALLBACK_INTERVAL_MS = 1_000L;
private static final int UNBYPASSABLE_BG_BLOCKED_REASONS =
- ~ConnectivityManager.BLOCKED_REASON_NONE;
+ ~ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND;
private static final int UNBYPASSABLE_EJ_BLOCKED_REASONS =
~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY
| ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER
+ | ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND
| ConnectivityManager.BLOCKED_REASON_DOZE);
private static final int UNBYPASSABLE_UI_BLOCKED_REASONS =
~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY
| ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER
| ConnectivityManager.BLOCKED_REASON_DOZE
| ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER
+ | ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND
| ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED);
private static final int UNBYPASSABLE_FOREGROUND_BLOCKED_REASONS =
~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY
| ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER
| ConnectivityManager.BLOCKED_REASON_DOZE
| ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER
+ | ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND
| ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED);
@VisibleForTesting
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
index be4b720..d52c4ce 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -36,10 +36,9 @@
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
+import java.util.Comparator;
import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
+import java.util.PriorityQueue;
import java.util.function.Predicate;
/**
@@ -64,8 +63,17 @@
private volatile long mLastFiredDelayExpiredElapsedMillis;
private AlarmManager mAlarmService = null;
- /** List of tracked jobs, sorted asc. by deadline */
- private final List<JobStatus> mTrackedJobs = new LinkedList<>();
+
+ /** List of tracked jobs, ordered by deadline (lowest i.e. earliest first) */
+ private final PriorityQueue<JobStatus> mTrackedJobs =
+ new PriorityQueue<>(
+ new Comparator<JobStatus>() {
+ public int compare(JobStatus left, JobStatus right) {
+ return Long.compare(
+ left.getLatestRunTimeElapsed(),
+ right.getLatestRunTimeElapsed());
+ }
+ });
public TimeController(JobSchedulerService service) {
super(service);
@@ -102,20 +110,7 @@
}
}
- boolean isInsert = false;
- ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
- while (it.hasPrevious()) {
- JobStatus ts = it.previous();
- if (ts.getLatestRunTimeElapsed() < job.getLatestRunTimeElapsed()) {
- // Insert
- isInsert = true;
- break;
- }
- }
- if (isInsert) {
- it.next();
- }
- it.add(job);
+ mTrackedJobs.add(job);
job.setTrackingController(JobStatus.TRACKING_TIME);
WorkSource ws =
@@ -226,7 +221,7 @@
String nextExpiryPackageName = null;
final long nowElapsedMillis = sElapsedRealtimeClock.millis();
- ListIterator<JobStatus> it = mTrackedJobs.listIterator();
+ Iterator<JobStatus> it = mTrackedJobs.iterator();
while (it.hasNext()) {
JobStatus job = it.next();
if (!job.hasDeadlineConstraint()) {
diff --git a/config/Android.bp b/config/Android.bp
index dd681ca..adce203 100644
--- a/config/Android.bp
+++ b/config/Android.bp
@@ -29,6 +29,13 @@
],
}
+prebuilt_etc {
+ name: "preloaded-classes",
+ src: "preloaded-classes",
+ filename: "preloaded-classes",
+ installable: false,
+}
+
filegroup {
name: "preloaded-classes-denylist",
srcs: ["preloaded-classes-denylist"],
diff --git a/core/api/current.txt b/core/api/current.txt
index 2f2a765..53cf7d5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -451,12 +451,12 @@
field public static final int alertDialogTheme = 16843529; // 0x1010309
field public static final int alignmentMode = 16843642; // 0x101037a
field public static final int allContactsName = 16843468; // 0x10102cc
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int allow;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int allow = 16844430; // 0x101068e
field public static final int allowAudioPlaybackCapture = 16844289; // 0x1010601
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
field public static final int allowClickWhenDisabled = 16844312; // 0x1010618
- field @FlaggedApi("android.security.asm_restrictions_enabled") public static final int allowCrossUidActivitySwitchFromBelow;
+ field @FlaggedApi("android.security.asm_restrictions_enabled") public static final int allowCrossUidActivitySwitchFromBelow = 16844449; // 0x10106a1
field public static final int allowEmbedded = 16843765; // 0x10103f5
field public static final int allowGameAngleDriver = 16844376; // 0x1010658
field public static final int allowGameDownscaling = 16844377; // 0x1010659
@@ -511,7 +511,7 @@
field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field @Deprecated public static final int autoText = 16843114; // 0x101016a
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int autoTransact;
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int autoTransact = 16844441; // 0x1010699
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
field public static final int autofillHints = 16844118; // 0x1010556
@@ -658,7 +658,7 @@
field public static final int contentInsetRight = 16843862; // 0x1010456
field public static final int contentInsetStart = 16843859; // 0x1010453
field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
- field @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") public static final int contentSensitivity;
+ field @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") public static final int contentSensitivity = 16844446; // 0x101069e
field public static final int contextClickable = 16844007; // 0x10104e7
field public static final int contextDescription = 16844078; // 0x101052e
field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
@@ -688,7 +688,7 @@
field public static final int debuggable = 16842767; // 0x101000f
field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
field public static final int defaultHeight = 16844021; // 0x10104f5
- field @FlaggedApi("android.content.res.default_locale") public static final int defaultLocale;
+ field @FlaggedApi("android.content.res.default_locale") public static final int defaultLocale = 16844424; // 0x1010688
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
field public static final int defaultWidth = 16844020; // 0x10104f4
@@ -858,7 +858,7 @@
field public static final int format24Hour = 16843723; // 0x10103cb
field public static final int fraction = 16843992; // 0x10104d8
field public static final int fragment = 16843491; // 0x10102e3
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentAdvancedPattern;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentAdvancedPattern = 16844438; // 0x1010696
field public static final int fragmentAllowEnterTransitionOverlap = 16843976; // 0x10104c8
field public static final int fragmentAllowReturnTransitionOverlap = 16843977; // 0x10104c9
field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
@@ -869,13 +869,13 @@
field public static final int fragmentFadeExitAnimation = 16843498; // 0x10102ea
field public static final int fragmentOpenEnterAnimation = 16843493; // 0x10102e5
field public static final int fragmentOpenExitAnimation = 16843494; // 0x10102e6
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPattern;
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPrefix;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPattern = 16844437; // 0x1010695
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPrefix = 16844436; // 0x1010694
field public static final int fragmentReenterTransition = 16843975; // 0x10104c7
field public static final int fragmentReturnTransition = 16843973; // 0x10104c5
field public static final int fragmentSharedElementEnterTransition = 16843972; // 0x10104c4
field public static final int fragmentSharedElementReturnTransition = 16843974; // 0x10104c6
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentSuffix;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentSuffix = 16844439; // 0x1010697
field public static final int freezesText = 16843116; // 0x101016c
field public static final int fromAlpha = 16843210; // 0x10101ca
field public static final int fromDegrees = 16843187; // 0x10101b3
@@ -1345,15 +1345,15 @@
field public static final int propertyYName = 16843893; // 0x1010475
field public static final int protectionLevel = 16842761; // 0x1010009
field public static final int publicKey = 16843686; // 0x10103a6
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int query;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int query = 16844431; // 0x101068f
field public static final int queryActionMsg = 16843227; // 0x10101db
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryAdvancedPattern;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryAdvancedPattern = 16844434; // 0x1010692
field public static final int queryAfterZeroResults = 16843394; // 0x1010282
field public static final int queryBackground = 16843911; // 0x1010487
field public static final int queryHint = 16843608; // 0x1010358
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPattern;
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPrefix;
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int querySuffix;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPattern = 16844433; // 0x1010691
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPrefix = 16844432; // 0x1010690
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int querySuffix = 16844435; // 0x1010693
field public static final int quickContactBadgeStyleSmallWindowLarge = 16843443; // 0x10102b3
field public static final int quickContactBadgeStyleSmallWindowMedium = 16843442; // 0x10102b2
field public static final int quickContactBadgeStyleSmallWindowSmall = 16843441; // 0x10102b1
@@ -1382,7 +1382,7 @@
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
field public static final int requestRawExternalStorageAccess = 16844357; // 0x1010645
- field @FlaggedApi("android.security.content_uri_permission_apis") public static final int requireContentUriPermissionFromCaller;
+ field @FlaggedApi("android.security.content_uri_permission_apis") public static final int requireContentUriPermissionFromCaller = 16844443; // 0x101069b
field public static final int requireDeviceScreenOn = 16844317; // 0x101061d
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
@@ -1494,12 +1494,12 @@
field @Deprecated public static final int sharedUserLabel = 16843361; // 0x1010261
field public static final int sharedUserMaxSdkVersion = 16844365; // 0x101064d
field public static final int shell = 16844180; // 0x1010594
- field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int shiftDrawingOffsetForStartOverhang;
+ field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int shiftDrawingOffsetForStartOverhang = 16844450; // 0x10106a2
field public static final int shortcutDisabledMessage = 16844075; // 0x101052b
field public static final int shortcutId = 16844072; // 0x1010528
field public static final int shortcutLongLabel = 16844074; // 0x101052a
field public static final int shortcutShortLabel = 16844073; // 0x1010529
- field @FlaggedApi("android.nfc.nfc_observe_mode") public static final int shouldDefaultToObserveMode;
+ field @FlaggedApi("android.nfc.nfc_observe_mode") public static final int shouldDefaultToObserveMode = 16844448; // 0x10106a0
field public static final int shouldDisableView = 16843246; // 0x10101ee
field public static final int shouldUseDefaultUnfoldTransition = 16844364; // 0x101064c
field public static final int showAsAction = 16843481; // 0x10102d9
@@ -1610,7 +1610,7 @@
field public static final int supportedTypes = 16844369; // 0x1010651
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsBatteryGameMode = 16844374; // 0x1010656
- field @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public static final int supportsConnectionlessStylusHandwriting;
+ field @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public static final int supportsConnectionlessStylusHandwriting = 16844447; // 0x101069f
field public static final int supportsInlineSuggestions = 16844301; // 0x101060d
field public static final int supportsInlineSuggestionsWithTouchExploration = 16844397; // 0x101066d
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
@@ -1631,7 +1631,7 @@
field public static final int switchTextOff = 16843628; // 0x101036c
field public static final int switchTextOn = 16843627; // 0x101036b
field public static final int syncable = 16842777; // 0x1010019
- field @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") public static final int systemUserOnly;
+ field @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") public static final int systemUserOnly = 16844429; // 0x101068d
field public static final int tabStripEnabled = 16843453; // 0x10102bd
field public static final int tabStripLeft = 16843451; // 0x10102bb
field public static final int tabStripRight = 16843452; // 0x10102bc
@@ -1808,12 +1808,12 @@
field public static final int updatePeriodMillis = 16843344; // 0x1010250
field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useAppZygote = 16844183; // 0x1010597
- field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int useBoundsForWidth;
+ field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int useBoundsForWidth = 16844440; // 0x1010698
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useEmbeddedDex = 16844190; // 0x101059e
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
- field @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public static final int useLocalePreferredLineHeightForMinimum;
+ field @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public static final int useLocalePreferredLineHeightForMinimum = 16844445; // 0x101069d
field public static final int userVisible = 16843409; // 0x1010291
field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
field public static final int usesPermissionFlags = 16844356; // 0x1010644
@@ -1892,7 +1892,7 @@
field public static final int windowFullscreen = 16843277; // 0x101020d
field public static final int windowHideAnimation = 16842935; // 0x10100b7
field public static final int windowIsFloating = 16842839; // 0x1010057
- field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final int windowIsFrameRatePowerSavingsBalanced;
+ field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final int windowIsFrameRatePowerSavingsBalanced = 16844451; // 0x10106a3
field public static final int windowIsTranslucent = 16842840; // 0x1010058
field public static final int windowLayoutAffinity = 16844313; // 0x1010619
field public static final int windowLayoutInDisplayCutoutMode = 16844166; // 0x1010586
@@ -1903,7 +1903,7 @@
field public static final int windowNoDisplay = 16843294; // 0x101021e
field public static final int windowNoMoveAnimation = 16844421; // 0x1010685
field public static final int windowNoTitle = 16842838; // 0x1010056
- field @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") public static final int windowOptOutEdgeToEdgeEnforcement;
+ field @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") public static final int windowOptOutEdgeToEdgeEnforcement = 16844442; // 0x101069a
field @Deprecated public static final int windowOverscan = 16843727; // 0x10103cf
field public static final int windowReenterTransition = 16843951; // 0x10104af
field public static final int windowReturnTransition = 16843950; // 0x10104ae
@@ -2015,19 +2015,19 @@
field public static final int system_control_highlight_light = 17170558; // 0x106007e
field public static final int system_control_normal_dark = 17170600; // 0x10600a8
field public static final int system_control_normal_light = 17170557; // 0x106007d
- field public static final int system_error_0;
- field public static final int system_error_10;
- field public static final int system_error_100;
- field public static final int system_error_1000;
- field public static final int system_error_200;
- field public static final int system_error_300;
- field public static final int system_error_400;
- field public static final int system_error_50;
- field public static final int system_error_500;
- field public static final int system_error_600;
- field public static final int system_error_700;
- field public static final int system_error_800;
- field public static final int system_error_900;
+ field public static final int system_error_0 = 17170629; // 0x10600c5
+ field public static final int system_error_10 = 17170630; // 0x10600c6
+ field public static final int system_error_100 = 17170632; // 0x10600c8
+ field public static final int system_error_1000 = 17170641; // 0x10600d1
+ field public static final int system_error_200 = 17170633; // 0x10600c9
+ field public static final int system_error_300 = 17170634; // 0x10600ca
+ field public static final int system_error_400 = 17170635; // 0x10600cb
+ field public static final int system_error_50 = 17170631; // 0x10600c7
+ field public static final int system_error_500 = 17170636; // 0x10600cc
+ field public static final int system_error_600 = 17170637; // 0x10600cd
+ field public static final int system_error_700 = 17170638; // 0x10600ce
+ field public static final int system_error_800 = 17170639; // 0x10600cf
+ field public static final int system_error_900 = 17170640; // 0x10600d0
field public static final int system_error_container_dark = 17170597; // 0x10600a5
field public static final int system_error_container_light = 17170554; // 0x106007a
field public static final int system_error_dark = 17170595; // 0x10600a3
@@ -2077,7 +2077,7 @@
field public static final int system_on_secondary_fixed_variant = 17170619; // 0x10600bb
field public static final int system_on_secondary_light = 17170533; // 0x1060065
field public static final int system_on_surface_dark = 17170584; // 0x1060098
- field public static final int system_on_surface_disabled;
+ field public static final int system_on_surface_disabled = 17170627; // 0x10600c3
field public static final int system_on_surface_light = 17170541; // 0x106006d
field public static final int system_on_surface_variant_dark = 17170593; // 0x10600a1
field public static final int system_on_surface_variant_light = 17170550; // 0x1060076
@@ -2088,7 +2088,7 @@
field public static final int system_on_tertiary_fixed_variant = 17170623; // 0x10600bf
field public static final int system_on_tertiary_light = 17170537; // 0x1060069
field public static final int system_outline_dark = 17170594; // 0x10600a2
- field public static final int system_outline_disabled;
+ field public static final int system_outline_disabled = 17170628; // 0x10600c4
field public static final int system_outline_light = 17170551; // 0x1060077
field public static final int system_outline_variant_dark = 17170625; // 0x10600c1
field public static final int system_outline_variant_light = 17170624; // 0x10600c0
@@ -2129,7 +2129,7 @@
field public static final int system_surface_dark = 17170583; // 0x1060097
field public static final int system_surface_dim_dark = 17170591; // 0x106009f
field public static final int system_surface_dim_light = 17170548; // 0x1060074
- field public static final int system_surface_disabled;
+ field public static final int system_surface_disabled = 17170626; // 0x10600c2
field public static final int system_surface_light = 17170540; // 0x106006c
field public static final int system_surface_variant_dark = 17170592; // 0x10600a0
field public static final int system_surface_variant_light = 17170549; // 0x1060075
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e12da63..eabe1f1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -437,10 +437,10 @@
public static final class R.attr {
field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
- field @FlaggedApi("android.content.res.manifest_flagging") public static final int featureFlag;
+ field @FlaggedApi("android.content.res.manifest_flagging") public static final int featureFlag = 16844428; // 0x101068c
field public static final int gameSessionService = 16844373; // 0x1010655
field public static final int hotwordDetectionService = 16844326; // 0x1010626
- field @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") public static final int isVirtualDeviceOnly;
+ field @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") public static final int isVirtualDeviceOnly = 16844425; // 0x1010689
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int minExtensionVersion = 16844305; // 0x1010611
field public static final int playHomeTransitionSound = 16844358; // 0x1010646
@@ -492,9 +492,9 @@
field public static final int config_defaultCallScreening = 17039398; // 0x1040026
field public static final int config_defaultDialer = 17039395; // 0x1040023
field public static final int config_defaultNotes = 17039429; // 0x1040045
- field @FlaggedApi("android.permission.flags.retail_demo_role_enabled") public static final int config_defaultRetailDemo;
+ field @FlaggedApi("android.permission.flags.retail_demo_role_enabled") public static final int config_defaultRetailDemo = 17039432; // 0x1040048
field public static final int config_defaultSms = 17039396; // 0x1040024
- field @FlaggedApi("android.permission.flags.wallet_role_enabled") public static final int config_defaultWallet;
+ field @FlaggedApi("android.permission.flags.wallet_role_enabled") public static final int config_defaultWallet = 17039433; // 0x1040049
field public static final int config_devicePolicyManagement = 17039421; // 0x104003d
field public static final int config_feedbackIntentExtraKey = 17039391; // 0x104001f
field public static final int config_feedbackIntentNameKey = 17039392; // 0x1040020
@@ -872,6 +872,7 @@
public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
method public int describeContents();
method @Nullable public String getAttributionTag();
+ method @FlaggedApi("android.permission.flags.device_id_in_op_proxy_info_enabled") @Nullable public String getDeviceId();
method @Nullable public String getPackageName();
method @IntRange(from=0) public int getUid();
method public void writeToParcel(@NonNull android.os.Parcel, int);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index bc66127..caaaf51 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -353,6 +353,9 @@
private static final String DEFAULT_FULL_BACKUP_AGENT = "android.app.backup.FullBackupAgent";
+ private static final long BINDER_CALLBACK_THROTTLE = 10_100L;
+ private long mBinderCallbackLast = -1;
+
/**
* Denotes the sequence number of the process state change for which the main thread needs
* to block until the network rules are updated for it.
@@ -7435,6 +7438,7 @@
}
mDdmSyncStageUpdater.next(Stage.Running);
+ long timestampApplicationOnCreateNs = 0;
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
@@ -7477,8 +7481,10 @@
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
+ timestampApplicationOnCreateNs = SystemClock.elapsedRealtimeNanos();
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
+ timestampApplicationOnCreateNs = 0;
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
@@ -7516,7 +7522,7 @@
}
try {
- mgr.finishAttachApplication(mStartSeq);
+ mgr.finishAttachApplication(mStartSeq, timestampApplicationOnCreateNs);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -7525,6 +7531,12 @@
Binder.setTransactionCallback(new IBinderCallback() {
@Override
public void onTransactionError(int pid, int code, int flags, int err) {
+ final long now = SystemClock.uptimeMillis();
+ if (now < mBinderCallbackLast + BINDER_CALLBACK_THROTTLE) {
+ Slog.d(TAG, "Too many transaction errors, throttling freezer binder callback.");
+ return;
+ }
+ mBinderCallbackLast = now;
try {
mgr.frozenBinderTransactionDetected(pid, code, flags, err);
} catch (RemoteException ex) {
diff --git a/core/java/android/app/AppOpInfo.java b/core/java/android/app/AppOpInfo.java
index 5268ec4..a0f0cca 100644
--- a/core/java/android/app/AppOpInfo.java
+++ b/core/java/android/app/AppOpInfo.java
@@ -88,7 +88,7 @@
/**
* This specifies whether each option is only allowed to be read
- * by apps with manage appops permission.
+ * by apps with privileged appops permission.
*/
public final boolean restrictRead;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8e766c9..2d0f6fc 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -3265,7 +3265,7 @@
}
/**
- * Retrieve whether the op can be read by apps with manage appops permission.
+ * Retrieve whether the op can be read by apps with privileged appops permission.
* @hide
*/
public static boolean opRestrictsRead(int op) {
@@ -3457,6 +3457,8 @@
private @Nullable String mPackageName;
/** Attribution tag of the proxy that noted the op */
private @Nullable String mAttributionTag;
+ /** Persistent device Id of the proxy that noted the op */
+ private @Nullable String mDeviceId;
/**
* Reinit existing object with new state.
@@ -3464,14 +3466,16 @@
* @param uid UID of the proxy app that noted the op
* @param packageName Package of the proxy that noted the op
* @param attributionTag attribution tag of the proxy that noted the op
+ * @param deviceId Persistent device Id of the proxy that noted the op
*
* @hide
*/
public void reinit(@IntRange(from = 0) int uid, @Nullable String packageName,
- @Nullable String attributionTag) {
+ @Nullable String attributionTag, @Nullable String deviceId) {
mUid = Preconditions.checkArgumentNonnegative(uid);
mPackageName = packageName;
mAttributionTag = attributionTag;
+ mDeviceId = deviceId;
}
@@ -3505,16 +3509,33 @@
@IntRange(from = 0) int uid,
@Nullable String packageName,
@Nullable String attributionTag) {
+ this(uid, packageName, attributionTag,
+ VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
+ }
+
+ /**
+ * Creates a new OpEventProxyInfo.
+ *
+ * @param uid UID of the proxy app that noted the op
+ * @param packageName Package of the proxy that noted the op
+ * @param attributionTag Attribution tag of the proxy that noted the op
+ * @param deviceId Persistent device Id of the proxy that noted the op
+ *
+ * @hide
+ */
+ public OpEventProxyInfo(
+ @IntRange(from = 0) int uid,
+ @Nullable String packageName,
+ @Nullable String attributionTag,
+ @Nullable String deviceId) {
this.mUid = uid;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mUid,
"from", 0);
this.mPackageName = packageName;
this.mAttributionTag = attributionTag;
-
- // onConstructed(); // You can define this method to get a callback
+ this.mDeviceId = deviceId;
}
-
/**
* Copy constructor
*
@@ -3525,6 +3546,7 @@
mUid = orig.mUid;
mPackageName = orig.mPackageName;
mAttributionTag = orig.mAttributionTag;
+ mDeviceId = orig.mDeviceId;
}
/**
@@ -3551,6 +3573,9 @@
return mAttributionTag;
}
+ @FlaggedApi(Flags.FLAG_DEVICE_ID_IN_OP_PROXY_INFO_ENABLED)
+ public @Nullable String getDeviceId() { return mDeviceId; }
+
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -3560,10 +3585,12 @@
byte flg = 0;
if (mPackageName != null) flg |= 0x2;
if (mAttributionTag != null) flg |= 0x4;
+ if (mDeviceId != null) flg |= 0x8;
dest.writeByte(flg);
dest.writeInt(mUid);
if (mPackageName != null) dest.writeString(mPackageName);
if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ if (mDeviceId != null) dest.writeString(mDeviceId);
}
@Override
@@ -3581,14 +3608,14 @@
int uid = in.readInt();
String packageName = (flg & 0x2) == 0 ? null : in.readString();
String attributionTag = (flg & 0x4) == 0 ? null : in.readString();
-
+ String deviceId = (flg & 0x8) == 0 ? null : in.readString();
this.mUid = uid;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mUid,
"from", 0);
this.mPackageName = packageName;
this.mAttributionTag = attributionTag;
-
+ this.mDeviceId = deviceId;
// onConstructed(); // You can define this method to get a callback
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index dd6bc55..b9906bf 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -84,6 +84,7 @@
import android.content.res.ApkAssets;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -118,9 +119,11 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.AttributeSet;
import android.util.LauncherIcons;
import android.util.Log;
import android.util.Slog;
+import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.Immutable;
@@ -132,6 +135,9 @@
import libcore.util.EmptyArray;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -4090,4 +4096,38 @@
}
}
}
+
+ @Override
+ public TypedArray extractPackageItemInfoAttributes(PackageItemInfo info, String name,
+ String rootTag, int[] attributes) {
+ if (info == null || info.metaData == null) {
+ return null;
+ }
+
+ try (XmlResourceParser parser = info.loadXmlMetaData(this, name)) {
+ if (parser == null) {
+ Log.w(TAG, "No " + name + " metadata");
+ return null;
+ }
+
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ while (true) {
+ final int type = parser.next();
+ if (type == XmlPullParser.END_DOCUMENT || type == XmlPullParser.START_TAG) {
+ break;
+ }
+ }
+
+ if (!TextUtils.equals(parser.getName(), rootTag)) {
+ Log.w(TAG, "Metadata does not start with " + name + " tag");
+ return null;
+ }
+
+ return getResourcesForApplication(info.getApplicationInfo())
+ .obtainAttributes(attrs, attributes);
+ } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) {
+ Log.e(TAG, "Error parsing: " + info.packageName, e);
+ return null;
+ }
+ }
}
diff --git a/core/java/android/app/GrammaticalInflectionManager.java b/core/java/android/app/GrammaticalInflectionManager.java
index f0bc3e2..37e51f8 100644
--- a/core/java/android/app/GrammaticalInflectionManager.java
+++ b/core/java/android/app/GrammaticalInflectionManager.java
@@ -104,7 +104,7 @@
* Sets the current grammatical gender for all privileged applications. The value will be
* stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int)}
*
- * @param grammaticalGender the terms of address the user preferred in system.
+ * @param grammaticalGender the grammatical gender set by the user for the system.
*
* @see Configuration#getGrammaticalGender
* @hide
@@ -123,12 +123,12 @@
}
/**
- * Get the current grammatical gender of privileged application from the encrypted file.
+ * Allows privileged preloaded applications to get the system grammatical gender when set.
*
- * @return the value of system grammatical gender only if the calling app has the permission,
- * otherwise throwing an exception.
+ * @return The value of system grammatical gender only if the calling app has the
+ * permission, otherwise throwing an exception.
*
- * @throws SecurityException if the caller does not have the required permission.
+ * @throws SecurityException If the caller does not have the required permission.
*
* @see Configuration#getGrammaticalGender
*/
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3765c81..e8b57f2 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -196,7 +196,7 @@
oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map,
boolean abortBroadcast, int flags);
void attachApplication(in IApplicationThread app, long startSeq);
- void finishAttachApplication(long startSeq);
+ void finishAttachApplication(long startSeq, long timestampApplicationOnCreateNs);
List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
@UnsupportedAppUsage
void moveTaskToFront(in IApplicationThread caller, in String callingPackage, int task,
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index b5e5074..62820ad 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -1032,9 +1032,7 @@
return false;
}
boolean success;
- try {
- LockscreenCredential credential = createLockscreenCredential(
- lockType, password);
+ try (LockscreenCredential credential = createLockscreenCredential(lockType, password)) {
success = mLockPatternUtils.setLockCredential(
credential,
/* savedPassword= */ LockscreenCredential.createNone(),
@@ -1213,19 +1211,20 @@
public boolean setLock(@LockTypes int newLockType, @Nullable byte[] newPassword,
@LockTypes int currentLockType, @Nullable byte[] currentPassword) {
final int userId = mContext.getUserId();
- LockscreenCredential currentCredential = createLockscreenCredential(
+ try (LockscreenCredential currentCredential = createLockscreenCredential(
currentLockType, currentPassword);
- LockscreenCredential newCredential = createLockscreenCredential(
- newLockType, newPassword);
- PasswordMetrics adminMetrics =
- mLockPatternUtils.getRequestedPasswordMetrics(mContext.getUserId());
- List<PasswordValidationError> errors = PasswordMetrics.validateCredential(adminMetrics,
- DevicePolicyManager.PASSWORD_COMPLEXITY_NONE, newCredential);
- if (!errors.isEmpty()) {
- Log.e(TAG, "New credential is not valid: " + errors.get(0));
- return false;
+ LockscreenCredential newCredential = createLockscreenCredential(
+ newLockType, newPassword)) {
+ PasswordMetrics adminMetrics =
+ mLockPatternUtils.getRequestedPasswordMetrics(mContext.getUserId());
+ List<PasswordValidationError> errors = PasswordMetrics.validateCredential(adminMetrics,
+ DevicePolicyManager.PASSWORD_COMPLEXITY_NONE, newCredential);
+ if (!errors.isEmpty()) {
+ Log.e(TAG, "New credential is not valid: " + errors.get(0));
+ return false;
+ }
+ return mLockPatternUtils.setLockCredential(newCredential, currentCredential, userId);
}
- return mLockPatternUtils.setLockCredential(newCredential, currentCredential, userId);
}
/**
@@ -1244,14 +1243,14 @@
Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE
})
public boolean checkLock(@LockTypes int lockType, @Nullable byte[] password) {
- final LockscreenCredential credential = createLockscreenCredential(
- lockType, password);
- final VerifyCredentialResponse response = mLockPatternUtils.verifyCredential(
- credential, mContext.getUserId(), /* flags= */ 0);
- if (response == null) {
- return false;
+ try (LockscreenCredential credential = createLockscreenCredential(lockType, password)) {
+ final VerifyCredentialResponse response = mLockPatternUtils.verifyCredential(
+ credential, mContext.getUserId(), /* flags= */ 0);
+ if (response == null) {
+ return false;
+ }
+ return response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK;
}
- return response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK;
}
/** Starts a session to verify lockscreen credentials provided by a remote device.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index f1e44cc..1df8f63 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1104,6 +1104,10 @@
return true;
}
+ if (mDataDir == null) {
+ return false;
+ }
+
// Temporarily disable logging of disk reads on the Looper thread as this is necessary -
// and the loader will access the directory anyway if we don't check it.
StrictMode.ThreadPolicy oldThreadPolicy = allowThreadDiskReads();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b19dc8f..c3bac71 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -18,7 +18,6 @@
import static android.annotation.Dimension.DP;
import static android.app.Flags.evenlyDividedCallStyleActionLayout;
-import static android.app.Flags.updateRankingTime;
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;
@@ -897,15 +896,16 @@
/**
* Sphere of visibility of this notification, which affects how and when the SystemUI reveals
* the notification's presence and contents in untrusted situations (namely, on the secure
- * lockscreen).
+ * lockscreen and during screen sharing).
*
* The default level, {@link #VISIBILITY_PRIVATE}, behaves exactly as notifications have always
* done on Android: The notification's {@link #icon} and {@link #tickerText} (if available) are
* shown in all situations, but the contents are only available if the device is unlocked for
- * the appropriate user.
+ * the appropriate user and there is no active screen sharing session.
*
* A more permissive policy can be expressed by {@link #VISIBILITY_PUBLIC}; such a notification
- * can be read even in an "insecure" context (that is, above a secure lockscreen).
+ * can be read even in an "insecure" context (that is, above a secure lockscreen or while
+ * screen sharing with a remote viewer).
* To modify the public version of this notification—for example, to redact some portions—see
* {@link Builder#setPublicVersion(Notification)}.
*
@@ -924,7 +924,8 @@
public @interface Visibility {}
/**
- * Notification visibility: Show this notification in its entirety on all lockscreens.
+ * Notification visibility: Show this notification in its entirety on all lockscreens and while
+ * screen sharing.
*
* {@see #visibility}
*/
@@ -932,14 +933,16 @@
/**
* Notification visibility: Show this notification on all lockscreens, but conceal sensitive or
- * private information on secure lockscreens.
+ * private information on secure lockscreens. Conceal sensitive or private information while
+ * screen sharing.
*
* {@see #visibility}
*/
public static final int VISIBILITY_PRIVATE = 0;
/**
- * Notification visibility: Do not reveal any part of this notification on a secure lockscreen.
+ * Notification visibility: Do not reveal any part of this notification on a secure lockscreen
+ * or while screen sharing.
*
* {@see #visibility}
*/
@@ -2596,7 +2599,7 @@
public Notification()
{
this.when = System.currentTimeMillis();
- if (updateRankingTime()) {
+ if (Flags.sortSectionByTime()) {
creationTime = when;
extras.putBoolean(EXTRA_SHOW_WHEN, true);
} else {
@@ -2612,7 +2615,7 @@
public Notification(Context context, int icon, CharSequence tickerText, long when,
CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
{
- if (updateRankingTime()) {
+ if (Flags.sortSectionByTime()) {
creationTime = when;
extras.putBoolean(EXTRA_SHOW_WHEN, true);
}
@@ -2645,7 +2648,7 @@
this.icon = icon;
this.tickerText = tickerText;
this.when = when;
- if (updateRankingTime()) {
+ if (Flags.sortSectionByTime()) {
creationTime = when;
extras.putBoolean(EXTRA_SHOW_WHEN, true);
} else {
@@ -3256,8 +3259,9 @@
boolean mustClearCookie = false;
if (!parcel.hasClassCookie(Notification.class)) {
// This is the "root" notification, and not an "inner" notification (including
- // publicVersion or anything else that might be embedded in extras).
- parcel.setClassCookie(Notification.class, this);
+ // publicVersion or anything else that might be embedded in extras). So we want
+ // to use its token for every inner notification (might be null).
+ parcel.setClassCookie(Notification.class, mAllowlistToken);
mustClearCookie = true;
}
try {
@@ -3266,7 +3270,7 @@
writeToParcelImpl(parcel, flags);
} finally {
if (mustClearCookie) {
- parcel.removeClassCookie(Notification.class, this);
+ parcel.removeClassCookie(Notification.class, mAllowlistToken);
}
}
} else {
@@ -3290,14 +3294,9 @@
parcel.writeInt(1);
if (Flags.secureAllowlistToken()) {
- Notification rootNotification = (Notification) parcel.getClassCookie(
- Notification.class);
- if (rootNotification != null && rootNotification != this) {
- // Always use the same token as the root notification
- parcel.writeStrongBinder(rootNotification.mAllowlistToken);
- } else {
- parcel.writeStrongBinder(mAllowlistToken);
- }
+ // Always use the same token as the root notification (might be null).
+ IBinder rootNotificationToken = (IBinder) parcel.getClassCookie(Notification.class);
+ parcel.writeStrongBinder(rootNotificationToken);
} else {
parcel.writeStrongBinder(mAllowlistToken);
}
@@ -4538,12 +4537,6 @@
*/
@NonNull
public Builder setWhen(long when) {
- if (updateRankingTime()) {
- // don't show a timestamp that's decades old
- if (mN.extras.getBoolean(EXTRA_SHOW_WHEN, true) && when == 0) {
- return this;
- }
- }
mN.when = when;
return this;
}
@@ -5987,21 +5980,22 @@
}
if (mN.extras.getBoolean(EXTRA_SHOW_CHRONOMETER)) {
contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
- contentView.setLong(R.id.chronometer, "setBase",
- mN.when + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
+ contentView.setLong(R.id.chronometer, "setBase", mN.getWhen()
+ + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
contentView.setBoolean(R.id.chronometer, "setStarted", true);
boolean countsDown = mN.extras.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN);
contentView.setChronometerCountDown(R.id.chronometer, countsDown);
setTextViewColorSecondary(contentView, R.id.chronometer, p);
} else {
contentView.setViewVisibility(R.id.time, View.VISIBLE);
- contentView.setLong(R.id.time, "setTime", mN.when);
+ contentView.setLong(R.id.time, "setTime", mN.getWhen());
setTextViewColorSecondary(contentView, R.id.time, p);
}
} else {
// We still want a time to be set but gone, such that we can show and hide it
// on demand in case it's a child notification without anything in the header
- contentView.setLong(R.id.time, "setTime", mN.when != 0 ? mN.when : mN.creationTime);
+ contentView.setLong(R.id.time, "setTime", mN.getWhen() != 0 ? mN.getWhen() :
+ mN.creationTime);
setTextViewColorSecondary(contentView, R.id.time, p);
}
}
@@ -7168,7 +7162,7 @@
}
}
- if (!updateRankingTime()) {
+ if (!Flags.sortSectionByTime()) {
mN.creationTime = System.currentTimeMillis();
}
@@ -7621,10 +7615,29 @@
}
/**
+ * Returns #when, unless it's set to 0, which should be shown as/treated as a 'current'
+ * notification. 0 is treated as a special value because it was special in an old version of
+ * android, and some apps are still (incorrectly) using it.
+ *
+ * @hide
+ */
+ public long getWhen() {
+ if (Flags.sortSectionByTime()) {
+ if (when == 0) {
+ return creationTime;
+ }
+ }
+ return when;
+ }
+
+ /**
* @return true if the notification will show the time; false otherwise
* @hide
*/
public boolean showsTime() {
+ if (Flags.sortSectionByTime()) {
+ return extras.getBoolean(EXTRA_SHOW_WHEN);
+ }
return when != 0 && extras.getBoolean(EXTRA_SHOW_WHEN);
}
@@ -7633,6 +7646,9 @@
* @hide
*/
public boolean showsChronometer() {
+ if (Flags.sortSectionByTime()) {
+ return extras.getBoolean(EXTRA_SHOW_CHRONOMETER);
+ }
return when != 0 && extras.getBoolean(EXTRA_SHOW_CHRONOMETER);
}
@@ -9776,6 +9792,12 @@
* You can opt-out of this behavior by using {@link Notification.Builder#setColorized(boolean)}.
* <p>
*
+ * <p>
+ * Starting at {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM Android V} the
+ * {@link Notification#FLAG_NO_CLEAR NO_CLEAR flag} will be set for valid MediaStyle
+ * notifications.
+ * <p>
+ *
* To use this style with your Notification, feed it to
* {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
* <pre class="prettyprint">
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index f092945..726064e 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -1197,6 +1197,25 @@
/**
* Callback called when a particular foreground service type has timed out.
*
+ * <p>This callback is meant to give the app a small grace period of a few seconds to finish
+ * the foreground service of the associated type - if it fails to do so, the app will be
+ * declared an ANR.
+ *
+ * <p>The foreground service of the associated type can be stopped within the time limit by
+ * {@link android.app.Service#stopSelf()},
+ * {@link android.content.Context#stopService(android.content.Intent)} or their overloads.
+ * {@link android.app.Service#stopForeground(int)} can be used as well, which demotes the
+ * service to a "background" service, which will soon be stopped by the system.
+ *
+ * <p>The specific time limit for each type (if one exists) is mentioned in the documentation
+ * for that foreground service type. See
+ * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC dataSync} for example.
+ *
+ * <p>Note: time limits are restricted to a rolling 24-hour window - for example, if a
+ * foreground service type has a time limit of 6 hours, that time counter begins as soon as the
+ * foreground service starts. This time limit will only be reset once every 24 hours or if the
+ * app comes into the foreground state.
+ *
* @param startId the startId passed to {@link #onStartCommand(Intent, int, int)} when
* the service started.
* @param fgsType the {@link ServiceInfo.ForegroundServiceType foreground service type} which
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 103af4b..8171723 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1814,6 +1814,11 @@
return null;
}
break;
+ case Context.APPWIDGET_SERVICE:
+ if (!hasSystemFeatureOpportunistic(ctx, PackageManager.FEATURE_APP_WIDGETS)) {
+ return null;
+ }
+ break;
}
Slog.wtf(TAG, "Manager wrapper not available: " + name);
return null;
diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig
index e4425ca..8c4667f 100644
--- a/core/java/android/app/activity_manager.aconfig
+++ b/core/java/android/app/activity_manager.aconfig
@@ -40,3 +40,13 @@
description: "Add a new callback in Service to indicate a FGS has reached its timeout."
bug: "317799821"
}
+
+flag {
+ namespace: "system_performance"
+ name: "app_start_info_timestamps"
+ description: "Additional timestamps."
+ bug: "287153617"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/app/admin/EnterprisePlatform_OWNERS b/core/java/android/app/admin/EnterprisePlatform_OWNERS
index 4d1ed590..9da526f 100644
--- a/core/java/android/app/admin/EnterprisePlatform_OWNERS
+++ b/core/java/android/app/admin/EnterprisePlatform_OWNERS
@@ -1,2 +1,3 @@
sandness@google.com #{LAST_RESORT_SUGGESTION}
-scottjonathan@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
+scottjonathan@google.com #{LAST_RESORT_SUGGESTION}
+rubinxu@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index 31c9a258..18914e1 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -275,13 +275,23 @@
}
flag {
- name: "headless_single_user_bad_device_admin_state_fix"
- namespace: "enterprise"
- description: "Fix the bad state in DPMS caused by an earlier bug related to the headless single user change"
- bug: "332477138"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
+ name: "headless_single_user_bad_device_admin_state_fix"
+ namespace: "enterprise"
+ description: "Fix the bad state in DPMS caused by an earlier bug related to the headless single user change"
+ bug: "332477138"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "onboarding_bugreport_storage_bug_fix"
+ namespace: "enterprise"
+ description: "Add a separate storage limit for deferred bugreports"
+ bug: "330177040"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 7ac9547..4f06209 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1348,6 +1348,17 @@
public static final long OVERRIDE_MIN_ASPECT_RATIO = 174042980L; // buganizer id
/**
+ * This change id restricts treatments that force a given min aspect ratio to
+ * only when an app is connected to the camera
+ *
+ * @hide
+ */
+ @ChangeId
+ @Overridable
+ @Disabled
+ public static final long OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA = 325586858L; // buganizer id
+
+ /**
* This change id restricts treatments that force a given min aspect ratio to activities
* whose orientation is fixed to portrait.
*
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index cae4fab..495ae60 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2700,7 +2700,7 @@
/**
* @hide
*/
- @Override protected ApplicationInfo getApplicationInfo() {
+ @Override public ApplicationInfo getApplicationInfo() {
return this;
}
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java
index cc4e9c8..c309129 100644
--- a/core/java/android/content/pm/BaseParceledListSlice.java
+++ b/core/java/android/content/pm/BaseParceledListSlice.java
@@ -45,12 +45,19 @@
private static final String TAG = "ParceledListSlice";
private static final boolean DEBUG = false;
- /*
- * TODO get this number from somewhere else. For now set it to a quarter of
- * the 1MB limit.
- */
private static final int MAX_IPC_SIZE = IBinder.getSuggestedMaxIpcSizeBytes();
+ /**
+ * As of 2024 and for some time, max size has been 64KB. If a single
+ * element is too large, this class will write too big of Parcels,
+ * so log. 64KB/4 is 16KB is still pretty big for a single element
+ * (which could result in a ~64KB + 16KB = 80KB transaction). We may
+ * want to reduce the warning size just in case. Though, 64KB is
+ * already quite large for binder transactions, another strategy may
+ * be needed.
+ */
+ private static final int WARN_ELM_SIZE = MAX_IPC_SIZE / 4;
+
private List<T> mList;
private int mInlineCountLimit = Integer.MAX_VALUE;
@@ -206,13 +213,24 @@
try {
reply.writeNoException();
+
+ // note: this logic ensures if there are enough elements in the list,
+ // we will always write over the max IPC size. This is dangerous
+ // when there are large elements.
while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
reply.writeInt(1);
+ int preWriteSize = reply.dataSize();
+
final T parcelable = mList.get(i);
verifySameType(listElementClass, parcelable.getClass());
writeElement(parcelable, reply, callFlags);
+ int elmSize = reply.dataSize() - preWriteSize;
+ if (elmSize >= WARN_ELM_SIZE) {
+ Log.w(TAG, "Element #" + i + " is " + elmSize + " bytes.");
+ }
+
if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
i++;
}
@@ -223,6 +241,9 @@
if (DEBUG) Log.d(TAG, "Transfer done, clearing mList reference");
mList = null;
}
+ if (reply.dataSize() >= MAX_IPC_SIZE + WARN_ELM_SIZE) {
+ Log.w(TAG, "Overly large reply size: " + reply.dataSize());
+ }
} catch (RuntimeException e) {
if (DEBUG) Log.d(TAG, "Transfer failed, clearing mList reference");
mList = null;
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index ff48ffa..4d9ecc4 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -284,7 +284,7 @@
/**
* @hide
*/
- @Override protected ApplicationInfo getApplicationInfo() {
+ @Override public ApplicationInfo getApplicationInfo() {
return applicationInfo;
}
}
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 1f821b9..51285de 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -511,7 +511,7 @@
*
* @hide
*/
- protected ApplicationInfo getApplicationInfo() {
+ public ApplicationInfo getApplicationInfo() {
return null;
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f5bff9d..83285e0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -62,6 +62,7 @@
import android.content.pm.verify.domain.DomainVerificationManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
@@ -11743,4 +11744,17 @@
throw new UnsupportedOperationException(
"parseAndroidManifest not implemented in subclass");
}
+
+ /**
+ * @param info The {@link ServiceInfo} to pull the attributes from.
+ * @param name The name of the Xml metadata where the attributes are stored.
+ * @param rootTag The root tag of the attributes.
+ * @return A {@link TypedArray} of attributes if successful, {@code null} otherwise.
+ * @hide
+ */
+ public TypedArray extractPackageItemInfoAttributes(PackageItemInfo info, String name,
+ String rootTag, int[] attributes) {
+ throw new UnsupportedOperationException(
+ "parseServiceMetadata not implemented in subclass");
+ }
}
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 6158917..205f1e9 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -240,3 +240,11 @@
bug: "297603927"
is_fixed_read_only: true
}
+
+flag {
+ name: "component_state_changed_metrics"
+ namespace: "package_manager_service"
+ description: "Feature flag to log the metrics when the component state is changed."
+ bug: "316916801"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/database/sqlite/package.html b/core/java/android/database/sqlite/package.html
index f2df536..06f8974 100644
--- a/core/java/android/database/sqlite/package.html
+++ b/core/java/android/database/sqlite/package.html
@@ -17,10 +17,14 @@
<code>platform-tools/</code> folder of your SDK. On the emulator, run the tool
with adb shell, for example, <code>adb shell sqlite3</code>.
-<p>The version of SQLite depends on the version of Android. See the following table:
+<p>The version of SQLite depends on the version of Android. In the past,
+ SQLite upgrades have been delivered as part of a new API level, but more
+ recently SQLite may be upgraded within an API level. See the following
+ table:
<table style="width:auto;">
<tr><th>Android API</th><th>SQLite Version</th></tr>
- <tr><td>LATEST</td><td>3.42.0</td></tr>
+ <tr><td>API 35</td><td>3.44.3</td></tr>
+ <tr><td>API 34</td><td>3.42.0</td></tr>
<tr><td>API 34</td><td>3.39</td></tr>
<tr><td>API 33</td><td>3.32</td></tr>
<tr><td>API 32</td><td>3.32</td></tr>
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index 2ba1d89..ac47c8d 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -34,7 +34,7 @@
*
* @hide
*/
-public interface BiometricFaceConstants {
+public class BiometricFaceConstants {
//
// Accessibility constants
//
@@ -43,12 +43,12 @@
* authentication. Note this is to accommodate people who have limited
* vision.
*/
- int FEATURE_REQUIRE_ATTENTION = 1;
+ public static final int FEATURE_REQUIRE_ATTENTION = 1;
/**
* Require a diverse set of poses during enrollment. Note this is to
* accommodate people with limited mobility.
*/
- int FEATURE_REQUIRE_REQUIRE_DIVERSITY = 2;
+ public static final int FEATURE_REQUIRE_REQUIRE_DIVERSITY = 2;
//
// Error messages from face authentication hardware during initialization, enrollment,
@@ -75,49 +75,49 @@
BIOMETRIC_ERROR_POWER_PRESSED,
})
@Retention(RetentionPolicy.SOURCE)
- @interface FaceError {}
+ public @interface FaceError {}
/**
* The hardware is unavailable. Try again later.
*/
- int FACE_ERROR_HW_UNAVAILABLE = 1;
+ public static final int FACE_ERROR_HW_UNAVAILABLE = 1;
/**
* Error state returned when the sensor was unable to process the current image.
*/
- int FACE_ERROR_UNABLE_TO_PROCESS = 2;
+ public static final int FACE_ERROR_UNABLE_TO_PROCESS = 2;
/**
* Error state returned when the current request has been running too long. This is intended to
* prevent programs from waiting for the face authentication sensor indefinitely. The timeout is
* platform and sensor-specific, but is generally on the order of 30 seconds.
*/
- int FACE_ERROR_TIMEOUT = 3;
+ public static final int FACE_ERROR_TIMEOUT = 3;
/**
* Error state returned for operations like enrollment; the operation cannot be completed
* because there's not enough storage remaining to complete the operation.
*/
- int FACE_ERROR_NO_SPACE = 4;
+ public static final int FACE_ERROR_NO_SPACE = 4;
/**
* The operation was canceled because the face authentication sensor is unavailable. For
* example, this may happen when the user is switched, the device is locked or another pending
* operation prevents or disables it.
*/
- int FACE_ERROR_CANCELED = 5;
+ public static final int FACE_ERROR_CANCELED = 5;
/**
* The {@link FaceManager#remove} call failed. Typically this will happen when the
* provided face id was incorrect.
*/
- int FACE_ERROR_UNABLE_TO_REMOVE = 6;
+ public static final int FACE_ERROR_UNABLE_TO_REMOVE = 6;
/**
* The operation was canceled because the API is locked out due to too many attempts.
* This occurs after 5 failed attempts, and lasts for 30 seconds.
*/
- int FACE_ERROR_LOCKOUT = 7;
+ public static final int FACE_ERROR_LOCKOUT = 7;
/**
* Hardware vendors may extend this list if there are conditions that do not fall under one of
@@ -127,46 +127,46 @@
* expected to show the error message string if they happen, but are advised not to rely on the
* message id since they will be device and vendor-specific
*/
- int FACE_ERROR_VENDOR = 8;
+ public static final int FACE_ERROR_VENDOR = 8;
/**
* The operation was canceled because FACE_ERROR_LOCKOUT occurred too many times.
* Face authentication is disabled until the user unlocks with strong authentication
* (PIN/Pattern/Password)
*/
- int FACE_ERROR_LOCKOUT_PERMANENT = 9;
+ public static final int FACE_ERROR_LOCKOUT_PERMANENT = 9;
/**
* The user canceled the operation. Upon receiving this, applications should use alternate
* authentication (e.g. a password). The application should also provide the means to return
* to face authentication, such as a "use face authentication" button.
*/
- int FACE_ERROR_USER_CANCELED = 10;
+ public static final int FACE_ERROR_USER_CANCELED = 10;
/**
* The user does not have a face enrolled.
*/
- int FACE_ERROR_NOT_ENROLLED = 11;
+ public static final int FACE_ERROR_NOT_ENROLLED = 11;
/**
* The device does not have a face sensor. This message will propagate if the calling app
* ignores the result from PackageManager.hasFeature(FEATURE_FACE) and calls
* this API anyway. Apps should always check for the feature before calling this API.
*/
- int FACE_ERROR_HW_NOT_PRESENT = 12;
+ public static final int FACE_ERROR_HW_NOT_PRESENT = 12;
/**
* The user pressed the negative button. This is a placeholder that is currently only used
* by the support library.
*/
- int FACE_ERROR_NEGATIVE_BUTTON = 13;
+ public static final int FACE_ERROR_NEGATIVE_BUTTON = 13;
/**
* The device does not have pin, pattern, or password set up. See
* {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)} and
* {@link KeyguardManager#isDeviceSecure()}
*/
- int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+ public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
/**
* A security vulnerability has been discovered and the sensor is unavailable until a
@@ -174,30 +174,30 @@
* authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
* sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}.
*/
- int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
+ public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
/**
* Authentication cannot proceed because re-enrollment is required.
*/
- int BIOMETRIC_ERROR_RE_ENROLL = 16;
+ public static final int BIOMETRIC_ERROR_RE_ENROLL = 16;
/**
* Unknown error received from the HAL.
*/
- int FACE_ERROR_UNKNOWN = 17;
+ public static final int FACE_ERROR_UNKNOWN = 17;
/**
* A power press stopped this biometric operation.
* @hide
*/
- int BIOMETRIC_ERROR_POWER_PRESSED = 19;
+ public static final int BIOMETRIC_ERROR_POWER_PRESSED = 19;
/**
* Vendor codes received from the HAL start at 0. Codes that the framework exposes to keyguard
* append this value for some reason. We should probably remove this and just send the actual
* vendor code.
*/
- int FACE_ERROR_VENDOR_BASE = 1000;
+ public static final int FACE_ERROR_VENDOR_BASE = 1000;
//
// Image acquisition messages. These will not be sent to the user, since they conflict with
@@ -232,18 +232,18 @@
FACE_ACQUIRED_DARK_GLASSES_DETECTED,
FACE_ACQUIRED_MOUTH_COVERING_DETECTED})
@Retention(RetentionPolicy.SOURCE)
- @interface FaceAcquired {}
+ public @interface FaceAcquired {}
/**
* The image acquired was good.
*/
- int FACE_ACQUIRED_GOOD = 0;
+ public static final int FACE_ACQUIRED_GOOD = 0;
/**
* The face image was not good enough to process due to a detected condition.
* (See {@link #FACE_ACQUIRED_TOO_BRIGHT or @link #FACE_ACQUIRED_TOO_DARK}).
*/
- int FACE_ACQUIRED_INSUFFICIENT = 1;
+ public static final int FACE_ACQUIRED_INSUFFICIENT = 1;
/**
* The face image was too bright due to too much ambient light.
@@ -252,7 +252,7 @@
* The user is expected to take action to retry in better lighting conditions
* when this is returned.
*/
- int FACE_ACQUIRED_TOO_BRIGHT = 2;
+ public static final int FACE_ACQUIRED_TOO_BRIGHT = 2;
/**
* The face image was too dark due to illumination light obscured.
@@ -261,65 +261,65 @@
* The user is expected to take action to retry in better lighting conditions
* when this is returned.
*/
- int FACE_ACQUIRED_TOO_DARK = 3;
+ public static final int FACE_ACQUIRED_TOO_DARK = 3;
/**
* The detected face is too close to the sensor, and the image can't be processed.
* The user should be informed to move farther from the sensor when this is returned.
*/
- int FACE_ACQUIRED_TOO_CLOSE = 4;
+ public static final int FACE_ACQUIRED_TOO_CLOSE = 4;
/**
* The detected face is too small, as the user might be too far from the sensor.
* The user should be informed to move closer to the sensor when this is returned.
*/
- int FACE_ACQUIRED_TOO_FAR = 5;
+ public static final int FACE_ACQUIRED_TOO_FAR = 5;
/**
* Only the upper part of the face was detected. The sensor field of view is too high.
* The user should be informed to move up with respect to the sensor when this is returned.
*/
- int FACE_ACQUIRED_TOO_HIGH = 6;
+ public static final int FACE_ACQUIRED_TOO_HIGH = 6;
/**
* Only the lower part of the face was detected. The sensor field of view is too low.
* The user should be informed to move down with respect to the sensor when this is returned.
*/
- int FACE_ACQUIRED_TOO_LOW = 7;
+ public static final int FACE_ACQUIRED_TOO_LOW = 7;
/**
* Only the right part of the face was detected. The sensor field of view is too far right.
* The user should be informed to move to the right with respect to the sensor
* when this is returned.
*/
- int FACE_ACQUIRED_TOO_RIGHT = 8;
+ public static final int FACE_ACQUIRED_TOO_RIGHT = 8;
/**
* Only the left part of the face was detected. The sensor field of view is too far left.
* The user should be informed to move to the left with respect to the sensor
* when this is returned.
*/
- int FACE_ACQUIRED_TOO_LEFT = 9;
+ public static final int FACE_ACQUIRED_TOO_LEFT = 9;
/**
* The user's eyes have strayed away from the sensor. If this message is sent, the user should
* be informed to look at the device. If the user can't be found in the frame, one of the other
* acquisition messages should be sent, e.g. FACE_ACQUIRED_NOT_DETECTED.
*/
- int FACE_ACQUIRED_POOR_GAZE = 10;
+ public static final int FACE_ACQUIRED_POOR_GAZE = 10;
/**
* No face was detected in front of the sensor.
* The user should be informed to point the sensor to a face when this is returned.
*/
- int FACE_ACQUIRED_NOT_DETECTED = 11;
+ public static final int FACE_ACQUIRED_NOT_DETECTED = 11;
/**
* Too much motion was detected.
* The user should be informed to keep their face steady relative to the
* sensor.
*/
- int FACE_ACQUIRED_TOO_MUCH_MOTION = 12;
+ public static final int FACE_ACQUIRED_TOO_MUCH_MOTION = 12;
/**
* The sensor needs to be re-calibrated. This is an unexpected condition, and should only be
@@ -327,20 +327,20 @@
* requires user intervention, e.g. re-enrolling. The expected response to this message is to
* direct the user to re-enroll.
*/
- int FACE_ACQUIRED_RECALIBRATE = 13;
+ public static final int FACE_ACQUIRED_RECALIBRATE = 13;
/**
* The face is too different from a previous acquisition. This condition
* only applies to enrollment. This can happen if the user passes the
* device to someone else in the middle of enrollment.
*/
- int FACE_ACQUIRED_TOO_DIFFERENT = 14;
+ public static final int FACE_ACQUIRED_TOO_DIFFERENT = 14;
/**
* The face is too similar to a previous acquisition. This condition only
* applies to enrollment. The user should change their pose.
*/
- int FACE_ACQUIRED_TOO_SIMILAR = 15;
+ public static final int FACE_ACQUIRED_TOO_SIMILAR = 15;
/**
* The magnitude of the pan angle of the user’s face with respect to the sensor’s
@@ -352,7 +352,7 @@
*
* The user should be informed to look more directly at the camera.
*/
- int FACE_ACQUIRED_PAN_TOO_EXTREME = 16;
+ public static final int FACE_ACQUIRED_PAN_TOO_EXTREME = 16;
/**
* The magnitude of the tilt angle of the user’s face with respect to the sensor’s
@@ -363,7 +363,7 @@
*
* The user should be informed to look more directly at the camera.
*/
- int FACE_ACQUIRED_TILT_TOO_EXTREME = 17;
+ public static final int FACE_ACQUIRED_TILT_TOO_EXTREME = 17;
/**
* The magnitude of the roll angle of the user’s face with respect to the sensor’s
@@ -375,7 +375,7 @@
*
* The user should be informed to look more directly at the camera.
*/
- int FACE_ACQUIRED_ROLL_TOO_EXTREME = 18;
+ public static final int FACE_ACQUIRED_ROLL_TOO_EXTREME = 18;
/**
* The user’s face has been obscured by some object.
@@ -383,7 +383,7 @@
* The user should be informed to remove any objects from the line of sight from
* the sensor to the user’s face.
*/
- int FACE_ACQUIRED_FACE_OBSCURED = 19;
+ public static final int FACE_ACQUIRED_FACE_OBSCURED = 19;
/**
* This message represents the earliest message sent at the beginning of the authentication
@@ -393,47 +393,47 @@
* The framework will measure latency based on the time between the last START message and the
* onAuthenticated callback.
*/
- int FACE_ACQUIRED_START = 20;
+ public static final int FACE_ACQUIRED_START = 20;
/**
* The sensor is dirty. The user should be informed to clean the sensor.
*/
- int FACE_ACQUIRED_SENSOR_DIRTY = 21;
+ public static final int FACE_ACQUIRED_SENSOR_DIRTY = 21;
/**
* Hardware vendors may extend this list if there are conditions that do not fall under one of
* the above categories. Vendors are responsible for providing error strings for these errors.
*/
- int FACE_ACQUIRED_VENDOR = 22;
+ public static final int FACE_ACQUIRED_VENDOR = 22;
/**
* Unknown acquired code received from the HAL.
*/
- int FACE_ACQUIRED_UNKNOWN = 23;
+ public static final int FACE_ACQUIRED_UNKNOWN = 23;
/**
* The first frame from the camera has been received.
*/
- int FACE_ACQUIRED_FIRST_FRAME_RECEIVED = 24;
+ public static final int FACE_ACQUIRED_FIRST_FRAME_RECEIVED = 24;
/**
* Dark glasses detected. This can be useful for providing relevant feedback to the user and
* enabling an alternative authentication logic if the implementation supports it.
*/
- int FACE_ACQUIRED_DARK_GLASSES_DETECTED = 25;
+ public static final int FACE_ACQUIRED_DARK_GLASSES_DETECTED = 25;
/**
* A face mask or face covering detected. This can be useful for providing relevant feedback to
* the user and enabling an alternative authentication logic if the implementation supports it.
*/
- int FACE_ACQUIRED_MOUTH_COVERING_DETECTED = 26;
+ public static final int FACE_ACQUIRED_MOUTH_COVERING_DETECTED = 26;
/**
* Vendor codes received from the HAL start at 0. Codes that the framework exposes to keyguard
* append this value for some reason. We should probably remove this and just send the actual
* vendor code.
*/
- int FACE_ACQUIRED_VENDOR_BASE = 1000;
+ public static final int FACE_ACQUIRED_VENDOR_BASE = 1000;
/**
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index c62680f..027d101 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -92,6 +92,7 @@
mTestedUsers = new ArraySet<>();
mUsersCleaningUp = new ArraySet<>();
setTestHalEnabled(true);
+ Log.d(getTag(), "Opening BiometricTestSession");
}
/**
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index c6a8762..342479b 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -5062,21 +5062,29 @@
/**
* <p>The version of the session configuration query
* {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup#isSessionConfigurationSupported }
- * API</p>
+ * and {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup#getSessionCharacteristics }
+ * APIs.</p>
* <p>The possible values in this key correspond to the values defined in
* android.os.Build.VERSION_CODES. Each version defines a set of feature combinations the
* camera device must reliably report whether they are supported via
- * {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup#isSessionConfigurationSupported }
- * API. And the version is always less or equal to android.os.Build.VERSION.SDK_INT.</p>
- * <p>If set to UPSIDE_DOWN_CAKE, this camera device doesn't support
* {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup#isSessionConfigurationSupported }.
- * Calling the method for this camera ID throws an UnsupportedOperationException.</p>
- * <p>If set to VANILLA_ICE_CREAM, the application can call
+ * It also defines the set of session specific keys in CameraCharacteristics when returned from
+ * {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup#getSessionCharacteristics }.
+ * The version is always less or equal to android.os.Build.VERSION.SDK_INT.</p>
+ * <p>If set to UPSIDE_DOWN_CAKE, this camera device doesn't support the
+ * {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup } API.
+ * Trying to create a CameraDeviceSetup instance throws an UnsupportedOperationException.</p>
+ * <p>From VANILLA_ICE_CREAM onwards, the camera compliance tests verify a set of
+ * commonly used SessionConfigurations to ensure that the outputs of
* {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup#isSessionConfigurationSupported }
- * to check if the combinations of below features are supported.</p>
+ * and {@link android.hardware.camera2.CameraDevice.CameraDeviceSetup#getSessionCharacteristics }
+ * are accurate. The application is encouraged to use these SessionConfigurations when turning on
+ * multiple features at the same time.</p>
+ * <p>When set to VANILLA_ICE_CREAM, the combinations of the following configurations are verified
+ * by the compliance tests:</p>
* <ul>
- * <li>A subset of LIMITED-level device stream combinations.</li>
- * </ul>
+ * <li>
+ * <p>A set of commonly used stream combinations:</p>
* <table>
* <thead>
* <tr>
@@ -5084,257 +5092,108 @@
* <th style="text-align: center;">Size</th>
* <th style="text-align: center;">Target 2</th>
* <th style="text-align: center;">Size</th>
- * <th style="text-align: center;">Sample use case(s)</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;">Simple preview, GPU video processing, or no-preview video recording.</td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
* <td style="text-align: center;">S1080P</td>
* <td style="text-align: center;"></td>
* <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
* </tr>
* <tr>
* <td style="text-align: center;">PRIV</td>
* <td style="text-align: center;">S720P</td>
* <td style="text-align: center;"></td>
* <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;">In-application video/image processing.</td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;">Standard still imaging.</td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
* </tr>
* <tr>
* <td style="text-align: center;">PRIV</td>
* <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">MAXIMUM_16_9</td>
+ * </tr>
+ * <tr>
+ * <td style="text-align: center;">PRIV</td>
+ * <td style="text-align: center;">S1080P</td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">UHD</td>
+ * </tr>
+ * <tr>
+ * <td style="text-align: center;">PRIV</td>
+ * <td style="text-align: center;">S1080P</td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">S1440P</td>
+ * </tr>
+ * <tr>
+ * <td style="text-align: center;">PRIV</td>
+ * <td style="text-align: center;">S1080P</td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">S1080P</td>
+ * </tr>
+ * <tr>
+ * <td style="text-align: center;">PRIV</td>
+ * <td style="text-align: center;">S1080P</td>
+ * <td style="text-align: center;">PRIV</td>
+ * <td style="text-align: center;">UHD</td>
* </tr>
* <tr>
* <td style="text-align: center;">PRIV</td>
* <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;"></td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">MAXIMUM_16_9</td>
* </tr>
* <tr>
* <td style="text-align: center;">PRIV</td>
* <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;">In-app processing plus still capture.</td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">MAXIMUM</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;">JPEG</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;">Standard recording.</td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;"></td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">UHD</td>
* </tr>
* <tr>
* <td style="text-align: center;">PRIV</td>
* <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">PREVIEW</td>
- * <td style="text-align: center;">Preview plus in-app processing.</td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1440P</td>
- * <td style="text-align: center;"></td>
- * </tr>
- * <tr>
- * <td style="text-align: center;">PRIV</td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
* <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S1080P</td>
- * <td style="text-align: center;"></td>
* </tr>
* <tr>
* <td style="text-align: center;">PRIV</td>
- * <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;">YUV</td>
- * <td style="text-align: center;">S720P</td>
- * <td style="text-align: center;"></td>
+ * <td style="text-align: center;">XVGA</td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">MAXIMUM_4_3</td>
+ * </tr>
+ * <tr>
+ * <td style="text-align: center;">PRIV</td>
+ * <td style="text-align: center;">S1080P_4_3</td>
+ * <td style="text-align: center;">JPEG/JPEG_R</td>
+ * <td style="text-align: center;">MAXIMUM_4_3</td>
* </tr>
* </tbody>
* </table>
- * <pre><code>- {@code MAXIMUM} size refers to the camera device's maximum output resolution for
- * that format from {@code StreamConfigurationMap#getOutputSizes}. {@code PREVIEW} size
- * refers to the best size match to the device's screen resolution, or to 1080p
- * (@code 1920x1080}, whichever is smaller. Both sizes are guaranteed to be supported.
- *
- * - {@code S1440P} refers to {@code 1920x1440 (4:3)} and {@code 2560x1440 (16:9)}.
- * {@code S1080P} refers to {@code 1440x1080 (4:3)} and {@code 1920x1080 (16:9)}.
- * And {@code S720P} refers to {@code 960x720 (4:3)} and {@code 1280x720 (16:9)}.
- *
- * - If a combination contains a S1440P, S1080P, or S720P stream,
- * both 4:3 and 16:9 aspect ratio sizes can be queried. For example, for the
- * stream combination of {PRIV, S1440P, JPEG, MAXIMUM}, and if MAXIMUM ==
- * 4032 x 3024, the application will be able to query both
- * {PRIV, 1920 x 1440, JPEG, 4032 x 3024} and {PRIV, 2560 x 1440, JPEG, 4032 x 2268}
- * without an exception being thrown.
- * </code></pre>
* <ul>
- * <li>VIDEO_STABILIZATION_MODES: {OFF, PREVIEW}</li>
- * <li>AE_TARGET_FPS_RANGE: { {<em>, 30}, {</em>, 60} }</li>
- * <li>DYNAMIC_RANGE_PROFILE: {STANDARD, HLG10}</li>
+ * <li>{@code MAXIMUM_4_3} refers to the camera device's maximum output resolution with
+ * 4:3 aspect ratio for that format from {@code StreamConfigurationMap#getOutputSizes}.</li>
+ * <li>{@code MAXIMUM_16_9} is the maximum output resolution with 16:9 aspect ratio.</li>
+ * <li>{@code S1440P} refers to {@code 2560x1440 (16:9)}.</li>
+ * <li>{@code S1080P} refers to {@code 1920x1080 (16:9)}.</li>
+ * <li>{@code S720P} refers to {@code 1280x720 (16:9)}.</li>
+ * <li>{@code UHD} refers to {@code 3840x2160 (16:9)}.</li>
+ * <li>{@code XVGA} refers to {@code 1024x768 (4:3)}.</li>
+ * <li>{@code S1080P_43} refers to {@code 1440x1080 (4:3)}.</li>
* </ul>
+ * </li>
+ * <li>
+ * <p>VIDEO_STABILIZATION_MODE: {OFF, PREVIEW}</p>
+ * </li>
+ * <li>
+ * <p>AE_TARGET_FPS_RANGE: { {*, 30}, {*, 60} }</p>
+ * </li>
+ * <li>
+ * <p>DYNAMIC_RANGE_PROFILE: {STANDARD, HLG10}</p>
+ * </li>
+ * </ul>
+ * <p>All of the above configurations can be set up with a SessionConfiguration. The list of
+ * OutputConfiguration contains the stream configurations and DYNAMIC_RANGE_PROFILE, and
+ * the AE_TARGET_FPS_RANGE and VIDEO_STABILIZATION_MODE are set as session parameters.</p>
* <p>This key is available on all devices.</p>
*/
@PublicKey
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index eb644e8..dfbf06b 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -917,8 +917,11 @@
* image. For example, it can be used as a temporary placeholder for the requested capture
* while the final image is being processed. The supported sizes for a still capture's postview
* can be retrieved using
- * {@link CameraExtensionCharacteristics#getPostviewSupportedSizes(int, Size, int)}.
- * The formats of the still capture and postview should be equivalent upon capture request.</p>
+ * {@link CameraExtensionCharacteristics#getPostviewSupportedSizes(int, Size, int)}.</p>
+ *
+ * <p>Starting with Android {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM},
+ * the formats of the still capture and postview are not required to be equivalent upon capture
+ * request.</p>
*
* @param extension the extension type
* @return {@code true} in case postview is supported, {@code false} otherwise
@@ -976,8 +979,7 @@
*
* @param extension the extension type
* @param captureSize size of the still capture for which the postview is requested
- * @param format device-specific extension output format of the still capture and
- * postview
+ * @param format device-specific extension output format of the postview
* @return non-modifiable list of available sizes or an empty list if the format and
* size is not supported.
* @throws IllegalArgumentException in case of unsupported extension or if postview
@@ -1018,8 +1020,8 @@
}
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId, mCharacteristicsMapNative);
- return generateSupportedSizes(extender.getSupportedPostviewResolutions(
- sz), format, streamMap);
+ return getSupportedSizes(extender.getSupportedPostviewResolutions(sz),
+ format);
} else {
Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
initializeExtension(extension);
@@ -1034,15 +1036,13 @@
}
if (format == ImageFormat.YUV_420_888) {
- return generateSupportedSizes(
- extenders.second.getSupportedPostviewResolutions(sz),
- format, streamMap);
+ return getSupportedSizes(
+ extenders.second.getSupportedPostviewResolutions(sz), format);
} else if (format == ImageFormat.JPEG) {
// The framework will perform the additional encoding pass on the
// processed YUV_420 buffers.
- return generateJpegSupportedSizes(
- extenders.second.getSupportedPostviewResolutions(sz),
- streamMap);
+ return getSupportedSizes(
+ extenders.second.getSupportedPostviewResolutions(sz), format);
} else if (format == ImageFormat.JPEG_R || format == ImageFormat.YCBCR_P010) {
// Jpeg_R/UltraHDR + YCBCR_P010 is currently not supported in the basic
// extension case
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
index 875550a..a10e250 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
@@ -36,6 +36,8 @@
import android.util.Log;
import android.view.Surface;
+import com.android.internal.camera.flags.Flags;
+
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Iterator;
@@ -57,6 +59,8 @@
private android.hardware.camera2.extension.Size mResolution = null;
private android.hardware.camera2.extension.Size mPostviewResolution = null;
private int mFormat = -1;
+ private int mPostviewFormat = -1;
+ private int mCaptureFormat = -1;
private Surface mOutputSurface = null;
private ImageWriter mOutputWriter = null;
private Surface mPostviewOutputSurface = null;
@@ -204,10 +208,12 @@
}
public void onOutputSurface(Surface surface, int format) throws RemoteException {
- if (format != ImageFormat.JPEG) {
+ if (!Flags.extension10Bit() && format != ImageFormat.JPEG) {
Log.e(TAG, "Unsupported output format: " + format);
return;
}
+ CameraExtensionUtils.SurfaceInfo surfaceInfo = CameraExtensionUtils.querySurface(surface);
+ mCaptureFormat = surfaceInfo.mFormat;
mOutputSurface = surface;
initializePipeline();
}
@@ -215,10 +221,11 @@
public void onPostviewOutputSurface(Surface surface) throws RemoteException {
CameraExtensionUtils.SurfaceInfo postviewSurfaceInfo =
CameraExtensionUtils.querySurface(surface);
- if (postviewSurfaceInfo.mFormat != ImageFormat.JPEG) {
+ if (!Flags.extension10Bit() && postviewSurfaceInfo.mFormat != ImageFormat.JPEG) {
Log.e(TAG, "Unsupported output format: " + postviewSurfaceInfo.mFormat);
return;
}
+ mPostviewFormat = postviewSurfaceInfo.mFormat;
mPostviewOutputSurface = surface;
initializePostviewPipeline();
}
@@ -233,7 +240,7 @@
}
public void onImageFormatUpdate(int format) throws RemoteException {
- if (format != ImageFormat.YUV_420_888) {
+ if (!Flags.extension10Bit() && format != ImageFormat.YUV_420_888) {
Log.e(TAG, "Unsupported input format: " + format);
return;
}
@@ -244,33 +251,45 @@
private void initializePipeline() throws RemoteException {
if ((mFormat != -1) && (mOutputSurface != null) && (mResolution != null) &&
(mYuvReader == null)) {
- // Jpeg/blobs are expected to be configured with (w*h)x1.5 + 64k Jpeg APP1 segment
- mOutputWriter = ImageWriter.newInstance(mOutputSurface, 1 /*maxImages*/,
- ImageFormat.JPEG,
- (mResolution.width * mResolution.height * 3)/2 + JPEG_APP_SEGMENT_SIZE, 1);
- mYuvReader = ImageReader.newInstance(mResolution.width, mResolution.height, mFormat,
- JPEG_QUEUE_SIZE);
- mYuvReader.setOnImageAvailableListener(
- new YuvCallback(mYuvReader, mOutputWriter), mHandler);
- mProcessor.onOutputSurface(mYuvReader.getSurface(), mFormat);
+ if (Flags.extension10Bit() && mCaptureFormat == ImageFormat.YUV_420_888) {
+ // For the case when postview is JPEG and capture is YUV
+ mProcessor.onOutputSurface(mOutputSurface, mCaptureFormat);
+ } else {
+ // Jpeg/blobs are expected to be configured with (w*h)x1.5 + 64k Jpeg APP1 segment
+ mOutputWriter = ImageWriter.newInstance(mOutputSurface, 1 /*maxImages*/,
+ ImageFormat.JPEG,
+ (mResolution.width * mResolution.height * 3) / 2
+ + JPEG_APP_SEGMENT_SIZE, 1);
+ mYuvReader = ImageReader.newInstance(mResolution.width, mResolution.height,
+ mFormat, JPEG_QUEUE_SIZE);
+ mYuvReader.setOnImageAvailableListener(
+ new YuvCallback(mYuvReader, mOutputWriter), mHandler);
+ mProcessor.onOutputSurface(mYuvReader.getSurface(), mFormat);
+ }
mProcessor.onResolutionUpdate(mResolution, mPostviewResolution);
- mProcessor.onImageFormatUpdate(mFormat);
+ mProcessor.onImageFormatUpdate(ImageFormat.YUV_420_888);
}
}
private void initializePostviewPipeline() throws RemoteException {
if ((mFormat != -1) && (mPostviewOutputSurface != null) && (mPostviewResolution != null)
&& (mPostviewYuvReader == null)) {
- // Jpeg/blobs are expected to be configured with (w*h)x1
- mPostviewOutputWriter = ImageWriter.newInstance(mPostviewOutputSurface, 1/*maxImages*/,
- ImageFormat.JPEG, mPostviewResolution.width * mPostviewResolution.height, 1);
- mPostviewYuvReader = ImageReader.newInstance(mPostviewResolution.width,
- mPostviewResolution.height, mFormat, JPEG_QUEUE_SIZE);
- mPostviewYuvReader.setOnImageAvailableListener(
- new YuvCallback(mPostviewYuvReader, mPostviewOutputWriter), mHandler);
- mProcessor.onPostviewOutputSurface(mPostviewYuvReader.getSurface());
+ if (Flags.extension10Bit() && mPostviewFormat == ImageFormat.YUV_420_888) {
+ // For the case when postview is YUV and capture is JPEG
+ mProcessor.onPostviewOutputSurface(mPostviewOutputSurface);
+ } else {
+ // Jpeg/blobs are expected to be configured with (w*h)x1
+ mPostviewOutputWriter = ImageWriter.newInstance(mPostviewOutputSurface,
+ 1/*maxImages*/, ImageFormat.JPEG,
+ mPostviewResolution.width * mPostviewResolution.height, 1);
+ mPostviewYuvReader = ImageReader.newInstance(mPostviewResolution.width,
+ mPostviewResolution.height, mFormat, JPEG_QUEUE_SIZE);
+ mPostviewYuvReader.setOnImageAvailableListener(
+ new YuvCallback(mPostviewYuvReader, mPostviewOutputWriter), mHandler);
+ mProcessor.onPostviewOutputSurface(mPostviewYuvReader.getSurface());
+ }
mProcessor.onResolutionUpdate(mResolution, mPostviewResolution);
- mProcessor.onImageFormatUpdate(mFormat);
+ mProcessor.onImageFormatUpdate(ImageFormat.YUV_420_888);
}
}
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index c00e610..3ae3199 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -390,7 +390,16 @@
if (surfaceInfo.mFormat == ImageFormat.JPEG) {
mImageJpegProcessor = new CameraExtensionJpegProcessor(mImageProcessor);
mImageProcessor = mImageJpegProcessor;
+ } else if (Flags.extension10Bit() && mClientPostviewSurface != null) {
+ // Handles case when postview is JPEG and capture is YUV
+ CameraExtensionUtils.SurfaceInfo postviewSurfaceInfo =
+ CameraExtensionUtils.querySurface(mClientPostviewSurface);
+ if (postviewSurfaceInfo.mFormat == ImageFormat.JPEG) {
+ mImageJpegProcessor = new CameraExtensionJpegProcessor(mImageProcessor);
+ mImageProcessor = mImageJpegProcessor;
+ }
}
+
mBurstCaptureImageReader = ImageReader.newInstance(surfaceInfo.mWidth,
surfaceInfo.mHeight, CameraExtensionCharacteristics.PROCESSING_INPUT_FORMAT,
mImageExtender.getMaxCaptureStage());
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
index f0c6e2e..40f0477 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
@@ -112,19 +112,30 @@
if (outputConfig == null) return null;
SurfaceInfo surfaceInfo = querySurface(outputConfig.getSurface());
- if (surfaceInfo.mFormat == captureFormat) {
- if (supportedPostviewSizes.containsKey(captureFormat)) {
- Size postviewSize = new Size(surfaceInfo.mWidth, surfaceInfo.mHeight);
- if (supportedPostviewSizes.get(surfaceInfo.mFormat)
- .contains(postviewSize)) {
- return outputConfig.getSurface();
- } else {
- throw new IllegalArgumentException("Postview size not supported!");
- }
+
+ if (Flags.extension10Bit()) {
+ Size postviewSize = new Size(surfaceInfo.mWidth, surfaceInfo.mHeight);
+ if (supportedPostviewSizes.get(surfaceInfo.mFormat)
+ .contains(postviewSize)) {
+ return outputConfig.getSurface();
+ } else {
+ throw new IllegalArgumentException("Postview size not supported!");
}
} else {
- throw new IllegalArgumentException("Postview format should be equivalent to " +
- " the capture format!");
+ if (surfaceInfo.mFormat == captureFormat) {
+ if (supportedPostviewSizes.containsKey(captureFormat)) {
+ Size postviewSize = new Size(surfaceInfo.mWidth, surfaceInfo.mHeight);
+ if (supportedPostviewSizes.get(surfaceInfo.mFormat)
+ .contains(postviewSize)) {
+ return outputConfig.getSurface();
+ } else {
+ throw new IllegalArgumentException("Postview size not supported!");
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Postview format should be equivalent to "
+ + " the capture format!");
+ }
}
return null;
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 2592630..d340f3f 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -20,6 +20,44 @@
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
+import static android.hardware.biometrics.BiometricFaceConstants.BIOMETRIC_ERROR_RE_ENROLL;
+import static android.hardware.biometrics.BiometricFaceConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_GOOD;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_INSUFFICIENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_MOUTH_COVERING_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_NOT_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_PAN_TOO_EXTREME;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_POOR_GAZE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_RECALIBRATE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_ROLL_TOO_EXTREME;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_SENSOR_DIRTY;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TILT_TOO_EXTREME;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_CLOSE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DIFFERENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_FAR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_MUCH_MOTION;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_SIMILAR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_NOT_PRESENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_NOT_ENROLLED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_NO_SPACE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_USER_CANCELED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_VENDOR;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -29,7 +67,6 @@
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.CryptoObject;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
@@ -58,7 +95,7 @@
* @hide
*/
@SystemService(Context.FACE_SERVICE)
-public class FaceManager implements BiometricAuthenticator, BiometricFaceConstants {
+public class FaceManager implements BiometricAuthenticator {
private static final String TAG = "FaceManager";
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 23d6007..00ba3bf 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -133,6 +133,7 @@
int getUserStatusBarIconResId(int userId);
boolean hasBadge(int userId);
int getProfileLabelResId(int userId);
+ int getProfileAccessibilityLabelResId(int userId);
boolean isUserUnlocked(int userId);
boolean isUserRunning(int userId);
boolean isUserForeground(int userId);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 857a85d..d38354d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -18,6 +18,7 @@
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
import static android.app.admin.DevicePolicyResources.Strings.Core.WORK_PROFILE_BADGED_LABEL;
+import static android.app.admin.DevicePolicyResources.Strings.SystemUi.STATUS_BAR_WORK_ICON_ACCESSIBILITY;
import static android.app.admin.DevicePolicyResources.UNDEFINED;
import android.Manifest;
@@ -5954,6 +5955,43 @@
}
/**
+ * Returns the string used to represent the profile associated with the given userId. This
+ * string typically includes the profile name used by accessibility services like TalkBack.
+ * @hide
+ *
+ * @return String representing the accessibility label for the given profile user.
+ *
+ * @throws android.content.res.Resources.NotFoundException if the user does not have a label
+ * defined.
+ */
+ @UserHandleAware(
+ requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+ Manifest.permission.MANAGE_USERS,
+ Manifest.permission.QUERY_USERS,
+ Manifest.permission.INTERACT_ACROSS_USERS})
+ public String getProfileAccessibilityString(int userId) {
+ if (isManagedProfile(mUserId)) {
+ DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ dpm.getResources().getString(
+ STATUS_BAR_WORK_ICON_ACCESSIBILITY,
+ () -> getProfileAccessibilityLabel(userId));
+ }
+ return getProfileAccessibilityLabel(userId);
+ }
+
+ private String getProfileAccessibilityLabel(int userId) {
+ try {
+ final int resourceId = mService.getProfileAccessibilityLabelResId(userId);
+ return Resources.getSystem().getString(resourceId);
+ } catch (Resources.NotFoundException nfe) {
+ Log.e(TAG, "Accessibility label not defined for user " + userId);
+ throw nfe;
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* If the user is a {@link UserManager#isProfile profile}, checks if the user
* shares media with its parent user (the user that created this profile).
* Returns false for any other type of user.
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 6b5e17d..b588308 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -180,3 +180,11 @@
description: "Use runtime permission state to determine appop state"
bug: "266164193"
}
+
+flag {
+ name: "device_id_in_op_proxy_info_enabled"
+ is_fixed_read_only: true
+ namespace: "permissions"
+ description: "Enable getDeviceId API in OpEventProxyInfo"
+ bug: "337340961"
+}
\ No newline at end of file
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 095ab70..e6ddf35 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1736,6 +1736,24 @@
"android.settings.NETWORK_OPERATOR_SETTINGS";
/**
+ * Activity Action: Show settings for selecting the network provider.
+ * <p>
+ * In some cases, a matching Activity may not be provided, so ensure you
+ * safeguard against this.
+ * <p>
+ * Access to this preference can be customized via Settings' app.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NETWORK_PROVIDER_SETTINGS =
+ "android.settings.NETWORK_PROVIDER_SETTINGS";
+
+ /**
* Activity Action: Show settings for selection of 2G/3G.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -8501,7 +8519,8 @@
/**
* Setting specifying the accessibility services, accessibility shortcut targets,
- * or features to be toggled via the accessibility button in the navigation bar.
+ * or features to be toggled via the accessibility button in the navigation bar,
+ * or the floating accessibility button.
*
* <p> This is a colon-separated string list which contains the flattened
* {@link ComponentName} and the class name of a system class implementing a supported
@@ -8513,7 +8532,7 @@
/**
* Setting specifying the accessibility services, shortcut targets or features
- * to be toggled via the floating accessibility menu
+ * to be toggled via the gesture shortcut
*
* <p> This is a colon-separated string list which contains the flattened
* {@link ComponentName} and the class name of a system class
@@ -8521,8 +8540,8 @@
* @hide
*/
@Readable
- public static final String ACCESSIBILITY_FLOATING_MENU_TARGETS =
- "accessibility_floating_menu_targets";
+ public static final String ACCESSIBILITY_GESTURE_TARGETS =
+ "accessibility_gesture_targets";
/**
* Setting specifying the accessibility services, accessibility shortcut targets,
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 02e787b..51758aa 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -43,6 +43,13 @@
}
flag {
+ name: "unlocked_storage_api"
+ namespace: "hardware_backed_security"
+ description: "Feature flag for unlocked-only storage API"
+ bug: "325129836"
+}
+
+flag {
name: "deprecate_fsv_sig"
namespace: "hardware_backed_security"
description: "Feature flag for deprecating .fsv_sig"
diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java
index a389223..7487d90 100644
--- a/core/java/android/service/dreams/DreamActivity.java
+++ b/core/java/android/service/dreams/DreamActivity.java
@@ -18,9 +18,12 @@
import android.annotation.Nullable;
import android.app.Activity;
+import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* The Activity used by the {@link DreamService} to draw screensaver content
* on the screen. This activity runs in dream application's process, but is started by a
@@ -41,6 +44,7 @@
*
* @hide
*/
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class DreamActivity extends Activity {
static final String EXTRA_CALLBACK = "binder";
static final String EXTRA_DREAM_TITLE = "title";
@@ -53,19 +57,55 @@
public void onCreate(@Nullable Bundle bundle) {
super.onCreate(bundle);
- final String title = getIntent().getStringExtra(EXTRA_DREAM_TITLE);
+ final String title = getTitle(getIntent());
if (!TextUtils.isEmpty(title)) {
setTitle(title);
}
- final Object callback = getIntent().getExtras().getBinder(EXTRA_CALLBACK);
- if (callback instanceof DreamService.DreamActivityCallbacks) {
- mCallback = (DreamService.DreamActivityCallbacks) callback;
- mCallback.onActivityCreated(this);
- } else {
- mCallback = null;
+ mCallback = getCallback(getIntent());
+
+ if (mCallback == null) {
finishAndRemoveTask();
+ return;
}
+
+ mCallback.onActivityCreated(this);
+ }
+
+ /**
+ * Sets the title of the dream in the intent for starting the {@link DreamActivity}.
+ */
+ public static void setTitle(Intent intent, CharSequence title) {
+ if (TextUtils.isEmpty(title)) {
+ return;
+ }
+
+ intent.putExtra(DreamActivity.EXTRA_DREAM_TITLE, title);
+ }
+
+ /**
+ * Gets the title of the dream from the intent used to start the {@link DreamActivity}.
+ */
+ public static String getTitle(Intent intent) {
+ return intent.getStringExtra(EXTRA_DREAM_TITLE);
+ }
+
+ /**
+ * Sets the dream callback in the intent for starting the {@link DreamActivity}.
+ */
+ public static void setCallback(Intent intent, DreamService.DreamActivityCallbacks callback) {
+ intent.putExtra(DreamActivity.EXTRA_CALLBACK, callback);
+ }
+
+ /**
+ * Retrieves the dream callback from the intent used to start the {@link DreamActivity}.
+ */
+ public static DreamService.DreamActivityCallbacks getCallback(Intent intent) {
+ final Object binder = intent.getExtras().getBinder(EXTRA_CALLBACK);
+
+ return (binder instanceof DreamService.DreamActivityCallbacks)
+ ? (DreamService.DreamActivityCallbacks) binder
+ : null;
}
@Override
diff --git a/core/java/android/service/dreams/DreamOverlayConnectionHandler.java b/core/java/android/service/dreams/DreamOverlayConnectionHandler.java
index cafe02a..85a13c7 100644
--- a/core/java/android/service/dreams/DreamOverlayConnectionHandler.java
+++ b/core/java/android/service/dreams/DreamOverlayConnectionHandler.java
@@ -39,7 +39,7 @@
*
* @hide
*/
-@VisibleForTesting
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public final class DreamOverlayConnectionHandler {
private static final String TAG = "DreamOverlayConnection";
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 5da0cb4..17d2790 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -16,6 +16,7 @@
package android.service.dreams;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -84,7 +85,14 @@
mService.comeToFront(this);
}
- private void onExitRequested() {
+ @Override
+ public void onWakeRequested() {
+ if (Flags.dreamWakeRedirect()) {
+ mService.onWakeRequested();
+ }
+ }
+
+ private void requestExit() {
try {
mDreamOverlayCallback.onExitRequested();
} catch (RemoteException e) {
@@ -92,6 +100,14 @@
}
}
+ private void redirectWake(boolean redirect) {
+ try {
+ mDreamOverlayCallback.onRedirectWake(redirect);
+ } catch (RemoteException e) {
+ Log.e(TAG, "could not request redirect wake", e);
+ }
+ }
+
private boolean shouldShowComplications() {
return mShowComplications;
}
@@ -229,7 +245,35 @@
throw new IllegalStateException("requested exit with no dream present");
}
- mCurrentClient.onExitRequested();
+ mCurrentClient.requestExit();
+ }
+
+ /**
+ * Called to inform the dream to redirect waking to this overlay rather than exiting.
+ * @param redirect {@code true} if waking up should be redirected. {@code false} otherwise.
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_DREAM_WAKE_REDIRECT)
+ public final void redirectWake(boolean redirect) {
+ if (!Flags.dreamWakeRedirect()) {
+ return;
+ }
+
+ if (mCurrentClient == null) {
+ throw new IllegalStateException("redirected wake with no dream present");
+ }
+
+ mCurrentClient.redirectWake(redirect);
+ }
+
+ /**
+ * Invoked when the dream has requested to exit. This is only called if the dream overlay
+ * has explicitly requested exits to be redirected via {@link #redirectWake(boolean)}.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_DREAM_WAKE_REDIRECT)
+ public void onWakeRequested() {
}
/**
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index c26d83c..5f6bdbf 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -41,7 +41,6 @@
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Build;
@@ -54,11 +53,9 @@
import android.os.ServiceManager;
import android.service.controls.flags.Flags;
import android.service.dreams.utils.DreamAccessibility;
-import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
-import android.util.Xml;
import android.view.ActionMode;
import android.view.Display;
import android.view.KeyEvent;
@@ -75,13 +72,10 @@
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.FileDescriptor;
-import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -200,13 +194,6 @@
"android.service.dreams.DreamService";
/**
- * The name of the extra where the dream overlay component is stored.
- * @hide
- */
- public static final String EXTRA_DREAM_OVERLAY_COMPONENT =
- "android.service.dream.DreamService.dream_overlay_component";
-
- /**
* Name under which a Dream publishes information about itself.
* This meta-data must reference an XML resource containing
* a <code><{@link android.R.styleable#Dream dream}></code>
@@ -230,6 +217,7 @@
* The default value for dream category
* @hide
*/
+ @VisibleForTesting
public static final int DREAM_CATEGORY_DEFAULT = 0;
/**
@@ -253,8 +241,14 @@
@Retention(RetentionPolicy.SOURCE)
@interface DreamCategory {}
+ /**
+ * The name of the extra where the dream overlay component is stored.
+ */
+ static final String EXTRA_DREAM_OVERLAY_COMPONENT =
+ "android.service.dream.DreamService.dream_overlay_component";
+
private final IDreamManager mDreamManager;
- private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final Handler mHandler;
private IBinder mDreamToken;
private Window mWindow;
private Activity mActivity;
@@ -287,9 +281,128 @@
private Integer mTrackingConfirmKey = null;
+ private boolean mRedirectWake;
+
+ private final Injector mInjector;
+
+ /**
+ * A helper object to inject dependencies into {@link DreamService}.
+ * @hide
+ */
+ @VisibleForTesting
+ public interface Injector {
+ /** Initializes the Injector */
+ void init(Context context);
+
+ /** Creates and returns the dream overlay connection */
+ DreamOverlayConnectionHandler createOverlayConnection(ComponentName overlayComponent);
+
+ /** Returns the {@link DreamActivity} component */
+ ComponentName getDreamActivityComponent();
+
+ /** Returns the dream component */
+ ComponentName getDreamComponent();
+
+ /** Returns the dream package name */
+ String getDreamPackageName();
+
+ /** Returns the {@link DreamManager} */
+ IDreamManager getDreamManager();
+
+ /** Returns the associated service info */
+ ServiceInfo getServiceInfo();
+
+ /** Returns the handler to be used for any posted operation */
+ Handler getHandler();
+
+ /** Returns the package manager */
+ PackageManager getPackageManager();
+
+ /** Returns the resources */
+ Resources getResources();
+ }
+
+ private static final class DefaultInjector implements Injector {
+ private Context mContext;
+ private Class<?> mClassName;
+
+ public void init(Context context) {
+ mContext = context;
+ mClassName = context.getClass();
+ }
+
+ @Override
+ public DreamOverlayConnectionHandler createOverlayConnection(
+ ComponentName overlayComponent) {
+ final Resources resources = mContext.getResources();
+
+ return new DreamOverlayConnectionHandler(
+ /* context= */ mContext,
+ Looper.getMainLooper(),
+ new Intent().setComponent(overlayComponent),
+ resources.getInteger(R.integer.config_minDreamOverlayDurationMs),
+ resources.getInteger(R.integer.config_dreamOverlayMaxReconnectAttempts),
+ resources.getInteger(R.integer.config_dreamOverlayReconnectTimeoutMs));
+ }
+
+ @Override
+ public ComponentName getDreamActivityComponent() {
+ return new ComponentName(mContext, DreamActivity.class);
+ }
+
+ @Override
+ public ComponentName getDreamComponent() {
+ return new ComponentName(mContext, mClassName);
+ }
+
+ @Override
+ public String getDreamPackageName() {
+ return mContext.getApplicationContext().getPackageName();
+ }
+
+ @Override
+ public IDreamManager getDreamManager() {
+ return IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+ }
+
+ @Override
+ public ServiceInfo getServiceInfo() {
+ return fetchServiceInfo(mContext, getDreamComponent());
+ }
+
+ @Override
+ public Handler getHandler() {
+ return new Handler(Looper.getMainLooper());
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mContext.getPackageManager();
+ }
+
+ @Override
+ public Resources getResources() {
+ return mContext.getResources();
+ }
+
+ }
public DreamService() {
- mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+ this(new DefaultInjector());
+ }
+
+ /**
+ * Constructor for test purposes.
+ *
+ * @param injector used for providing dependencies
+ * @hide
+ */
+ @VisibleForTesting
+ public DreamService(Injector injector) {
+ mInjector = injector;
+ mInjector.init(this);
+ mDreamManager = mInjector.getDreamManager();
+ mHandler = mInjector.getHandler();
}
/**
@@ -997,15 +1110,20 @@
public void onCreate() {
if (mDebug) Slog.v(mTag, "onCreate()");
- mDreamComponent = new ComponentName(this, getClass());
- mShouldShowComplications = fetchShouldShowComplications(this /*context*/,
- fetchServiceInfo(this /*context*/, mDreamComponent));
+ mDreamComponent = mInjector.getDreamComponent();
+ mShouldShowComplications = fetchShouldShowComplications(mInjector.getPackageManager(),
+ mInjector.getServiceInfo());
mOverlayCallback = new IDreamOverlayCallback.Stub() {
@Override
public void onExitRequested() {
// Simply finish dream when exit is requested.
mHandler.post(() -> finish());
}
+
+ @Override
+ public void onRedirectWake(boolean redirect) {
+ mRedirectWake = redirect;
+ }
};
super.onCreate();
@@ -1066,16 +1184,7 @@
// Connect to the overlay service if present.
if (!mWindowless && overlayComponent != null) {
- final Resources resources = getResources();
- final Intent overlayIntent = new Intent().setComponent(overlayComponent);
-
- mOverlayConnection = new DreamOverlayConnectionHandler(
- /* context= */ this,
- Looper.getMainLooper(),
- overlayIntent,
- resources.getInteger(R.integer.config_minDreamOverlayDurationMs),
- resources.getInteger(R.integer.config_dreamOverlayMaxReconnectAttempts),
- resources.getInteger(R.integer.config_dreamOverlayReconnectTimeoutMs));
+ mOverlayConnection = mInjector.createOverlayConnection(overlayComponent);
if (!mOverlayConnection.bind()) {
// Binding failed.
@@ -1181,6 +1290,18 @@
+ ", mFinished=" + mFinished);
}
+ if (!fromSystem && mOverlayConnection != null && mRedirectWake) {
+ mOverlayConnection.addConsumer(overlay -> {
+ try {
+ overlay.onWakeRequested();
+ } catch (RemoteException e) {
+ Log.e(mTag, "could not inform overlay of dream wakeup:" + e);
+ }
+ });
+
+ return;
+ }
+
if (!mWaking && !mFinished) {
mWaking = true;
@@ -1242,63 +1363,42 @@
@TestApi
public static DreamMetadata getDreamMetadata(@NonNull Context context,
@Nullable ServiceInfo serviceInfo) {
- if (serviceInfo == null) return null;
-
- final PackageManager pm = context.getPackageManager();
-
- try (TypedArray rawMetadata = readMetadata(pm, serviceInfo)) {
- if (rawMetadata == null) return null;
- return new DreamMetadata(
- convertToComponentName(
- rawMetadata.getString(
- com.android.internal.R.styleable.Dream_settingsActivity), serviceInfo),
- rawMetadata.getDrawable(
- com.android.internal.R.styleable.Dream_previewImage),
- rawMetadata.getBoolean(R.styleable.Dream_showClockAndComplications,
- DEFAULT_SHOW_COMPLICATIONS),
- rawMetadata.getInt(R.styleable.Dream_dreamCategory, DREAM_CATEGORY_DEFAULT)
- );
- }
+ return getDreamMetadata(context.getPackageManager(), serviceInfo);
}
/**
- * Returns the raw XML metadata fetched from the {@link ServiceInfo}.
+ * Parses and returns metadata of the dream service indicated by the service info. Returns null
+ * if metadata cannot be found.
*
- * Returns <code>null</code> if the {@link ServiceInfo} doesn't contain valid dream metadata.
+ * Note that {@link ServiceInfo} must be fetched with {@link PackageManager#GET_META_DATA} flag.
+ *
+ * @hide
*/
@Nullable
- private static TypedArray readMetadata(PackageManager pm, ServiceInfo serviceInfo) {
- if (serviceInfo == null || serviceInfo.metaData == null) {
- return null;
- }
+ public static DreamMetadata getDreamMetadata(@NonNull PackageManager packageManager,
+ @Nullable ServiceInfo serviceInfo) {
+ if (serviceInfo == null) return null;
- try (XmlResourceParser parser =
- serviceInfo.loadXmlMetaData(pm, DreamService.DREAM_META_DATA)) {
- if (parser == null) {
- if (DEBUG) Log.w(TAG, "No " + DreamService.DREAM_META_DATA + " metadata");
+ try (TypedArray rawMetadata = packageManager.extractPackageItemInfoAttributes(serviceInfo,
+ DreamService.DREAM_META_DATA, DREAM_META_DATA_ROOT_TAG,
+ com.android.internal.R.styleable.Dream)) {
+ if (rawMetadata == null) return null;
+ try {
+ return new DreamMetadata(
+ convertToComponentName(
+ rawMetadata.getString(
+ com.android.internal.R.styleable.Dream_settingsActivity),
+ serviceInfo),
+ rawMetadata.getDrawable(
+ com.android.internal.R.styleable.Dream_previewImage),
+ rawMetadata.getBoolean(R.styleable.Dream_showClockAndComplications,
+ DEFAULT_SHOW_COMPLICATIONS),
+ rawMetadata.getInt(R.styleable.Dream_dreamCategory, DREAM_CATEGORY_DEFAULT)
+ );
+ } catch (Exception exception) {
+ Log.e(TAG, "Failed to create read metadata", exception);
return null;
}
-
- final AttributeSet attrs = Xml.asAttributeSet(parser);
- while (true) {
- final int type = parser.next();
- if (type == XmlPullParser.END_DOCUMENT || type == XmlPullParser.START_TAG) {
- break;
- }
- }
-
- if (!parser.getName().equals(DREAM_META_DATA_ROOT_TAG)) {
- if (DEBUG) {
- Log.w(TAG, "Metadata does not start with " + DREAM_META_DATA_ROOT_TAG + " tag");
- }
- return null;
- }
-
- return pm.getResourcesForApplication(serviceInfo.applicationInfo).obtainAttributes(
- attrs, com.android.internal.R.styleable.Dream);
- } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) {
- if (DEBUG) Log.e(TAG, "Error parsing: " + serviceInfo.packageName, e);
- return null;
}
}
@@ -1406,14 +1506,16 @@
// for the DreamActivity to report onActivityCreated via
// DreamServiceWrapper.onActivityCreated.
if (!mWindowless) {
- Intent i = new Intent(this, DreamActivity.class);
- i.setPackage(getApplicationContext().getPackageName());
+ Intent i = new Intent();
+ i.setComponent(mInjector.getDreamActivityComponent());
+ i.setPackage(mInjector.getDreamPackageName());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
- i.putExtra(DreamActivity.EXTRA_CALLBACK, new DreamActivityCallbacks(mDreamToken));
- final ServiceInfo serviceInfo = fetchServiceInfo(this,
- new ComponentName(this, getClass()));
- i.putExtra(DreamActivity.EXTRA_DREAM_TITLE,
- fetchDreamLabel(this, serviceInfo, isPreviewMode));
+ DreamActivity.setCallback(i, new DreamActivityCallbacks(mDreamToken));
+ final ServiceInfo serviceInfo = mInjector.getServiceInfo();
+ final CharSequence title = fetchDreamLabel(mInjector.getPackageManager(),
+ mInjector.getResources(), serviceInfo, isPreviewMode);
+
+ DreamActivity.setTitle(i, title);
try {
mDreamManager.startDreamActivity(i);
@@ -1539,9 +1641,9 @@
* the dream should show complications on the overlay. If not defined, returns
* {@link DreamService#DEFAULT_SHOW_COMPLICATIONS}.
*/
- private static boolean fetchShouldShowComplications(Context context,
+ private static boolean fetchShouldShowComplications(@NonNull PackageManager packageManager,
@Nullable ServiceInfo serviceInfo) {
- final DreamMetadata metadata = getDreamMetadata(context, serviceInfo);
+ final DreamMetadata metadata = getDreamMetadata(packageManager, serviceInfo);
if (metadata != null) {
return metadata.showComplications;
}
@@ -1549,19 +1651,20 @@
}
@Nullable
- private static CharSequence fetchDreamLabel(Context context,
+ private static CharSequence fetchDreamLabel(
+ PackageManager pm,
+ Resources resources,
@Nullable ServiceInfo serviceInfo,
boolean isPreviewMode) {
if (serviceInfo == null) {
return null;
}
- final PackageManager pm = context.getPackageManager();
final CharSequence dreamLabel = serviceInfo.loadLabel(pm);
if (!isPreviewMode || dreamLabel == null) {
return dreamLabel;
}
// When in preview mode, return a special label indicating the dream is in preview.
- return context.getResources().getString(R.string.dream_preview_title, dreamLabel);
+ return resources.getString(R.string.dream_preview_title, dreamLabel);
}
@Nullable
@@ -1643,14 +1746,16 @@
}
/** @hide */
- final class DreamActivityCallbacks extends Binder {
+ @VisibleForTesting
+ public final class DreamActivityCallbacks extends Binder {
private final IBinder mActivityDreamToken;
DreamActivityCallbacks(IBinder token) {
mActivityDreamToken = token;
}
- void onActivityCreated(DreamActivity activity) {
+ /** Callback when the {@link DreamActivity} has been created */
+ public void onActivityCreated(DreamActivity activity) {
if (mActivityDreamToken != mDreamToken || mFinished) {
Slog.d(TAG, "DreamActivity was created after the dream was finished or "
+ "a new dream started, finishing DreamActivity");
@@ -1672,8 +1777,8 @@
onWindowCreated(activity.getWindow());
}
- // If DreamActivity is destroyed, wake up from Dream.
- void onActivityDestroyed() {
+ /** Callback when the {@link DreamActivity} has been destroyed */
+ public void onActivityDestroyed() {
mActivity = null;
mWindow = null;
detach();
@@ -1685,6 +1790,7 @@
*
* @hide
*/
+ @VisibleForTesting
@TestApi
public static final class DreamMetadata {
@Nullable
@@ -1700,7 +1806,11 @@
@FlaggedApi(Flags.FLAG_HOME_PANEL_DREAM)
public final int dreamCategory;
- DreamMetadata(
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public DreamMetadata(
ComponentName settingsActivity,
Drawable previewImage,
boolean showComplications,
@@ -1715,4 +1825,14 @@
}
}
}
+
+ /**
+ * Sets the dream overlay component to be used by the dream.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static void setDreamOverlayComponent(Intent intent, ComponentName component) {
+ intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, component);
+ }
}
diff --git a/core/java/android/service/dreams/IDreamOverlayCallback.aidl b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
index ec76a33..fae4780 100644
--- a/core/java/android/service/dreams/IDreamOverlayCallback.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
@@ -23,9 +23,14 @@
*
* @hide
*/
-interface IDreamOverlayCallback {
+oneway interface IDreamOverlayCallback {
/**
* Invoked to request the dream exit.
*/
void onExitRequested();
+
+ /**
+ * Invoked to redirect wake requests to overlay instead.
+ */
+ void onRedirectWake(boolean redirect);
}
\ No newline at end of file
diff --git a/core/java/android/service/dreams/IDreamOverlayClient.aidl b/core/java/android/service/dreams/IDreamOverlayClient.aidl
index 5054d4d..0eb15a0 100644
--- a/core/java/android/service/dreams/IDreamOverlayClient.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayClient.aidl
@@ -43,6 +43,9 @@
/** Called when the dream has ended. */
void endDream();
+ /** Called when wake up has been redirected to the overlay. */
+ void onWakeRequested();
+
/** Called when the dream is coming to the front. */
void comeToFront();
}
diff --git a/core/java/android/service/dreams/flags.aconfig b/core/java/android/service/dreams/flags.aconfig
index 0a458bc..a42eaff 100644
--- a/core/java/android/service/dreams/flags.aconfig
+++ b/core/java/android/service/dreams/flags.aconfig
@@ -21,6 +21,24 @@
}
flag {
+ name: "dream_wake_redirect"
+ namespace: "systemui"
+ description: "This flag enables using a host to handle displaying a dream's overlay rather than "
+ "relying on the dream's window"
+ bug: "334083490"
+}
+
+flag {
+ name: "dismiss_dream_on_keyguard_dismiss"
+ namespace: "systemui"
+ description: "Dismisses the dream in the keyguard-going-away transition, preventing it from being visible"
+ bug: "333829441"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "dream_tracks_focus"
namespace: "communal"
description: "This flag enables the ability for dreams to track whether or not they have focus"
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 582c90f..d174bef 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -30,6 +30,7 @@
import static com.android.window.flags.Flags.FLAG_OFFLOAD_COLOR_EXTRACTION;
import static com.android.window.flags.Flags.noConsecutiveVisibilityEvents;
import static com.android.window.flags.Flags.offloadColorExtraction;
+import static com.android.window.flags.Flags.windowSessionRelayoutInfo;
import android.animation.AnimationHandler;
import android.animation.Animator;
@@ -105,6 +106,7 @@
import android.view.WindowLayout;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.WindowRelayoutResult;
import android.window.ActivityWindowInfo;
import android.window.ClientWindowFrames;
import android.window.ScreenCapture;
@@ -299,7 +301,14 @@
final InsetsState mInsetsState = new InsetsState();
final InsetsSourceControl.Array mTempControls = new InsetsSourceControl.Array();
final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
- final Bundle mSyncSeqIdBundle = new Bundle();
+ final Bundle mSyncSeqIdBundle = windowSessionRelayoutInfo() ? null : new Bundle();
+
+ SurfaceControl mSurfaceControl = new SurfaceControl();
+ WindowRelayoutResult mRelayoutResult = windowSessionRelayoutInfo()
+ ? new WindowRelayoutResult(mWinFrames, mMergedConfiguration, mSurfaceControl,
+ mInsetsState, mTempControls)
+ : null;
+
private final Point mSurfaceSize = new Point();
private final Point mLastSurfaceSize = new Point();
private final Matrix mTmpMatrix = new Matrix();
@@ -357,8 +366,6 @@
private float mWallpaperDimAmount = 0f;
private float mPreviousWallpaperDimAmount = mWallpaperDimAmount;
private float mDefaultDimAmount = 0.05f;
-
- SurfaceControl mSurfaceControl = new SurfaceControl();
SurfaceControl mBbqSurfaceControl;
BLASTBufferQueue mBlastBufferQueue;
private SurfaceControl mScreenshotSurfaceControl;
@@ -1268,9 +1275,15 @@
} else {
mLayout.surfaceInsets.set(0, 0, 0, 0);
}
- final int relayoutResult = mSession.relayout(mWindow, mLayout, mWidth, mHeight,
- View.VISIBLE, 0, 0, 0, mWinFrames, mMergedConfiguration,
- mSurfaceControl, mInsetsState, mTempControls, mSyncSeqIdBundle);
+ final int relayoutResult;
+ if (windowSessionRelayoutInfo()) {
+ relayoutResult = mSession.relayout(mWindow, mLayout, mWidth, mHeight,
+ View.VISIBLE, 0, 0, 0, mRelayoutResult);
+ } else {
+ relayoutResult = mSession.relayoutLegacy(mWindow, mLayout, mWidth, mHeight,
+ View.VISIBLE, 0, 0, 0, mWinFrames, mMergedConfiguration,
+ mSurfaceControl, mInsetsState, mTempControls, mSyncSeqIdBundle);
+ }
final Rect outMaxBounds = mMergedConfiguration.getMergedConfiguration()
.windowConfiguration.getMaxBounds();
if (!outMaxBounds.equals(maxBounds)) {
@@ -2364,6 +2377,7 @@
if (mSurfaceControl != null) {
mSurfaceControl.release();
mSurfaceControl = null;
+ mRelayoutResult = null;
}
}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 8dee4b1..c674968 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -70,6 +70,11 @@
* For text that will not change, use a {@link StaticLayout}.
*/
public abstract class Layout {
+
+ // These should match the constants in framework/base/libs/hwui/hwui/DrawTextFunctor.h
+ private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX = 4f;
+ private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR = 0.2f;
+
/** @hide */
@IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
LineBreaker.BREAK_STRATEGY_SIMPLE,
@@ -494,9 +499,9 @@
drawText(canvas, firstLine, lastLine);
- // Since high contrast text draws a solid rectangle background behind the text, it covers up
- // the highlights and selections. In this case we draw over the top of the text with a
- // blend mode that ensures the text stays high-contrast.
+ // Since high contrast text draws a thick border on the text, the highlight actually makes
+ // it harder to read. In this case we draw over the top of the text with a blend mode that
+ // ensures the text stays high-contrast.
if (shouldDrawHighlightsOnTop(canvas)) {
drawHighlights(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint,
cursorOffsetVertical, firstLine, lastLine);
@@ -922,6 +927,9 @@
public void drawBackground(
@NonNull Canvas canvas,
int firstLine, int lastLine) {
+
+ drawHighContrastBackground(canvas, firstLine, lastLine);
+
// First, draw LineBackgroundSpans.
// LineBackgroundSpans know nothing about the alignment, margins, or
// direction of the layout or line. XXX: Should they?
@@ -988,6 +996,66 @@
}
/**
+ * Draws a solid rectangle behind the text, the same color as the high contrast stroke border,
+ * to make it even easier to read.
+ *
+ * <p>We draw it here instead of in DrawTextFunctor so that multiple spans don't draw
+ * backgrounds over each other's text.
+ */
+ private void drawHighContrastBackground(@NonNull Canvas canvas, int firstLine, int lastLine) {
+ if (!shouldDrawHighlightsOnTop(canvas)) {
+ return;
+ }
+
+ var padding = Math.max(HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX,
+ mPaint.getTextSize() * HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR);
+
+ var bgPaint = mWorkPlainPaint;
+ bgPaint.reset();
+ bgPaint.setColor(isHighContrastTextDark() ? Color.WHITE : Color.BLACK);
+ bgPaint.setStyle(Paint.Style.FILL);
+
+ int start = getLineStart(firstLine);
+ int end = getLineEnd(lastLine);
+ // Draw a separate background rectangle for each line of text, that only surrounds the
+ // characters on that line.
+ forEachCharacterBounds(
+ start,
+ end,
+ firstLine,
+ lastLine,
+ new CharacterBoundsListener() {
+ int mLastLineNum = -1;
+ final RectF mLineBackground = new RectF();
+
+ @Override
+ public void onCharacterBounds(int index, int lineNum, float left, float top,
+ float right, float bottom) {
+ if (lineNum != mLastLineNum) {
+ drawRect();
+ mLineBackground.set(left, top, right, bottom);
+ mLastLineNum = lineNum;
+ } else {
+ mLineBackground.union(left, top, right, bottom);
+ }
+ }
+
+ @Override
+ public void onEnd() {
+ drawRect();
+ }
+
+ private void drawRect() {
+ if (!mLineBackground.isEmpty()) {
+ mLineBackground.inset(-padding, -padding);
+ canvas.drawRect(mLineBackground, bgPaint);
+ }
+ }
+ }
+ );
+ }
+
+ /**
* @param canvas
* @return The range of lines that need to be drawn, possibly empty.
* @hide
@@ -1682,7 +1750,7 @@
}
if (bounds == null) {
- throw new IllegalArgumentException("bounds can't be null.");
+ throw new IllegalArgumentException("bounds can't be null.");
}
final int neededLength = 4 * (end - start);
@@ -1698,6 +1766,34 @@
final int startLine = getLineForOffset(start);
final int endLine = getLineForOffset(end - 1);
+
+ forEachCharacterBounds(start, end, startLine, endLine,
+ (index, lineNum, left, lineTop, right, lineBottom) -> {
+ final int boundsIndex = boundsStart + 4 * (index - start);
+ bounds[boundsIndex] = left;
+ bounds[boundsIndex + 1] = lineTop;
+ bounds[boundsIndex + 2] = right;
+ bounds[boundsIndex + 3] = lineBottom;
+ });
+ }
+
+ /**
+ * Return the characters' bounds in the given range. The coordinates are in local text layout.
+ *
+ * @param start the start index to compute the character bounds, inclusive.
+ * @param end the end index to compute the character bounds, exclusive.
+ * @param startLine index of the line that contains {@code start}
+ * @param endLine index of the line that contains {@code end}
+ * @param listener called for each character with its bounds
+ *
+ */
+ private void forEachCharacterBounds(
+ @IntRange(from = 0) int start,
+ @IntRange(from = 0) int end,
+ @IntRange(from = 0) int startLine,
+ @IntRange(from = 0) int endLine,
+ CharacterBoundsListener listener
+ ) {
float[] horizontalBounds = null;
for (int line = startLine; line <= endLine; ++line) {
final int lineStart = getLineStart(line);
@@ -1722,13 +1818,10 @@
final float left = horizontalBounds[offset * 2] + lineStartPos;
final float right = horizontalBounds[offset * 2 + 1] + lineStartPos;
- final int boundsIndex = boundsStart + 4 * (index - start);
- bounds[boundsIndex] = left;
- bounds[boundsIndex + 1] = lineTop;
- bounds[boundsIndex + 2] = right;
- bounds[boundsIndex + 3] = lineBottom;
+ listener.onCharacterBounds(index, line, left, lineTop, right, lineBottom);
}
}
+ listener.onEnd();
}
/**
@@ -4443,4 +4536,15 @@
public Paint.FontMetrics getMinimumFontMetrics() {
return mMinimumFontMetrics;
}
+
+ /**
+ * Callback for {@link #forEachCharacterBounds(int, int, int, int, CharacterBoundsListener)}
+ */
+ private interface CharacterBoundsListener {
+ void onCharacterBounds(int index, int lineNum, float left, float top, float right,
+ float bottom);
+
+ /** Called after the last character has been sent to {@link #onCharacterBounds}. */
+ default void onEnd() {}
+ }
}
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index b9de93c..7653bdb 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -56,11 +56,18 @@
public static class BytesResult {
public final String value;
public final String units;
+ /**
+ * Content description of the {@link #units}.
+ * See {@link View#setContentDescription(CharSequence)}
+ */
+ public final String unitsContentDescription;
public final long roundedBytes;
- public BytesResult(String value, String units, long roundedBytes) {
+ public BytesResult(String value, String units, String unitsContentDescription,
+ long roundedBytes) {
this.value = value;
this.units = units;
+ this.unitsContentDescription = unitsContentDescription;
this.roundedBytes = roundedBytes;
}
}
@@ -271,20 +278,20 @@
final Locale locale = res.getConfiguration().getLocales().get(0);
final NumberFormat numberFormatter = getNumberFormatter(locale, rounded.fractionDigits);
final String formattedNumber = numberFormatter.format(rounded.value);
- final String units;
+ // Since ICU does not give us access to the pattern, we need to extract the unit string
+ // from ICU, which we do by taking out the formatted number out of the formatted string
+ // and trimming the result of spaces and controls.
+ final String formattedMeasure = formatMeasureShort(
+ locale, numberFormatter, rounded.value, rounded.units);
+ final String numberRemoved = deleteFirstFromString(formattedMeasure, formattedNumber);
+ String units = SPACES_AND_CONTROLS.trim(numberRemoved).toString();
+ String unitsContentDescription = units;
if (rounded.units == MeasureUnit.BYTE) {
// ICU spells out "byte" instead of "B".
units = getByteSuffixOverride(res);
- } else {
- // Since ICU does not give us access to the pattern, we need to extract the unit string
- // from ICU, which we do by taking out the formatted number out of the formatted string
- // and trimming the result of spaces and controls.
- final String formattedMeasure = formatMeasureShort(
- locale, numberFormatter, rounded.value, rounded.units);
- final String numberRemoved = deleteFirstFromString(formattedMeasure, formattedNumber);
- units = SPACES_AND_CONTROLS.trim(numberRemoved).toString();
}
- return new BytesResult(formattedNumber, units, rounded.roundedBytes);
+ return new BytesResult(formattedNumber, units, unitsContentDescription,
+ rounded.roundedBytes);
}
/**
diff --git a/core/java/android/tracing/flags.aconfig b/core/java/android/tracing/flags.aconfig
index c50c384..74428aa 100644
--- a/core/java/android/tracing/flags.aconfig
+++ b/core/java/android/tracing/flags.aconfig
@@ -22,3 +22,11 @@
description: "Migrate IME tracing to Perfetto"
bug: "276433199"
}
+
+flag {
+ name: "perfetto_ime"
+ namespace: "windowing_tools"
+ description: "Migrate IME tracing to Perfetto"
+ is_fixed_read_only: true
+ bug: "276433199"
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 65d9b3a..cb5a885 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -62,7 +62,6 @@
import android.view.InputDevice;
import android.view.IInputFilter;
import android.view.AppTransitionAnimationSpec;
-import android.view.TaskTransitionSpec;
import android.view.WindowContentFrameStats;
import android.view.WindowManager;
import android.view.SurfaceControl;
@@ -962,19 +961,6 @@
void setTaskSnapshotEnabled(boolean enabled);
/**
- * Customized the task transition animation with a task transition spec.
- *
- * @param spec the spec that will be used to customize the task animations
- */
- void setTaskTransitionSpec(in TaskTransitionSpec spec);
-
- /**
- * Clears any task transition spec that has been previously set and
- * reverts to using the default task transition with no spec changes.
- */
- void clearTaskTransitionSpec();
-
- /**
* Registers the frame rate per second count callback for one given task ID.
* Each callback can only register for receiving FPS callback for one task id until unregister
* is called. If there's no task associated with the given task id,
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 3a90841..86264eb 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -35,6 +35,7 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import android.view.WindowRelayoutResult;
import android.window.ClientWindowFrames;
import android.window.InputTransferToken;
import android.window.OnBackInvokedCallbackInfo;
@@ -84,6 +85,16 @@
void remove(IBinder clientToken);
/**
+ * @deprecated
+ */
+ int relayoutLegacy(IWindow window, in WindowManager.LayoutParams attrs,
+ int requestedWidth, int requestedHeight, int viewVisibility,
+ int flags, int seq, int lastSyncSeqId, out ClientWindowFrames outFrames,
+ out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
+ out InsetsState insetsState, out InsetsSourceControl.Array activeControls,
+ out Bundle bundle);
+
+ /**
* Change the parameters of a window. You supply the
* new parameters, it returns the new frame of the window on screen (the
* position should be ignored) and surface of the window. The surface
@@ -98,22 +109,12 @@
* @param flags Request flags: {@link WindowManagerGlobal#RELAYOUT_INSETS_PENDING}.
* @param seq The calling sequence of {@link #relayout} and {@link #relayoutAsync}.
* @param lastSyncSeqId The last SyncSeqId that the client applied.
- * @param outFrames The window frames used by the client side for layout.
- * @param outMergedConfiguration New config container that holds global, override and merged
- * config for window, if it is now becoming visible and the merged
- * config has changed since it was last displayed.
- * @param outSurfaceControl Object in which is placed the new display surface.
- * @param insetsState The current insets state in the system.
- * @param activeControls Objects which allow controlling {@link InsetsSource}s.
- * @param bundle A Bundle to contain the latest SyncSeqId and any extra relayout optional infos.
+ * @param outRelayoutResult Data object contains the info to be returned from server side.
* @return int Result flags, defined in {@link WindowManagerGlobal}.
*/
- int relayout(IWindow window, in WindowManager.LayoutParams attrs,
- int requestedWidth, int requestedHeight, int viewVisibility,
- int flags, int seq, int lastSyncSeqId, out ClientWindowFrames outFrames,
- out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
- out InsetsState insetsState, out InsetsSourceControl.Array activeControls,
- out Bundle bundle);
+ int relayout(IWindow window, in WindowManager.LayoutParams attrs, int requestedWidth,
+ int requestedHeight, int viewVisibility, int flags, int seq, int lastSyncSeqId,
+ out @nullable WindowRelayoutResult outRelayoutResult);
/**
* Similar to {@link #relayout} but this is an oneway method which doesn't return anything.
diff --git a/core/java/android/view/ImeBackAnimationController.java b/core/java/android/view/ImeBackAnimationController.java
index e14ddd6..1afedc1 100644
--- a/core/java/android/view/ImeBackAnimationController.java
+++ b/core/java/android/view/ImeBackAnimationController.java
@@ -63,8 +63,8 @@
private boolean mIsPreCommitAnimationInProgress = false;
private int mStartRootScrollY = 0;
- public ImeBackAnimationController(ViewRootImpl viewRoot) {
- mInsetsController = viewRoot.getInsetsController();
+ public ImeBackAnimationController(ViewRootImpl viewRoot, InsetsController insetsController) {
+ mInsetsController = insetsController;
mViewRoot = viewRoot;
}
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 85c779b..6568912 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -95,7 +95,7 @@
private final Matrix mTmpMatrix = new Matrix();
private final InsetsState mInitialInsetsState;
private final @AnimationType int mAnimationType;
- private final @LayoutInsetsDuringAnimation int mLayoutInsetsDuringAnimation;
+ private @LayoutInsetsDuringAnimation int mLayoutInsetsDuringAnimation;
private final @InsetsType int mTypes;
private @InsetsType int mControllingTypes;
private final InsetsAnimationControlCallbacks mController;
@@ -377,6 +377,12 @@
}
@Override
+ public void updateLayoutInsetsDuringAnimation(
+ @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+ mLayoutInsetsDuringAnimation = layoutInsetsDuringAnimation;
+ }
+
+ @Override
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(IS_CANCELLED, mCancelled);
diff --git a/core/java/android/view/InsetsAnimationControlRunner.java b/core/java/android/view/InsetsAnimationControlRunner.java
index cf40e7e..8cb8b47 100644
--- a/core/java/android/view/InsetsAnimationControlRunner.java
+++ b/core/java/android/view/InsetsAnimationControlRunner.java
@@ -20,6 +20,7 @@
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsController.AnimationType;
+import android.view.InsetsController.LayoutInsetsDuringAnimation;
import android.view.WindowInsets.Type.InsetsType;
import android.view.inputmethod.ImeTracker;
@@ -82,6 +83,14 @@
ImeTracker.Token getStatsToken();
/**
+ * Updates the desired layout insets during the animation.
+ *
+ * @param layoutInsetsDuringAnimation Whether the insets should be shown or hidden
+ */
+ void updateLayoutInsetsDuringAnimation(
+ @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation);
+
+ /**
*
* Export the state of classes that implement this interface into a protocol buffer
* output stream.
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 92e20e0..83ff88b 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -186,4 +186,11 @@
public int getAnimationType() {
return mControl.getAnimationType();
}
+
+ @Override
+ public void updateLayoutInsetsDuringAnimation(
+ @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+ InsetsAnimationThread.getHandler().post(
+ () -> mControl.updateLayoutInsetsDuringAnimation(layoutInsetsDuringAnimation));
+ }
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 6c90011..c545267 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1028,8 +1028,23 @@
reportRequestedVisibleTypes();
}
- void setPredictiveBackImeHideAnimInProgress(boolean isInProgress) {
+ @VisibleForTesting(visibility = PACKAGE)
+ public void setPredictiveBackImeHideAnimInProgress(boolean isInProgress) {
mIsPredictiveBackImeHideAnimInProgress = isInProgress;
+ if (isInProgress) {
+ // The InsetsAnimationControlRunner has layoutInsetsDuringAnimation set to SHOWN during
+ // predictive back. Let's set it to HIDDEN once the predictive back animation enters the
+ // post-commit phase.
+ // That prevents flickers in case the animation is cancelled by an incoming show request
+ // during the hide animation.
+ for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
+ final InsetsAnimationControlRunner runner = mRunningAnimations.get(i).runner;
+ if ((runner.getTypes() & ime()) != 0) {
+ runner.updateLayoutInsetsDuringAnimation(LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
+ break;
+ }
+ }
+ }
}
boolean isPredictiveBackImeHideAnimInProgress() {
@@ -1231,7 +1246,8 @@
false /* fromPredictiveBack */);
}
- void controlWindowInsetsAnimation(@InsetsType int types,
+ @VisibleForTesting(visibility = PACKAGE)
+ public void controlWindowInsetsAnimation(@InsetsType int types,
@Nullable CancellationSignal cancellationSignal,
WindowInsetsAnimationControlListener listener,
boolean fromIme, long durationMs, @Nullable Interpolator interpolator,
@@ -1983,7 +1999,8 @@
}
}
- Host getHost() {
+ @VisibleForTesting(visibility = PACKAGE)
+ public Host getHost() {
return mHost;
}
}
diff --git a/core/java/android/view/InsetsResizeAnimationRunner.java b/core/java/android/view/InsetsResizeAnimationRunner.java
index ebdddd5..6e62221 100644
--- a/core/java/android/view/InsetsResizeAnimationRunner.java
+++ b/core/java/android/view/InsetsResizeAnimationRunner.java
@@ -34,6 +34,7 @@
import android.graphics.Rect;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import android.view.InsetsController.LayoutInsetsDuringAnimation;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.animation.Interpolator;
@@ -242,4 +243,9 @@
@Override
public void onCancelled(WindowInsetsAnimationController controller) {
}
+
+ @Override
+ public void updateLayoutInsetsDuringAnimation(
+ @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+ }
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 56edfe72..e20b15e 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -835,8 +835,8 @@
@Override
public String toString() {
synchronized (mLock) {
- return "Surface(name=" + mName + ")/@0x" +
- Integer.toHexString(System.identityHashCode(this));
+ return "Surface(name=" + mName + " mNativeObject=" + mNativeObject + ")/@0x"
+ + Integer.toHexString(System.identityHashCode(this));
}
}
diff --git a/core/java/android/view/TaskTransitionSpec.aidl b/core/java/android/view/TaskTransitionSpec.aidl
deleted file mode 100644
index 08af15c..0000000
--- a/core/java/android/view/TaskTransitionSpec.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-** Copyright 2021, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-/** @hide */
-parcelable TaskTransitionSpec;
diff --git a/core/java/android/view/TaskTransitionSpec.java b/core/java/android/view/TaskTransitionSpec.java
deleted file mode 100644
index 9a2d3ba..0000000
--- a/core/java/android/view/TaskTransitionSpec.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Holds information about how to execute task transition animations.
- *
- * This class is intended to be used with IWindowManager.setTaskTransitionSpec methods when
- * we want more customization over the way default task transitions are executed.
- *
- * @hide
- */
-public class TaskTransitionSpec implements Parcelable {
- /**
- * The background color to use during task animations (override the default background color)
- */
- public final int backgroundColor;
-
- public TaskTransitionSpec(int backgroundColor) {
- this.backgroundColor = backgroundColor;
- }
-
- public TaskTransitionSpec(Parcel in) {
- this.backgroundColor = in.readInt();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(backgroundColor);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<TaskTransitionSpec>
- CREATOR = new Parcelable.Creator<TaskTransitionSpec>() {
- public TaskTransitionSpec createFromParcel(Parcel in) {
- return new TaskTransitionSpec(in);
- }
-
- public TaskTransitionSpec[] newArray(int size) {
- return new TaskTransitionSpec[size];
- }
- };
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 510a4a3..a844370 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -912,12 +912,6 @@
private static final String AUTOFILL_LOG_TAG = "View.Autofill";
/**
- * The logging tag used by this class when logging verbose and chatty (high volume)
- * autofill-related messages.
- */
- private static final String AUTOFILL_CHATTY_LOG_TAG = "View.Autofill.Chatty";
-
- /**
* The logging tag used by this class when logging content capture-related messages.
*/
private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
@@ -2430,12 +2424,6 @@
public static final int FRAME_RATE_CATEGORY_REASON_VELOCITY = 0x0600_0000;
/**
- * This indicates that the frame rate category was chosen because it is idle.
- * @hide
- */
- public static final int FRAME_RATE_CATEGORY_REASON_IDLE = 0x0700_0000;
-
- /**
* This indicates that the frame rate category was chosen because it is currently boosting.
* @hide
*/
@@ -4745,6 +4733,11 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mLeft;
/**
+ * The mLeft from the previous frame. Used for detecting movement for purposes of variable
+ * refresh rate.
+ */
+ private int mLastFrameLeft;
+ /**
* The distance in pixels from the left edge of this view's parent
* to the right edge of this view.
* {@hide}
@@ -4761,6 +4754,11 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mTop;
/**
+ * The mTop from the previous frame. Used for detecting movement for purposes of variable
+ * refresh rate.
+ */
+ private int mLastFrameTop;
+ /**
* The distance in pixels from the top edge of this view's parent
* to the bottom edge of this view.
* {@hide}
@@ -8704,8 +8702,8 @@
@CallSuper
protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
@Nullable Rect previouslyFocusedRect) {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, "onFocusChanged() entered. gainFocus: "
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "onFocusChanged() entered. gainFocus: "
+ gainFocus);
}
if (gainFocus) {
@@ -8773,8 +8771,8 @@
if (canNotifyAutofillEnterExitEvent()) {
AutofillManager afm = getAutofillManager();
if (afm != null) {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, this + " afm is not null");
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, this + " afm is not null");
}
if (enter) {
// We have not been laid out yet, hence cannot evaluate
@@ -8787,8 +8785,8 @@
// animation beginning. On the time, the view is not visible
// to the user. And then as the animation progresses, the view
// becomes visible to the user.
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG,
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG,
"notifyEnterOrExitForAutoFillIfNeeded:"
+ " isLaidOut(): " + isLaidOut()
+ " isVisibleToUser(): " + isVisibleToUser()
@@ -11020,28 +11018,28 @@
}
private boolean isAutofillable() {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, "isAutofillable() entered.");
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "isAutofillable() entered.");
}
if (getAutofillType() == AUTOFILL_TYPE_NONE) {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
}
return false;
}
final AutofillManager afm = getAutofillManager();
if (afm == null) {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, "AutofillManager is null");
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "AutofillManager is null");
}
return false;
}
// Check whether view is not part of an activity. If it's not, return false.
if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
}
return false;
}
@@ -11052,9 +11050,8 @@
if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
|| (!isImportantForAutofill()
&& afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG,
- "isImportantForAutofill(): " + isImportantForAutofill()
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill()
+ "afm.isAutofillable(): " + afm.isAutofillable(this));
}
return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
@@ -11062,8 +11059,8 @@
// If the previous condition is not met, fall back to the previous way to trigger fill
// request based on autofill importance instead.
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
}
return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
}
@@ -11079,8 +11076,8 @@
/** @hide */
public boolean canNotifyAutofillEnterExitEvent() {
- if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_CHATTY_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
+ if (DBG) {
+ Log.d(VIEW_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
+ " isAutofillable(): " + isAutofillable()
+ " isAttachedToWindow(): " + isAttachedToWindow());
}
@@ -17156,10 +17153,12 @@
/**
* Handle a key event before it is processed by any input method
- * associated with the view hierarchy. This can be used to intercept
+ * associated with the view hierarchy. This can be used to intercept
* key events in special situations before the IME consumes them; a
* typical example would be handling the BACK key to update the application's
- * UI instead of allowing the IME to see it and close itself.
+ * UI instead of allowing the IME to see it and close itself. Due to a bug,
+ * this function is not called for BACK key events on Android T and U, when
+ * the IME is shown.
*
* @param keyCode The value in event.getKeyCode().
* @param event Description of the key event.
@@ -19535,7 +19534,6 @@
*/
public final void setTop(int top) {
if (top != mTop) {
- mPrivateFlags4 |= PFLAG4_HAS_MOVED;
final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
if (mAttachInfo != null) {
@@ -20427,7 +20425,6 @@
*/
public void offsetTopAndBottom(int offset) {
if (offset != 0) {
- mPrivateFlags4 |= PFLAG4_HAS_MOVED;
final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
if (isHardwareAccelerated()) {
@@ -20479,7 +20476,6 @@
*/
public void offsetLeftAndRight(int offset) {
if (offset != 0) {
- mPrivateFlags4 |= PFLAG4_HAS_MOVED;
final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
if (isHardwareAccelerated()) {
@@ -25523,7 +25519,6 @@
}
if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
- mPrivateFlags4 |= PFLAG4_HAS_MOVED;
changed = true;
// Remember our drawn bit
@@ -33976,28 +33971,32 @@
// The most common case is when nothing is set, so this special case is called
// often.
if (mAttachInfo.mViewVelocityApi
- && (mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
- PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)
+ && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
+ PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
+ || mLastFrameTop != mTop)
&& viewRootImpl.shouldCheckFrameRate(false)
&& parent instanceof View
&& ((View) parent).mFrameContentVelocity <= 0) {
viewRootImpl.votePreferredFrameRate(MAX_FRAME_RATE, FRAME_RATE_COMPATIBILITY_GTE);
}
- if (!willNotDraw() && viewRootImpl.shouldCheckFrameRateCategory()) {
+ if (viewRootImpl.shouldCheckFrameRateCategory()) {
int frameRateCategory = calculateFrameRateCategory();
int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
mLastFrameRateCategory = frameRateCategory;
}
+ mLastFrameLeft = mLeft;
+ mLastFrameTop = mTop;
return;
}
if (viewRootImpl.shouldCheckFrameRate(frameRate > 0f)) {
float velocityFrameRate = 0f;
if (mAttachInfo.mViewVelocityApi) {
if (velocity < 0f
- && (mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
- PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)
+ && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
+ PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
+ || mLastFrameTop != mTop)
&& mParent instanceof View
&& ((View) mParent).mFrameContentVelocity <= 0
) {
@@ -34022,7 +34021,7 @@
}
}
- if (!willNotDraw() && viewRootImpl.shouldCheckFrameRateCategory()) {
+ if (viewRootImpl.shouldCheckFrameRateCategory()) {
if (sToolkitMetricsForFrameRateDecisionFlagValue) {
int width = mRight - mLeft;
int height = mBottom - mTop;
@@ -34030,7 +34029,7 @@
viewRootImpl.recordViewPercentage(sizePercentage);
}
- int frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
+ int frameRateCategory;
if (Float.isNaN(frameRate)) {
frameRateCategory = calculateFrameRateCategory();
} else if (frameRate < 0) {
@@ -34055,6 +34054,10 @@
| FRAME_RATE_CATEGORY_REASON_INVALID;
}
}
+ } else {
+ // Category doesn't control it. It is directly controlled by frame rate
+ frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
+ | FRAME_RATE_CATEGORY_REASON_REQUESTED;
}
int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
@@ -34062,6 +34065,8 @@
viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
mLastFrameRateCategory = frameRateCategory;
}
+ mLastFrameLeft = mLeft;
+ mLastFrameTop = mTop;
}
private float convertVelocityToFrameRate(float velocityPps) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 701b2d3..f51d909 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -37,7 +37,6 @@
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
import static android.view.View.FRAME_RATE_CATEGORY_REASON_BOOST;
import static android.view.View.FRAME_RATE_CATEGORY_REASON_CONFLICTED;
-import static android.view.View.FRAME_RATE_CATEGORY_REASON_IDLE;
import static android.view.View.FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
import static android.view.View.FRAME_RATE_CATEGORY_REASON_INVALID;
import static android.view.View.FRAME_RATE_CATEGORY_REASON_LARGE;
@@ -111,6 +110,7 @@
import static android.view.accessibility.Flags.fixMergedContentChangeEventV2;
import static android.view.accessibility.Flags.forceInvertColor;
import static android.view.accessibility.Flags.reduceWindowContentChangedEventThrottle;
+import static android.view.flags.Flags.addSchandleToVriSurface;
import static android.view.flags.Flags.sensitiveContentAppProtection;
import static android.view.flags.Flags.toolkitFrameRateFunctionEnablingReadOnly;
import static android.view.flags.Flags.toolkitFrameRateTypingReadOnly;
@@ -126,6 +126,7 @@
import static com.android.window.flags.Flags.activityWindowInfoFlag;
import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay;
import static com.android.window.flags.Flags.setScPropertiesInClient;
+import static com.android.window.flags.Flags.windowSessionRelayoutInfo;
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
@@ -1088,16 +1089,10 @@
// The last preferred frame rate of the view that is mainly used to
// track the difference between the current preferred frame rate and the previous value.
private float mLastPreferredFrameRate = 0;
- // Used to check if there were any view invalidations in
- // the previous time frame (FRAME_RATE_IDLENESS_REEVALUATE_TIME).
- private boolean mHasInvalidation = false;
// Used to check if it is in the frame rate boosting period.
private boolean mIsFrameRateBoosting = false;
// Used to check if it is in touch boosting period.
private boolean mIsTouchBoosting = false;
- // Used to check if there is a message in the message queue
- // for idleness handling.
- private boolean mHasIdledMessage = false;
private boolean mDrawnThisFrame = false;
// Used to check if there is a conflict between different frame rate voting.
// Take 24 and 30 as an example, 24 is not a divisor of 30.
@@ -1108,10 +1103,6 @@
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
// time for touch boost period.
private static final int FRAME_RATE_TOUCH_BOOST_TIME = 3000;
- // time for checking idle status periodically.
- private static final int FRAME_RATE_IDLENESS_CHECK_TIME_MILLIS = 500;
- // time for revaluating the idle status before lowering the frame rate.
- private static final int FRAME_RATE_IDLENESS_REEVALUATE_TIME = 1000;
// time for evaluating the interval between current time and
// the time when frame rate was set previously.
private static final int FRAME_RATE_SETTING_REEVALUATE_TIME = 100;
@@ -1144,7 +1135,14 @@
* we get rid of synchronous relayout, until then, we use this bundle to channel the
* integer back over relayout.
*/
- private Bundle mRelayoutBundle = new Bundle();
+ private final Bundle mRelayoutBundle = windowSessionRelayoutInfo()
+ ? null
+ : new Bundle();
+
+ private final WindowRelayoutResult mRelayoutResult = windowSessionRelayoutInfo()
+ ? new WindowRelayoutResult(mTmpFrames, mPendingMergedConfiguration, mSurfaceControl,
+ mTempInsets, mTempControls)
+ : null;
private static volatile boolean sAnrReported = false;
static BLASTBufferQueue.TransactionHangCallback sTransactionHangCallback =
@@ -1245,7 +1243,7 @@
// TODO(b/222696368): remove getSfInstance usage and use vsyncId for transactions
mChoreographer = Choreographer.getInstance();
mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this));
- mImeBackAnimationController = new ImeBackAnimationController(this);
+ mImeBackAnimationController = new ImeBackAnimationController(this, mInsetsController);
mHandwritingInitiator = new HandwritingInitiator(
mViewConfiguration,
mContext.getSystemService(InputMethodManager.class));
@@ -2635,7 +2633,12 @@
mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl,
mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format);
mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback);
- Surface blastSurface = mBlastBufferQueue.createSurface();
+ Surface blastSurface;
+ if (addSchandleToVriSurface()) {
+ blastSurface = mBlastBufferQueue.createSurfaceWithHandle();
+ } else {
+ blastSurface = mBlastBufferQueue.createSurface();
+ }
// Only call transferFrom if the surface has changed to prevent inc the generation ID and
// causing EGL resources to be recreated.
mSurface.transferFrom(blastSurface);
@@ -4254,8 +4257,8 @@
// when the values are applicable.
if (mDrawnThisFrame) {
mDrawnThisFrame = false;
- updateInfrequentCount();
setCategoryFromCategoryCounts();
+ updateInfrequentCount();
setPreferredFrameRate(mPreferredFrameRate);
setPreferredFrameRateCategory(mPreferredFrameRateCategory);
if (!mIsFrameRateConflicted) {
@@ -4263,7 +4266,6 @@
mHandler.sendEmptyMessageDelayed(MSG_FRAME_RATE_SETTING,
FRAME_RATE_SETTING_REEVALUATE_TIME);
}
- checkIdleness();
mFrameRateCategoryHighCount = mFrameRateCategoryHighCount > 0
? mFrameRateCategoryHighCount - 1 : mFrameRateCategoryHighCount;
mFrameRateCategoryNormalCount = mFrameRateCategoryNormalCount > 0
@@ -4274,6 +4276,10 @@
mPreferredFrameRate = -1;
mIsFrameRateConflicted = false;
mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_UNKNOWN;
+ } else if (mPreferredFrameRate == 0) {
+ // From MSG_FRAME_RATE_SETTING, where mPreferredFrameRate is set to 0
+ setPreferredFrameRate(0);
+ mPreferredFrameRate = -1;
}
}
@@ -5954,13 +5960,19 @@
return handled;
}
- void setScrollY(int scrollY) {
+ @VisibleForTesting(visibility = PACKAGE)
+ public void setScrollY(int scrollY) {
if (mScroller != null) {
mScroller.abortAnimation();
}
mScrollY = scrollY;
}
+ @VisibleForTesting
+ public int getScrollY() {
+ return mScrollY;
+ }
+
/**
* @hide
*/
@@ -6445,8 +6457,6 @@
return "MSG_REFRESH_POINTER_ICON";
case MSG_TOUCH_BOOST_TIMEOUT:
return "MSG_TOUCH_BOOST_TIMEOUT";
- case MSG_CHECK_INVALIDATION_IDLE:
- return "MSG_CHECK_INVALIDATION_IDLE";
case MSG_FRAME_RATE_SETTING:
return "MSG_FRAME_RATE_SETTING";
}
@@ -6714,27 +6724,6 @@
mIsFrameRateBoosting = false;
mIsTouchBoosting = false;
break;
- case MSG_CHECK_INVALIDATION_IDLE:
- if (!mHasInvalidation && !mIsFrameRateBoosting && !mIsTouchBoosting) {
- mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
- mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_IDLE;
- mFrameRateCategoryView = null;
- setPreferredFrameRateCategory(mPreferredFrameRateCategory);
- mHasIdledMessage = false;
- } else {
- /**
- * If there is no invalidation within a certain period,
- * we consider the display is idled.
- * We then set the frame rate catetogry to NO_PREFERENCE.
- * Note that SurfaceFlinger also has a mechanism to lower the refresh rate
- * if there is no updates of the buffer.
- */
- mHasInvalidation = false;
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_INVALIDATION_IDLE,
- FRAME_RATE_IDLENESS_REEVALUATE_TIME);
- mHasIdledMessage = true;
- }
- break;
case MSG_REFRESH_POINTER_ICON:
if (mPointerIconEvent == null) {
break;
@@ -6744,7 +6733,6 @@
case MSG_FRAME_RATE_SETTING:
mPreferredFrameRate = 0;
mFrameRateCompatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
- setPreferredFrameRate(mPreferredFrameRate);
break;
}
}
@@ -9080,29 +9068,42 @@
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,
mLastSyncSeqId);
} else {
- relayoutResult = mWindowSession.relayout(mWindow, params,
- requestedWidth, requestedHeight, viewVisibility,
- insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,
- mLastSyncSeqId, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl,
- mTempInsets, mTempControls, mRelayoutBundle);
+ if (windowSessionRelayoutInfo()) {
+ relayoutResult = mWindowSession.relayout(mWindow, params,
+ requestedWidth, requestedHeight, viewVisibility,
+ insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
+ mRelayoutSeq, mLastSyncSeqId, mRelayoutResult);
+ } else {
+ relayoutResult = mWindowSession.relayoutLegacy(mWindow, params,
+ requestedWidth, requestedHeight, viewVisibility,
+ insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
+ mRelayoutSeq, mLastSyncSeqId, mTmpFrames, mPendingMergedConfiguration,
+ mSurfaceControl, mTempInsets, mTempControls, mRelayoutBundle);
+ }
mRelayoutRequested = true;
if (activityWindowInfoFlag() && mPendingActivityWindowInfo != null) {
ActivityWindowInfo outInfo = null;
- try {
- outInfo = mRelayoutBundle.getParcelable(
- IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO,
- ActivityWindowInfo.class);
- mRelayoutBundle.remove(IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO);
- } catch (IllegalStateException e) {
- Log.e(TAG, "Failed to get ActivityWindowInfo from relayout Bundle", e);
+ if (windowSessionRelayoutInfo()) {
+ outInfo = mRelayoutResult != null ? mRelayoutResult.activityWindowInfo : null;
+ } else {
+ try {
+ outInfo = mRelayoutBundle.getParcelable(
+ IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO,
+ ActivityWindowInfo.class);
+ mRelayoutBundle.remove(
+ IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Failed to get ActivityWindowInfo from relayout Bundle", e);
+ }
}
if (outInfo != null) {
mPendingActivityWindowInfo.set(outInfo);
}
}
- final int maybeSyncSeqId = mRelayoutBundle.getInt(
- IWindowSession.KEY_RELAYOUT_BUNDLE_SEQID);
+ final int maybeSyncSeqId = windowSessionRelayoutInfo()
+ ? mRelayoutResult.syncSeqId
+ : mRelayoutBundle.getInt(IWindowSession.KEY_RELAYOUT_BUNDLE_SEQID);
if (maybeSyncSeqId > 0) {
mSyncSeqId = maybeSyncSeqId;
}
@@ -12568,6 +12569,13 @@
case FRAME_RATE_CATEGORY_HIGH ->
mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
}
+
+ // If it's currently an intermittent update,
+ // we should keep mPreferredFrameRateCategory as NORMAL
+ if (intermittentUpdateState() == INTERMITTENT_STATE_INTERMITTENT) {
+ return;
+ }
+
if (mFrameRateCategoryHighCount > 0) {
mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
} else if (mFrameRateCategoryHighHintCount > 0) {
@@ -12649,7 +12657,6 @@
case FRAME_RATE_CATEGORY_REASON_REQUESTED -> str = "requested";
case FRAME_RATE_CATEGORY_REASON_INVALID -> str = "invalid frame rate";
case FRAME_RATE_CATEGORY_REASON_VELOCITY -> str = "velocity";
- case FRAME_RATE_CATEGORY_REASON_IDLE -> str = "idle";
case FRAME_RATE_CATEGORY_REASON_UNKNOWN -> str = "unknown";
case FRAME_RATE_CATEGORY_REASON_BOOST -> str = "boost";
case FRAME_RATE_CATEGORY_REASON_TOUCH -> str = "touch";
@@ -12718,7 +12725,6 @@
mFrameRateCategoryChangeReason = reason;
// mFrameRateCategoryView = view == null ? "-" : view.getClass().getSimpleName();
}
- mHasInvalidation = true;
mDrawnThisFrame = true;
}
@@ -12792,7 +12798,6 @@
mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_VELOCITY;
mFrameRateCategoryView = null;
- mHasInvalidation = true;
mDrawnThisFrame = true;
return;
}
@@ -12824,7 +12829,6 @@
mPreferredFrameRate = nextFrameRate;
mFrameRateCompatibility = nextFrameRateCompatibility;
- mHasInvalidation = true;
mDrawnThisFrame = true;
}
@@ -12944,19 +12948,8 @@
return false;
}
- private void checkIdleness() {
- if (!mHasIdledMessage) {
- // Check where the display is idled periodically.
- // If so, set the frame rate category to NO_PREFERENCE
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_INVALIDATION_IDLE,
- FRAME_RATE_IDLENESS_CHECK_TIME_MILLIS);
- mHasIdledMessage = true;
- }
- }
-
private void removeVrrMessages() {
mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
- mHandler.removeMessages(MSG_CHECK_INVALIDATION_IDLE);
mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
}
@@ -12976,7 +12969,8 @@
mMinusOneFrameIntervalMillis = timeIntervalMillis;
mLastUpdateTimeMillis = currentTimeMillis;
- if (timeIntervalMillis >= INFREQUENT_UPDATE_INTERVAL_MILLIS) {
+ if (timeIntervalMillis + mMinusTwoFrameIntervalMillis
+ >= INFREQUENT_UPDATE_INTERVAL_MILLIS) {
int infrequentUpdateCount = mInfrequentUpdateCount;
mInfrequentUpdateCount = infrequentUpdateCount == INFREQUENT_UPDATE_COUNTS
? infrequentUpdateCount : infrequentUpdateCount + 1;
diff --git a/core/java/android/view/WindowRelayoutResult.aidl b/core/java/android/view/WindowRelayoutResult.aidl
new file mode 100644
index 0000000..3b4e340
--- /dev/null
+++ b/core/java/android/view/WindowRelayoutResult.aidl
@@ -0,0 +1,23 @@
+/**
+ * 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;
+
+/**
+ * Stores information to pass to {@link IWindowSession#relayout} as AIDL out type.
+ * @hide
+ */
+parcelable WindowRelayoutResult;
diff --git a/core/java/android/view/WindowRelayoutResult.java b/core/java/android/view/WindowRelayoutResult.java
new file mode 100644
index 0000000..882d3a7
--- /dev/null
+++ b/core/java/android/view/WindowRelayoutResult.java
@@ -0,0 +1,140 @@
+/*
+ * 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;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.MergedConfiguration;
+import android.window.ActivityWindowInfo;
+import android.window.ClientWindowFrames;
+
+/**
+ * Stores information to pass to {@link IWindowSession#relayout} as AIDL out type.
+ * @hide
+ */
+public final class WindowRelayoutResult implements Parcelable {
+
+ /** The window frames used by the client side for layout. */
+ @NonNull
+ public final ClientWindowFrames frames;
+
+ /**
+ * New config container that holds global, override and merged config for window, if it is now
+ * becoming visible and the merged config has changed since it was last displayed.
+ */
+ @NonNull
+ public final MergedConfiguration mergedConfiguration;
+
+ /** Object in which is placed the new display surface. */
+ @NonNull
+ public final SurfaceControl surfaceControl;
+
+ /** The current insets state in the system. */
+ @NonNull
+ public final InsetsState insetsState;
+
+ /** Objects which allow controlling {@link InsetsSource}s. */
+ @NonNull
+ public final InsetsSourceControl.Array activeControls;
+
+ /** The latest sync seq id for the relayout configuration. */
+ public int syncSeqId;
+
+ /**
+ * The latest {@link ActivityWindowInfo} if this relayout window is an Activity window.
+ * {@code null} if this is not an Activity window.
+ */
+ @Nullable
+ public ActivityWindowInfo activityWindowInfo;
+
+ public WindowRelayoutResult() {
+ this(new ClientWindowFrames(), new MergedConfiguration(), new SurfaceControl(),
+ new InsetsState(), new InsetsSourceControl.Array());
+ }
+
+ /**
+ * Stores information to pass for {@link IWindowSession#relayout}.
+ *
+ * @param frames The window frames used by the client side for layout.
+ * @param mergedConfiguration New config container that holds global, override and merged
+ * config for window, if it is now becoming visible and the merged
+ * config has changed since it was last displayed.
+ * @param surfaceControl Object in which is placed the new display surface.
+ * @param insetsState The current insets state in the system.
+ * @param activeControls Objects which allow controlling {@link InsetsSource}s.
+ */
+ public WindowRelayoutResult(@NonNull ClientWindowFrames frames,
+ @NonNull MergedConfiguration mergedConfiguration,
+ @NonNull SurfaceControl surfaceControl, @NonNull InsetsState insetsState,
+ @NonNull InsetsSourceControl.Array activeControls) {
+ this.frames = requireNonNull(frames);
+ this.mergedConfiguration = requireNonNull(mergedConfiguration);
+ this.surfaceControl = requireNonNull(surfaceControl);
+ this.insetsState = requireNonNull(insetsState);
+ this.activeControls = requireNonNull(activeControls);
+ }
+
+ private WindowRelayoutResult(@NonNull Parcel in) {
+ this();
+ readFromParcel(in);
+ }
+
+ /** Needed for IBinder out parameter. */
+ public void readFromParcel(@NonNull Parcel in) {
+ frames.readFromParcel(in);
+ mergedConfiguration.readFromParcel(in);
+ surfaceControl.readFromParcel(in);
+ insetsState.readFromParcel(in);
+ activeControls.readFromParcel(in);
+ syncSeqId = in.readInt();
+ activityWindowInfo = in.readTypedObject(ActivityWindowInfo.CREATOR);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ frames.writeToParcel(dest, flags);
+ mergedConfiguration.writeToParcel(dest, flags);
+ surfaceControl.writeToParcel(dest, flags);
+ insetsState.writeToParcel(dest, flags);
+ activeControls.writeToParcel(dest, flags);
+ dest.writeInt(syncSeqId);
+ dest.writeTypedObject(activityWindowInfo, flags);
+ }
+
+ @NonNull
+ public static final Creator<WindowRelayoutResult> CREATOR =
+ new Creator<>() {
+ @Override
+ public WindowRelayoutResult createFromParcel(@NonNull Parcel in) {
+ return new WindowRelayoutResult(in);
+ }
+
+ @Override
+ public WindowRelayoutResult[] newArray(int size) {
+ return new WindowRelayoutResult[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 7309080..e6367ff 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -349,12 +349,49 @@
}
@Override
- public int relayout(IWindow window, WindowManager.LayoutParams inAttrs,
+ public int relayoutLegacy(IWindow window, WindowManager.LayoutParams inAttrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
int lastSyncSeqId, ClientWindowFrames outFrames,
MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl,
InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,
Bundle outSyncSeqIdBundle) {
+ return relayoutInner(window, inAttrs, requestedWidth, requestedHeight, viewFlags, flags,
+ seq, lastSyncSeqId, outFrames, outMergedConfiguration, outSurfaceControl,
+ outInsetsState, outActiveControls);
+ }
+
+ @Override
+ public int relayout(IWindow window, WindowManager.LayoutParams inAttrs,
+ int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
+ int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
+ final ClientWindowFrames outFrames;
+ final MergedConfiguration outMergedConfiguration;
+ final SurfaceControl outSurfaceControl;
+ final InsetsState outInsetsState;
+ final InsetsSourceControl.Array outActiveControls;
+ if (outRelayoutResult != null) {
+ outFrames = outRelayoutResult.frames;
+ outMergedConfiguration = outRelayoutResult.mergedConfiguration;
+ outSurfaceControl = outRelayoutResult.surfaceControl;
+ outInsetsState = outRelayoutResult.insetsState;
+ outActiveControls = outRelayoutResult.activeControls;
+ } else {
+ outFrames = null;
+ outMergedConfiguration = null;
+ outSurfaceControl = null;
+ outInsetsState = null;
+ outActiveControls = null;
+ }
+ return relayoutInner(window, inAttrs, requestedWidth, requestedHeight, viewFlags, flags,
+ seq, lastSyncSeqId, outFrames, outMergedConfiguration, outSurfaceControl,
+ outInsetsState, outActiveControls);
+ }
+
+ private int relayoutInner(IWindow window, WindowManager.LayoutParams inAttrs,
+ int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
+ int lastSyncSeqId, ClientWindowFrames outFrames,
+ MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl,
+ InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls) {
final State state;
synchronized (this) {
state = mStateForWindow.get(window.asBinder());
@@ -439,10 +476,10 @@
public void relayoutAsync(IWindow window, WindowManager.LayoutParams inAttrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
int lastSyncSeqId) {
- relayout(window, inAttrs, requestedWidth, requestedHeight, viewFlags, flags, seq,
+ relayoutInner(window, inAttrs, requestedWidth, requestedHeight, viewFlags, flags, seq,
lastSyncSeqId, null /* outFrames */, null /* outMergedConfiguration */,
null /* outSurfaceControl */, null /* outInsetsState */,
- null /* outActiveControls */, null /* outSyncSeqIdBundle */);
+ null /* outActiveControls */);
}
@Override
diff --git a/core/java/android/view/flags/view_flags.aconfig b/core/java/android/view/flags/view_flags.aconfig
index 33b29c7..16e1415 100644
--- a/core/java/android/view/flags/view_flags.aconfig
+++ b/core/java/android/view/flags/view_flags.aconfig
@@ -59,3 +59,14 @@
bug: "333752000"
is_fixed_read_only: true
}
+
+flag {
+ name: "add_schandle_to_vri_surface"
+ namespace: "window_surfaces"
+ description: "Add surface control handle to VRI Surface"
+ bug: "320706287"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index ee6ba24..3b9b162 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -16,6 +16,8 @@
package android.window;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
@@ -27,6 +29,8 @@
import android.util.Log;
import android.view.ViewRootImpl;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
/**
@@ -280,7 +284,8 @@
sendStopDispatching();
}
- static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
+ @VisibleForTesting(visibility = PACKAGE)
+ public static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
@NonNull
private final IOnBackInvokedCallback mIOnBackInvokedCallback;
/**
@@ -327,7 +332,8 @@
* Subclass of ImeOnBackInvokedCallback indicating that a predictive IME back animation may be
* played instead of invoking the callback.
*/
- static class DefaultImeOnBackAnimationCallback extends ImeOnBackInvokedCallback {
+ @VisibleForTesting(visibility = PACKAGE)
+ public static class DefaultImeOnBackAnimationCallback extends ImeOnBackInvokedCallback {
DefaultImeOnBackAnimationCallback(@NonNull IOnBackInvokedCallback iCallback, int id,
int priority) {
super(iCallback, id, priority);
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index e5658e6..29bb32e 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -52,11 +52,9 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.GraphicBuffer;
-import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.hardware.HardwareBuffer;
import android.os.IBinder;
import android.util.Log;
@@ -98,11 +96,6 @@
| FLAG_SECURE
| FLAG_DIM_BEHIND;
- private static final RectF sTmpSnapshotSize = new RectF();
- private static final RectF sTmpDstFrame = new RectF();
-
- private static final Matrix sSnapshotMatrix = new Matrix();
- private static final float[] sTmpFloat9 = new float[9];
private static final Paint sBackgroundPaint = new Paint();
/**
@@ -116,24 +109,27 @@
private final CharSequence mTitle;
private SystemBarBackgroundPainter mSystemBarBackgroundPainter;
- private final Rect mTaskBounds;
private final Rect mFrame = new Rect();
private final Rect mSystemBarInsets = new Rect();
+ private final int mSnapshotW;
+ private final int mSnapshotH;
private boolean mSizeMismatch;
public SnapshotSurface(SurfaceControl rootSurface, TaskSnapshot snapshot,
- CharSequence title,
- Rect taskBounds) {
+ CharSequence title) {
mRootSurface = rootSurface;
mSnapshot = snapshot;
mTitle = title;
- mTaskBounds = taskBounds;
+ final HardwareBuffer hwBuffer = snapshot.getHardwareBuffer();
+ mSnapshotW = hwBuffer.getWidth();
+ mSnapshotH = hwBuffer.getHeight();
}
/**
* Initiate system bar painter to draw the system bar background.
*/
- void initiateSystemBarPainter(int windowFlags, int windowPrivateFlags,
+ @VisibleForTesting
+ public void initiateSystemBarPainter(int windowFlags, int windowPrivateFlags,
int appearance, ActivityManager.TaskDescription taskDescription,
@WindowInsets.Type.InsetsType int requestedVisibleTypes) {
mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
@@ -143,14 +139,13 @@
}
/**
- * Set frame size.
+ * Set frame size that the snapshot should fill. It is the bounds of a task or activity.
*/
- void setFrames(Rect frame, Rect systemBarInsets) {
+ @VisibleForTesting
+ public void setFrames(Rect frame, Rect systemBarInsets) {
mFrame.set(frame);
mSystemBarInsets.set(systemBarInsets);
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- mSizeMismatch = (mFrame.width() != snapshot.getWidth()
- || mFrame.height() != snapshot.getHeight());
+ mSizeMismatch = (mFrame.width() != mSnapshotW || mFrame.height() != mSnapshotH);
mSystemBarBackgroundPainter.setInsets(systemBarInsets);
}
@@ -186,7 +181,7 @@
// We consider nearly matched dimensions as there can be rounding errors and the user
// won't notice very minute differences from scaling one dimension more than the other
- boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshot);
+ boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshotW, mSnapshotH);
// Keep a reference to it such that it doesn't get destroyed when finalized.
SurfaceControl childSurfaceControl = new SurfaceControl.Builder(session)
@@ -198,12 +193,14 @@
.build();
final Rect frame;
+ final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
+ float offsetX = letterboxInsets.left;
+ float offsetY = letterboxInsets.top;
// We can just show the surface here as it will still be hidden as the parent is
// still hidden.
mTransaction.show(childSurfaceControl);
if (aspectRatioMismatch) {
Rect crop = null;
- final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
if (letterboxInsets.left != 0 || letterboxInsets.top != 0
|| letterboxInsets.right != 0 || letterboxInsets.bottom != 0) {
// Clip off letterbox.
@@ -214,23 +211,27 @@
// if letterbox doesn't match window frame, try crop by content insets
if (aspectRatioMismatch) {
// Clip off ugly navigation bar.
- crop = calculateSnapshotCrop(mSnapshot.getContentInsets());
+ final Rect contentInsets = mSnapshot.getContentInsets();
+ crop = calculateSnapshotCrop(contentInsets);
+ offsetX = contentInsets.left;
+ offsetY = contentInsets.top;
}
frame = calculateSnapshotFrame(crop);
- mTransaction.setWindowCrop(childSurfaceControl, crop);
- mTransaction.setPosition(childSurfaceControl, frame.left, frame.top);
- sTmpSnapshotSize.set(crop);
- sTmpDstFrame.set(frame);
+ mTransaction.setCrop(childSurfaceControl, crop);
} else {
frame = null;
- sTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
- sTmpDstFrame.set(mFrame);
- sTmpDstFrame.offsetTo(0, 0);
}
- // Scale the mismatch dimensions to fill the task bounds
- sSnapshotMatrix.setRectToRect(sTmpSnapshotSize, sTmpDstFrame, Matrix.ScaleToFit.FILL);
- mTransaction.setMatrix(childSurfaceControl, sSnapshotMatrix, sTmpFloat9);
+ // Align the snapshot with content area.
+ if (offsetX != 0f || offsetY != 0f) {
+ mTransaction.setPosition(childSurfaceControl,
+ -offsetX * mFrame.width() / mSnapshot.getTaskSize().x,
+ -offsetY * mFrame.height() / mSnapshot.getTaskSize().y);
+ }
+ // Scale the mismatch dimensions to fill the target frame.
+ final float scaleX = (float) mFrame.width() / mSnapshotW;
+ final float scaleY = (float) mFrame.height() / mSnapshotH;
+ mTransaction.setScale(childSurfaceControl, scaleX, scaleY);
mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
mTransaction.setBuffer(childSurfaceControl, mSnapshot.getHardwareBuffer());
@@ -261,17 +262,17 @@
* @param insets Content insets or Letterbox insets
* @return crop rect in snapshot coordinate space.
*/
- Rect calculateSnapshotCrop(@NonNull Rect insets) {
+ @VisibleForTesting
+ public Rect calculateSnapshotCrop(@NonNull Rect insets) {
final Rect rect = new Rect();
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
+ rect.set(0, 0, mSnapshotW, mSnapshotH);
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+ final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
// Let's remove all system decorations except the status bar, but only if the task is at
// the very top of the screen.
- final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
+ final boolean isTop = mFrame.top == 0;
rect.inset((int) (insets.left * scaleX),
isTop ? 0 : (int) (insets.top * scaleY),
(int) (insets.right * scaleX),
@@ -284,10 +285,10 @@
*
* @param crop rect that is in snapshot coordinate space.
*/
- Rect calculateSnapshotFrame(Rect crop) {
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+ @VisibleForTesting
+ public Rect calculateSnapshotFrame(Rect crop) {
+ final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
// Rescale the frame from snapshot to window coordinate space
final Rect frame = new Rect(0, 0,
@@ -303,7 +304,8 @@
/**
* Draw status bar and navigation bar background.
*/
- void drawBackgroundAndBars(Canvas c, Rect frame) {
+ @VisibleForTesting
+ public void drawBackgroundAndBars(Canvas c, Rect frame) {
final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
final boolean fillHorizontally = c.getWidth() > frame.right;
final boolean fillVertically = c.getHeight() > frame.bottom;
@@ -320,33 +322,27 @@
/**
* Ask system bar background painter to draw status bar background.
- *
*/
- void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+ @VisibleForTesting
+ public void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
mSystemBarBackgroundPainter.drawStatusBarBackground(c, alreadyDrawnFrame,
mSystemBarBackgroundPainter.getStatusBarColorViewHeight());
}
/**
* Ask system bar background painter to draw navigation bar background.
- *
*/
- void drawNavigationBarBackground(Canvas c) {
+ @VisibleForTesting
+ public void drawNavigationBarBackground(Canvas c) {
mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
}
}
- /**
- * @return true if the aspect ratio match between a frame and a snapshot buffer.
- */
- public static boolean isAspectRatioMatch(Rect frame, TaskSnapshot snapshot) {
+ private static boolean isAspectRatioMatch(Rect frame, int w, int h) {
if (frame.isEmpty()) {
return false;
}
- final HardwareBuffer buffer = snapshot.getHardwareBuffer();
- return Math.abs(
- ((float) buffer.getWidth() / buffer.getHeight())
- - ((float) frame.width() / frame.height())) <= 0.01f;
+ return Math.abs(((float) w / h) - ((float) frame.width() / frame.height())) <= 0.01f;
}
private static boolean isAspectRatioMatch(Rect frame1, Rect frame2) {
@@ -378,14 +374,14 @@
*/
public static void drawSnapshotOnSurface(StartingWindowInfo info, WindowManager.LayoutParams lp,
SurfaceControl rootSurface, TaskSnapshot snapshot,
- Rect configBounds, Rect windowBounds, InsetsState topWindowInsetsState,
+ Rect windowBounds, InsetsState topWindowInsetsState,
boolean releaseAfterDraw) {
if (windowBounds.isEmpty()) {
Log.e(TAG, "Unable to draw snapshot on an empty windowBounds");
return;
}
final SnapshotSurface drawSurface = new SnapshotSurface(
- rootSurface, snapshot, lp.getTitle(), configBounds);
+ rootSurface, snapshot, lp.getTitle());
final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 260d9a8..72df343 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -22,6 +22,7 @@
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -79,11 +80,17 @@
/**
* The {@link TaskInfo} from this task.
- * @hide
+ * <p>Note that the configuration of this taskInfo could be from the top activity of its task.
+ * Because only activity contains persisted configuration (e.g. night mode, language). Besides,
+ * it can also be used for activity level snapshot.
*/
@NonNull
public ActivityManager.RunningTaskInfo taskInfo;
+ /** The bounds of the target task. */
+ @NonNull
+ public final Rect taskBounds = new Rect();
+
/**
* The {@link ActivityInfo} of the target activity which to create the starting window.
* It can be null if the info is the same as the top in task info.
@@ -253,6 +260,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(taskInfo, flags);
+ taskBounds.writeToParcel(dest, flags);
dest.writeTypedObject(targetActivityInfo, flags);
dest.writeInt(startingWindowTypeParameter);
dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
@@ -269,6 +277,7 @@
void readFromParcel(@NonNull Parcel source) {
taskInfo = source.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ taskBounds.readFromParcel(source);
targetActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
startingWindowTypeParameter = source.readInt();
topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 7f6678e..cf0c015 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -176,6 +176,12 @@
mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
return;
}
+ if ((callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback
+ || callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
+ && !isOnBackInvokedCallbackEnabled()) {
+ // Fall back to compat back key injection if legacy back behaviour should be used.
+ return;
+ }
if (!mOnBackInvokedCallbacks.containsKey(priority)) {
mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
}
diff --git a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
index 98ff3c6..cd13c4a 100644
--- a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
+++ b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
@@ -2,6 +2,13 @@
container: "system"
flag {
+ name: "disable_thin_letterboxing_reachability"
+ namespace: "large_screen_experiences_app_compat"
+ description: "Whether reachability is disabled in case of thin letterboxing"
+ bug: "334077350"
+}
+
+flag {
name: "allows_screen_size_decoupled_from_status_bar_and_cutout"
namespace: "large_screen_experiences_app_compat"
description: "When necessary, configuration decoupled from status bar and display cutout"
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 001ed79..945164a 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -109,4 +109,15 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+flag {
+ namespace: "windowing_sdk"
+ name: "window_session_relayout_info"
+ description: "Pass an out RelayoutInfo instead of Bundle to fix the Parcel recycle bug"
+ bug: "335601427"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 4f55441..d72207d 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -272,6 +272,7 @@
getOpenInWorkMessage(launchIntent, target.loadLabel(packageManagerForTargetUser)),
packageManagerForTargetUser);
+ ((Button) findViewById(R.id.button_open)).setText(getOpenInWorkButtonString(launchIntent));
View telephonyInfo = findViewById(R.id.miniresolver_info_section);
@@ -310,7 +311,15 @@
packageManagerForTargetUser);
View telephonyInfo = findViewById(R.id.miniresolver_info_section);
- telephonyInfo.setVisibility(View.GONE);
+ telephonyInfo.setVisibility(View.VISIBLE);
+
+ if (isTextMessageIntent(launchIntent)) {
+ ((TextView) findViewById(R.id.miniresolver_info_section_text)).setText(
+ R.string.miniresolver_private_space_messages_information);
+ } else {
+ ((TextView) findViewById(R.id.miniresolver_info_section_text)).setText(
+ R.string.miniresolver_private_space_phone_information);
+ }
}
private void buildMiniResolver(ResolveInfo target, Intent launchIntent, int targetUserId,
@@ -334,7 +343,6 @@
((Button) findViewById(R.id.use_same_profile_browser)).setText(R.string.cancel);
findViewById(R.id.use_same_profile_browser).setOnClickListener(v -> finish());
- ((Button) findViewById(R.id.button_open)).setText(getOpenInWorkButtonString(launchIntent));
findViewById(R.id.button_open).setOnClickListener(v -> {
startActivityAsCaller(
launchIntent,
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 5705b7e..7ac553c 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -48,8 +48,6 @@
public abstract class PackageMonitor extends android.content.BroadcastReceiver {
static final String TAG = "PackageMonitor";
- final IntentFilter mPackageFilt;
-
Context mRegisteredContext;
Handler mRegisteredHandler;
String[] mDisappearingPackages;
@@ -66,17 +64,32 @@
private Executor mExecutor;
+ final boolean mSupportsPackageRestartQuery;
+
@UnsupportedAppUsage
public PackageMonitor() {
+ this(true);
+ }
+
+ /**
+ * The constructor of PackageMonitor whose parameters clearly indicate whether support
+ * querying package restart event.
+ */
+ public PackageMonitor(boolean supportsPackageRestartQuery) {
+ mSupportsPackageRestartQuery = supportsPackageRestartQuery;
+ }
+
+ private IntentFilter getPackageFilter() {
final boolean isCore = UserHandle.isCore(android.os.Process.myUid());
- mPackageFilt = new IntentFilter();
+ IntentFilter filter = new IntentFilter();
// Settings app sends the broadcast
- mPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
- mPackageFilt.addDataScheme("package");
+ filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+ filter.addDataScheme("package");
if (isCore) {
- mPackageFilt.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
}
+ return filter;
}
@UnsupportedAppUsage
@@ -91,7 +104,6 @@
(thread == null) ? BackgroundThread.getHandler() : new Handler(thread));
}
-
/**
* Register for notifications of package changes such as install, removal and other events.
*/
@@ -101,10 +113,13 @@
}
mRegisteredContext = context;
mRegisteredHandler = Objects.requireNonNull(handler);
- if (user != null) {
- context.registerReceiverAsUser(this, user, mPackageFilt, null, mRegisteredHandler);
- } else {
- context.registerReceiver(this, mPackageFilt, null, mRegisteredHandler);
+ if (mSupportsPackageRestartQuery) {
+ final IntentFilter filter = getPackageFilter();
+ if (user != null) {
+ context.registerReceiverAsUser(this, user, filter, null, mRegisteredHandler);
+ } else {
+ context.registerReceiver(this, filter, null, mRegisteredHandler);
+ }
}
if (mPackageMonitorCallback == null) {
PackageManager pm = mRegisteredContext.getPackageManager();
@@ -126,7 +141,9 @@
if (mRegisteredContext == null) {
throw new IllegalStateException("Not registered");
}
- mRegisteredContext.unregisterReceiver(this);
+ if (mSupportsPackageRestartQuery) {
+ mRegisteredContext.unregisterReceiver(this);
+ }
PackageManager pm = mRegisteredContext.getPackageManager();
if (pm != null && mPackageMonitorCallback != null) {
@@ -378,7 +395,7 @@
* @param intent the intent that contains package related event information
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public void doHandlePackageEvent(Intent intent) {
+ public final void doHandlePackageEvent(Intent intent) {
mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL);
if (mChangeUserId == UserHandle.USER_NULL) {
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 8aba36b..e6af64a 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -133,6 +133,13 @@
// For state2, trace all bit changes.
static final int STATE2_TRACE_MASK = ~0;
+ /**
+ * Number of overflow bytes that can be written into the history buffer if the history
+ * directory is locked. This is done to prevent a long lock contention and a potential
+ * kill by a watchdog.
+ */
+ private static final int EXTRA_BUFFER_SIZE_WHEN_DIR_LOCKED = 100_000;
+
private final Parcel mHistoryBuffer;
private final File mSystemDir;
private final HistoryStepDetailsCalculator mStepDetailsCalculator;
@@ -260,6 +267,10 @@
mLock.lock();
}
+ boolean tryLock() {
+ return mLock.tryLock();
+ }
+
void unlock() {
mLock.unlock();
if (mCleanupNeeded) {
@@ -469,14 +480,12 @@
return;
}
- if (isLocked()) {
+ if (!tryLock()) {
mCleanupNeeded = true;
return;
}
mCleanupNeeded = false;
-
- lock();
try {
// if free disk space is less than 100MB, delete oldest history file.
if (!hasFreeDiskSpace(mDirectory)) {
@@ -1772,29 +1781,12 @@
}
mHistoryLastWritten.setTo(mHistoryLastLastWritten);
}
- final int dataSize = mHistoryBuffer.dataSize();
- if (dataSize >= mMaxHistoryBufferSize) {
- if (mMaxHistoryBufferSize == 0) {
- Slog.wtf(TAG, "mMaxHistoryBufferSize should not be zero when writing history");
- mMaxHistoryBufferSize = 1024;
- }
-
- // Make a copy of mHistoryCur.
- HistoryItem copy = new HistoryItem();
- copy.setTo(cur);
-
- startNextFile(elapsedRealtimeMs);
-
- // startRecordingHistory will reset mHistoryCur.
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
-
- // Add the copy into history buffer.
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, copy, HistoryItem.CMD_UPDATE);
+ if (maybeFlushBufferAndWriteHistoryItem(cur, elapsedRealtimeMs, uptimeMs)) {
return;
}
- if (dataSize == 0) {
+ if (mHistoryBuffer.dataSize() == 0) {
// The history is currently empty; we need it to start with a time stamp.
HistoryItem copy = new HistoryItem();
copy.setTo(cur);
@@ -1812,6 +1804,52 @@
}
@GuardedBy("this")
+ private boolean maybeFlushBufferAndWriteHistoryItem(HistoryItem cur, long elapsedRealtimeMs,
+ long uptimeMs) {
+ int dataSize = mHistoryBuffer.dataSize();
+ if (dataSize < mMaxHistoryBufferSize) {
+ return false;
+ }
+
+ if (mMaxHistoryBufferSize == 0) {
+ Slog.wtf(TAG, "mMaxHistoryBufferSize should not be zero when writing history");
+ mMaxHistoryBufferSize = 1024;
+ }
+
+ boolean successfullyLocked = mHistoryDir.tryLock();
+ if (!successfullyLocked) { // Already locked by another thread
+ // If the buffer size is below the allowed overflow limit, just keep going
+ if (dataSize < mMaxHistoryBufferSize + EXTRA_BUFFER_SIZE_WHEN_DIR_LOCKED) {
+ return false;
+ }
+
+ // Report the long contention as a WTF and flush the buffer anyway, potentially
+ // triggering a watchdog kill, which is still better than spinning forever.
+ Slog.wtf(TAG, "History buffer overflow exceeds " + EXTRA_BUFFER_SIZE_WHEN_DIR_LOCKED
+ + " bytes");
+ }
+
+ // Make a copy of mHistoryCur before starting a new file
+ HistoryItem copy = new HistoryItem();
+ copy.setTo(cur);
+
+ try {
+ startNextFile(elapsedRealtimeMs);
+ } finally {
+ if (successfullyLocked) {
+ mHistoryDir.unlock();
+ }
+ }
+
+ // startRecordingHistory will reset mHistoryCur.
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
+
+ // Add the copy into history buffer.
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, copy, HistoryItem.CMD_UPDATE);
+ return true;
+ }
+
+ @GuardedBy("this")
private void writeHistoryItem(long elapsedRealtimeMs,
@SuppressWarnings("UnusedVariable") long uptimeMs, HistoryItem cur, byte cmd) {
if (!mMutable) {
diff --git a/core/java/com/android/internal/os/PowerStats.java b/core/java/com/android/internal/os/PowerStats.java
index 7c7c7b8..9f9aae5 100644
--- a/core/java/com/android/internal/os/PowerStats.java
+++ b/core/java/com/android/internal/os/PowerStats.java
@@ -473,7 +473,14 @@
} finally {
// Unconditionally skip to the end of the written data, even if the actual parcel
// format is incompatible
- parcel.setDataPosition(endPos);
+ if (endPos > parcel.dataPosition()) {
+ if (endPos >= parcel.dataSize()) {
+ throw new IndexOutOfBoundsException(
+ "PowerStats end position: " + endPos + " is outside the parcel bounds: "
+ + parcel.dataSize());
+ }
+ parcel.setDataPosition(endPos);
+ }
}
}
diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index 9dec102..2f09a55 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -1340,35 +1340,39 @@
final int pixelStride = plane.getPixelStride();
final int rowStride = plane.getRowStride();
final int sampling = 10;
- final int[] borderLumas = new int[(width + height) * 2 / sampling];
+ final int[] histogram = new int[256];
// Grab the top and bottom borders.
int i = 0;
for (int x = 0, size = width - sampling; x < size; x += sampling) {
- borderLumas[i++] = getPixelLuminance(buffer, x, 0, pixelStride, rowStride);
- borderLumas[i++] = getPixelLuminance(buffer, x, height - 1, pixelStride, rowStride);
+ final int topLm = getPixelLuminance(buffer, x, 0, pixelStride, rowStride);
+ final int bottomLm = getPixelLuminance(buffer, x, height - 1, pixelStride, rowStride);
+ histogram[topLm]++;
+ histogram[bottomLm]++;
}
// Grab the left and right borders.
for (int y = 0, size = height - sampling; y < size; y += sampling) {
- borderLumas[i++] = getPixelLuminance(buffer, 0, y, pixelStride, rowStride);
- borderLumas[i++] = getPixelLuminance(buffer, width - 1, y, pixelStride, rowStride);
+ final int leftLm = getPixelLuminance(buffer, 0, y, pixelStride, rowStride);
+ final int rightLm = getPixelLuminance(buffer, width - 1, y, pixelStride, rowStride);
+ histogram[leftLm]++;
+ histogram[rightLm]++;
}
ir.close();
- // Get "mode" by histogram.
- final int[] histogram = new int[256];
- int maxCount = 0;
- int mostLuma = 0;
- for (int luma : borderLumas) {
- final int count = ++histogram[luma];
- if (count > maxCount) {
- maxCount = count;
- mostLuma = luma;
+ // Find the median from histogram.
+ final int halfNum = (width + height) / sampling;
+ int sum = 0;
+ int medianLuminance = 0;
+ for (i = 0; i < histogram.length; i++) {
+ sum += histogram[i];
+ if (sum >= halfNum) {
+ medianLuminance = i;
+ break;
}
}
- return mostLuma / 255f;
+ return medianLuminance / 255f;
}
/** Returns the luminance of the pixel in 0~255. */
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index b3e1df1..874cc49 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -131,7 +131,8 @@
Runnable cacheUpdater
) {
Producer.init(InitArguments.DEFAULTS);
- mDataSource.register(DataSourceParams.DEFAULTS);
+ mDataSource.register(new DataSourceParams(
+ DataSourceParams.PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT));
this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
this.mViewerConfigReader = viewerConfigReader;
this.mLogGroups = logGroups;
@@ -191,8 +192,6 @@
Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump on tracing end", e);
}
});
-
- mDataSource.flush();
}
private static void writeViewerConfigGroup(
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index 69d3d6a..c21a43e 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -53,8 +53,6 @@
public ScreenshotHelper(Context context) {
mContext = context;
- IntentFilter filter = new IntentFilter(ACTION_USER_SWITCHED);
- mContext.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED);
}
/**
@@ -108,6 +106,8 @@
public void takeScreenshotInternal(ScreenshotRequest request, @NonNull Handler handler,
@Nullable Consumer<Uri> completionConsumer, long timeoutMs) {
synchronized (mScreenshotLock) {
+ mContext.registerReceiver(mBroadcastReceiver,
+ new IntentFilter(ACTION_USER_SWITCHED), Context.RECEIVER_EXPORTED);
final Runnable mScreenshotTimeout = () -> {
synchronized (mScreenshotLock) {
@@ -223,6 +223,11 @@
mScreenshotConnection = null;
mScreenshotService = null;
}
+ try {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Attempted to remove broadcast receiver twice");
+ }
}
/**
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index 18d5f6d..54b9a22 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -386,6 +386,11 @@
}
@Override
+ public void finalize() {
+ zeroize();
+ }
+
+ @Override
public int hashCode() {
// Effective Java — Always override hashCode when you override equals
return Objects.hash(mType, Arrays.hashCode(mCredential), mHasInvalidChars);
diff --git a/core/java/com/android/internal/widget/NotificationRowIconView.java b/core/java/com/android/internal/widget/NotificationRowIconView.java
new file mode 100644
index 0000000..4031b2f
--- /dev/null
+++ b/core/java/com/android/internal/widget/NotificationRowIconView.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.app.Flags;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.RemoteViews;
+
+import androidx.annotation.Nullable;
+
+/**
+ * An image view that holds the icon displayed on the left side of a notification row.
+ */
+@RemoteViews.RemoteView
+public class NotificationRowIconView extends CachingIconView {
+ public NotificationRowIconView(Context context) {
+ super(context);
+ }
+
+ public NotificationRowIconView(Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public NotificationRowIconView(Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public NotificationRowIconView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ // If showing the app icon, we don't need background or padding.
+ if (Flags.notificationsUseAppIcon()) {
+ setPadding(0, 0, 0, 0);
+ setBackground(null);
+ }
+
+ super.onFinishInflate();
+ }
+}
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index a022842..7267eb8 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -190,17 +190,21 @@
return -1;
}
- jbyte* bufferBytes = NULL;
- if (buffer) {
- bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL);
+ bool is_dir_in = (endpoint & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
+ jbyte *bufferBytes = (jbyte *)malloc(length);
+
+ if (!is_dir_in && buffer) {
+ env->GetByteArrayRegion(buffer, start, length, bufferBytes);
}
- jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes + start, length, timeout);
+ jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout);
- if (bufferBytes) {
- env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0);
+ if (is_dir_in && buffer) {
+ env->SetByteArrayRegion(buffer, start, length, bufferBytes);
}
+ free(bufferBytes);
+
return result;
}
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 7f3b32e..88e6fa3 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -190,15 +190,31 @@
return;
}
}
+ // Calling SystemProperties.set() with a null value is equivalent to an
+ // empty string, but this is not true for the underlying libc function.
+ const char* value_c_str = value ? value->c_str() : "";
+ // Explicitly clear errno so we can recognize __system_property_set()
+ // failures from failed system calls (as opposed to "init rejected your
+ // request" failures).
+ errno = 0;
bool success;
#if defined(__BIONIC__)
- success = !__system_property_set(key.c_str(), value ? value->c_str() : "");
+ success = !__system_property_set(key.c_str(), value_c_str);
#else
- success = android::base::SetProperty(key.c_str(), value ? value->c_str() : "");
+ success = android::base::SetProperty(key.c_str(), value_c_str);
#endif
if (!success) {
- jniThrowException(env, "java/lang/RuntimeException",
- "failed to set system property (check logcat for reason)");
+ if (errno != 0) {
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "failed to set system property \"%s\" to \"%s\": %m",
+ key.c_str(), value_c_str);
+ } else {
+ // Must have made init unhappy, which will have logged something,
+ // but there's no API to ask for more detail.
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "failed to set system property \"%s\" to \"%s\" (check logcat for reason)",
+ key.c_str(), value_c_str);
+ }
}
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 9abb5c8..cb7c226 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -102,7 +102,7 @@
optional SettingProto qs_targets = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_pinch_to_zoom_anywhere_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_single_finger_panning_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto accessibility_floating_menu_targets = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_gesture_targets = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto display_daltonizer_saturation_level = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index d31baf3..e3a438d 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -1059,6 +1059,7 @@
optional int32 uid = 1;
repeated .android.app.ApplicationStartInfoProto app_start_info = 2;
+ optional bool monitoring_enabled = 3;
}
repeated User users = 2;
}
diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto
index 9151958..1d9b0db 100644
--- a/core/proto/android/server/vibrator/vibratormanagerservice.proto
+++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto
@@ -116,7 +116,7 @@
reserved 6; // prev int32 status
// Also used by VibrationReported from frameworks/proto_logging/stats/atoms.proto.
- // Next Tag: 26
+ // Next Tag: 29
enum Status {
UNKNOWN = 0;
RUNNING = 1;
@@ -135,7 +135,6 @@
IGNORED_ERROR_TOKEN= 14;
IGNORED_APP_OPS = 15;
IGNORED_BACKGROUND = 16;
- IGNORED_UNKNOWN_VIBRATION = 17;
IGNORED_UNSUPPORTED = 18;
IGNORED_FOR_EXTERNAL = 19;
IGNORED_FOR_HIGHER_IMPORTANCE = 20;
@@ -146,6 +145,8 @@
IGNORED_SUPERSEDED = 25;
IGNORED_FROM_VIRTUAL_DEVICE = 26;
IGNORED_ON_WIRELESS_CHARGER = 27;
+ IGNORED_MISSING_PERMISSION = 28;
+ reserved 17; // prev IGNORED_UNKNOWN_VIBRATION
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 567844c..77a9912 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6200,7 +6200,7 @@
@hide
@removed -->
<permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|role" />
<!-- Allows an application to know what content is playing and control its playback.
<p>Not for use by third-party applications due to privacy of media consumption</p> -->
@@ -8233,7 +8233,7 @@
</activity>
<activity android:name="com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity"
android:exported="false"
- android:theme="@style/Theme.DeviceDefault.Resolver"
+ android:theme="@style/AccessibilityButtonChooserDialog"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
android:documentLaunchMode="never"
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 3489cac..a7d1a86 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -33,6 +33,19 @@
# Multiuser
per-file res/xml/config_user_types.xml = file:/MULTIUSER_OWNERS
+# Notifications
+per-file res/*/*notification* = file:/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS
+# TODO(b/337816136): Move notification values to separate files
+per-file res/values*/attrs.xml = jeffdq@google.com
+per-file res/values*/colors.xml = jeffdq@google.com
+per-file res/values*/dimens.xml = jeffdq@google.com
+per-file res/values*/config.xml = jeffdq@google.com
+per-file res/values/ids.xml = jeffdq@google.com
+per-file res/values/strings.xml = jeffdq@google.com
+per-file res/values/symbols.xml = jeffdq@google.com
+per-file res/values/themes_device_defaults.xml = jeffdq@google.com
+per-file res/values/styles_material.xml = jeffdq@google.com
+
# Battery Saver
per-file res/values/config_battery_saver.xml = file:/services/core/java/com/android/server/power/batterysaver/OWNERS
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 6f06d80..d80b765 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -41,7 +41,7 @@
android:visibility="gone"
/>
- <com.android.internal.widget.CachingIconView
+ <com.android.internal.widget.NotificationRowIconView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_circle_size"
android:layout_height="@dimen/notification_icon_circle_size"
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 64227d8..452df50 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -37,7 +37,7 @@
android:visibility="gone"
/>
- <com.android.internal.widget.CachingIconView
+ <com.android.internal.widget.NotificationRowIconView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_circle_size"
android:layout_height="@dimen/notification_icon_circle_size"
diff --git a/core/res/res/layout/notification_template_material_compact_heads_up_base.xml b/core/res/res/layout/notification_template_material_compact_heads_up_base.xml
index 57da898..f38da26 100644
--- a/core/res/res/layout/notification_template_material_compact_heads_up_base.xml
+++ b/core/res/res/layout/notification_template_material_compact_heads_up_base.xml
@@ -23,7 +23,7 @@
android:gravity="center_vertical"
android:theme="@style/Theme.DeviceDefault.Notification"
android:importantForAccessibility="no">
- <com.android.internal.widget.CachingIconView
+ <com.android.internal.widget.NotificationRowIconView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_circle_size"
android:layout_height="@dimen/notification_icon_circle_size"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 8a94c48..6e9d17f 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -38,7 +38,7 @@
android:visibility="gone"
/>
- <com.android.internal.widget.CachingIconView
+ <com.android.internal.widget.NotificationRowIconView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_circle_size"
android:layout_height="@dimen/notification_icon_circle_size"
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index a83d923..1eae41d 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -51,7 +51,7 @@
android:visibility="gone"
/>
- <com.android.internal.widget.CachingIconView
+ <com.android.internal.widget.NotificationRowIconView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_circle_size"
android:layout_height="@dimen/notification_icon_circle_size"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 8218ff1..7f0e4c2 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> sekondes"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nie aangestuur nie"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nie aangestuur nie"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Selnetwerksekuriteit"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Gaan instellings na"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Toegang gekry tot toestelidentifiseerder"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"’n Netwerk op die <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>-verbinding het jou toestel se unieke identifiseerder (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> keer in die tydperk tussen <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> en <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> aangeteken."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Geënkripteerde verbinding aan <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Jy is nou gekoppel aan ’n veiliger selnetwerk."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nie-geënkripteerde verbinding aan <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Jy is gekoppel aan \'n nie-geënkripteerde selnetwerk. Jou oproepe, boodskappe en data is kwesbaar vir onderskepping."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Selsekuriteitinstellings"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Meer inligting"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kenmerkkode klaar."</string>
<string name="fcError" msgid="5325116502080221346">"Verbindingsprobleem of ongeldige kenmerk-kode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -830,7 +845,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Stel wagwoordreëls"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Beheer die lengte en die karakters wat in skermslotwagwoorde en -PIN\'e toegelaat word."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor pogings om skerm te ontsluit"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor die aantal keer wat \'n verkeerde wagwoorde ingevoer is wanneer die skerm ontsluit word. Sluit die tablet of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor die aantal keer wat \'n verkeerde wagwoord ingevoer word wanneer die skerm ontsluit word. Sluit die tablet of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor die aantal verkeerde wagwoorde wat ingetik word wanneer die skerm ontsluit word, en sluit jou Android TV-toestel of vee al jou Android TV-toestel se data uit as te veel verkeerde wagwoorde ingetik word."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor die aantal verkeerde wagwoorde wat ingevoer word wanneer die skerm ontsluit word, en sluit die inligtingvermaakstelsel of vee al die inligtingvermaakstelsel se data uit as te veel verkeerde wagwoorde ingevoer word."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor die aantal keer wat \'n verkeerde wagwoorde ingevoer is wanneer die skerm ontsluit word. Sluit die foon of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string>
@@ -843,7 +858,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Om die skerm te sluit"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Beheer hoe en wanneer die skerm sluit."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Om alle data uit te vee"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vee die tablet se data uit sonder waarskuwing, deur \'n fabrieksterugstelling uit te voer."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vee die tablet se data uit sonder waarskuwing, deur \'n fabriekterugstelling uit te voer."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Vee jou Android TV-toestel se data sonder waarskuwing uit deur \'n fabrieksterugstelling uit te voer."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Vee die inligtingvermaakstelsel se data sonder waarskuwing uit deur \'n fabriekterugstelling te doen."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Vee die foon se data uit sonder waarskuwing, deur \'n fabrieksterugstelling uit te voer."</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vra PIN voordat jy ontspeld"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vra ontsluitpatroon voordat jy ontspeld"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vra wagwoord voordat jy ontspeld"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Deur jou admin geïnstalleer.\nGaan na instellings om toegestaande toestemmings te sien"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Opgedateer deur jou administrateur"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Uitgevee deur jou administrateur"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Skakel oor na werkapp?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Jou organisasie laat jou net toe om oproepe van werkapps af te maak"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Jou organisasie laat jou net toe om boodskappe van werkapps af te stuur"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gebruik persoonlike blaaier"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gebruik werkblaaier"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Bel"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Werk 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Toets"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Gemeenskaplik"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Sensitiewe kennisgewinginhoud is versteek"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Appinhoud is weens sekuriteit van skermdeling verberg"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Outomaties aan satelliet gekoppel"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b1f9447..cf6cd30 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡<xliff:g id="DIALING_NUMBER">{1}</xliff:g> ከ<xliff:g id="TIME_DELAY">{2}</xliff:g> ሰከንዶች በኋላ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡አልተላለፈም"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡አልተላለፈም"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"የተንቀሳቃሽ ስልክ አውታረ መረብ ደኅንነት"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ቅንብሮችን ይገምግሙ"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"የመሣሪያ ለዪ ተደርሶበታል"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"በ<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ግንኙነት ላይ ያለው አውታረ መረብ የመሣሪያዎን ተለይቶ የሚታወቅ (IMSI) በ<xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> እና በ<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> መካከል ባለው ጊዜ ውስጥ <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ጊዜ መዝግቧል።"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"የተመሰጠረ ግንኙነት ከ<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ጋር"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"አሁን ይበልጥ ደኅንነቱ ከተጠበቀ የተንቀሳቃሽ ስልክ አውታረ መረብ ጋር ተገናኝተዋል።"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"ያልተመሰጠረ ግንኙነት ከ<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ጋር"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"ካልተመሰጠረ የተንቀሳቃሽ ስልክ አውታረ መረብ ጋር ተገናኝተዋል። የእርስዎ ጥሪዎች፣ መልዕክቶች እና ውሂብ ለመጠለፍ የተጋለጡ ናቸው።"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"የተንቀሳቃሽ ስልክ ደኅንነት ቅንብሮች"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"የበለጠ ለመረዳት"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">" ኮድ ባህሪይ ተጠናቋል።"</string>
<string name="fcError" msgid="5325116502080221346">"የተያያዥ ችግር ወይም ትክከል ያልሆነኮድ ባህሪ።"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"እሺ"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ቅጽበታዊ ገፅ እይታን ያነሳል"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"የማሳያው ቅጽበታዊ ገፅ እይታን ማንሳት ይችላል።"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"ቅድመ ዕይታ፣ <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"አሰናብት"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"የሁኔታ አሞሌ መሆን"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ከመንቀል በፊት ፒን ጠይቅ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ከመንቀል በፊት የማስከፈቻ ሥርዓተ-ጥለት ጠይቅ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"በአስተዳዳሪዎ ተጭኗል።\nየተፈቀዱ ፍቃዶችን ለማየት ወደ ቅንብሮች ይሂዱ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"በእርስዎ አስተዳዳሪ ተዘምኗል"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"በእርስዎ አስተዳዳሪ ተሰርዟል"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"እሺ"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ወደ የሥራ መተግበሪያ ይቀየር?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ድርጅትዎ ከሥራ መተግበሪያዎች ብቻ ጥሪዎችን እንዲያደርጉ ይፈቅድልዎታል"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ድርጅትዎ ከሥራ መተግበሪያዎች ብቻ መልዕክቶችን እንዲልኩ ይፈቅድልዎታል"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"የግል አሳሽ ተጠቀም"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"የስራ አሳሽ ተጠቀም"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ደውል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 453998f..dfaa285 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -157,16 +157,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانية"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"أمان شبكة الجوّال"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"مراجعة الإعدادات"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"تم رصد معرِّف جهازك"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"هناك شبكة تراقب الاتصال \"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>\" رصدت المعرّف الفريد لجهازك (رقم التعريف الدولي للمشترك في خدمات الجوّال (IMSI)) بمقدار <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> مرة في الفترة بين <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> و<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"اتصال مشفَّر بشبكة \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"أنت الآن متصل بشبكة جوّال أكثر أمانًا."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"اتصال غير مشفَّر بشبكة \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"أنت الآن متصل بشبكة جوّال غير مشفَّرة. لذلك، يمكن أن يتم اعتراض مكالماتك ورسائلك وبياناتك."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"إعدادات الأمان المتعلّقة بشبكة الجوّال"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"مزيد من المعلومات"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"اكتمل رمز الميزة."</string>
<string name="fcError" msgid="5325116502080221346">"حدثت مشكلة بالاتصال أو أن رمز الميزة غير صحيح."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"حسنًا"</string>
@@ -360,8 +375,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"أخذ لقطة شاشة"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"يمكن أخذ لقطة شاشة."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"نسخة حصرية، \"<xliff:g id="DREAM_NAME">%1$s</xliff:g>\""</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"إغلاق"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"للسماح للتطبيق بإيقاف شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"العمل كشريط للحالة"</string>
@@ -2221,6 +2235,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"هل تريد الانتقال إلى تطبيق العمل؟"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"تسمح لك مؤسستك بإجراء المكالمات من تطبيقات العمل فقط."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"تسمح لك مؤسستك بإرسال الرسائل من تطبيقات العمل فقط."</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"استخدام المتصفّح الشخصي"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"استخدام متصفّح العمل"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"الاتصال"</string>
@@ -2400,8 +2418,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ملف العمل 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ملف شخصي تجريبي"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ملف شخصي مشترك"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"تم إخفاء المحتوى الحساس في الإشعار"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"تم إخفاء محتوى التطبيق بعد تفعيل ميزة \"مشاركة الشاشة\" للحفاظ على أمانك"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"تم الاتصال تلقائيًا بالقمر الصناعي"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 89a6f97..c695e86 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ছেকেণ্ডৰ পাছত"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"চেলুলাৰ নেটৱৰ্কৰ সুৰক্ষা"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ছেটিং পৰ্যালোচনা কৰক"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ডিভাইচৰ চিনাক্তকৰ্তা এক্সেছ কৰা হৈছে"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> সংযোগত এটা নেটৱৰ্কে আপোনাৰ ডিভাইচৰ অদ্বিতীয় চিনাক্তকৰ্তা (IMSI)ক <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> আৰু <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>ৰ মাজৰ সময় অৱধিত<xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> বাৰ ৰেকৰ্ড কৰিছে।"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>ৰ সৈতে এনক্ৰিপ্ট কৰা সংযোগ"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"আপুনি এতিয়া এটা অধিক সুৰক্ষিত চেলুলাৰ নেটৱৰ্কৰ সৈতে সংযুক্ত হৈছে।"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>ৰ সৈতে এনক্ৰিপ্ট নকৰা সংযোগ"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"আপুনি এটা এনক্ৰিপ্ট নকৰা চেলুলাৰ নেটৱৰ্কৰ সৈতে সংযুক্ত হৈছে। আপোনাৰ কল, বাৰ্তা আৰু ডেটা বাধাগ্ৰস্ত হ’ব পাৰে।"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"চেলুলাৰ সুৰক্ষাৰ ছেটিং"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"অধিক জানক"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"সুবিধাৰ ক\'ড সম্পূর্ণ হ’ল।"</string>
<string name="fcError" msgid="5325116502080221346">"সংযোগত সমস্যা হৈছে বা সুবিধাৰ ক\'ড অমান্য।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ঠিক আছে"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্ৰীনশ্বট লওক"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিছপ্লে’খনৰ এটা স্ক্ৰীনশ্বট ল\'ব পাৰে।"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"পূৰ্বদৰ্শন কৰক, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"অগ্ৰাহ্য কৰক"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপ্টোক অনুমতি দিয়ে।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দণ্ড হ\'ব পাৰে"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন কৰাৰ পূৰ্বে পিন দিবলৈ কওক"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন কৰাৰ পূৰ্বে আনলক আৰ্হি দিবলৈ কওক"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন কৰাৰ পূৰ্বে পাছৱৰ্ড দিবলৈ কওক"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"আপোনাৰ প্ৰশাসকে ইনষ্টল কৰিছে।\nপ্ৰদান কৰা অনুমতিসমূহ চাবলৈ ছেটিঙলৈ যাওক"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"আপোনাৰ প্ৰশাসকে আপেডট কৰিছে"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"আপোনাৰ প্ৰশাসকে মচিছে"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ঠিক আছে"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ইয়াৰ সলনি কাম সম্পৰ্কীয় এপ্ ব্যৱহাৰ কৰিবনে?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাক কেৱল কাম সম্পৰ্কীয় এপ্সমূহৰ পৰা কল কৰিবলৈ অনুমতি দিয়ে"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাক কেৱল কাম সম্পৰ্কীয় এপ্সমূহৰ পৰা বাৰ্তা পঠিওৱাৰ অনুমতি দিয়ে"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ব্যক্তিগত ব্ৰাউজাৰ ব্যৱহাৰ কৰক"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"কৰ্মস্থানৰ ব্ৰাউজাৰ ব্যৱহাৰ কৰক"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"কল কৰক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 3bc5b92..c110e3e 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> saniyə sonra"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönləndirilmədi"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönləndirilmədi"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobil şəbəkə güvənliyi"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Ayarları nəzərdən keçirin"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Cihaz identifikatoruna giriş edilib"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> bağlantısındakı şəbəkə <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> və <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> aralığında <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> dəfə cihazın unikal identifikatorunu (IMSI) qeydə aldı."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ilə bağlantı şifrələndi"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Güvənli mobil şəbəkəyə qoşuldunuz."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ilə şifrələnməmiş bağlantı"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Şifrələnməmiş mobil şəbəkəyə qoşulmusunuz. Zəng, mesaj və data ələ keçirilə bilər."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobil güvənlik ayarları"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Ətraflı məlumat"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Özəllik kodu tamamlandı."</string>
<string name="fcError" msgid="5325116502080221346">"Əlaqə problemi və ya yanlış funksiya kodu."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ayırmadan öncə PIN istənilsin"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Qrafik açar istənilsin"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ayırmadan öncə parol istənilsin"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Admin quraşdırıb.\nVerilən icazələrə baxmaq üçün ayarlara keçin"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Admin tərəfindən yeniləndi"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Admin tərəfindən silindi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"İş tətbiqinə dəyişilsin?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Təşkilat yalnız iş tətbiqindən zəng etməyə icazə verir"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Təşkilat yalnız iş tətbiqindən mesaj göndərməyə icazə verir"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Şəxsi brauzerdən istifadə edin"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"İş brauzerindən istifadə edin"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Zəng edin"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"İş 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Kommunal"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Həssas bildiriş kontenti gizlədildi"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Güvənlik üçün tətbiq kontenti ekran paylaşımından gizlədildi"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Peykə avtomatik qoşulub"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 5a79197..2977bfb 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunde/i"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Bezbednost mobilne mreže"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Pregledajte podešavanja"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Pristupljeno je identifikatoru uređaja"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Mreža na <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> vezi je zabeležila jedinstveni identifikator (IMSI) uređaja <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> put/a u periodu od <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> do <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifrovana veza sa: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Povezani ste na bezbedniju mobilnu mrežu."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifrovana veza sa: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Povezani ste na mobilnu mrežu koja nije šifrovana. Pozivi, poruke i podaci su podložni presretanju."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Podešavanja bezbednosti mobilne mreže"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saznajte više"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kôd funkcije je izvršen."</string>
<string name="fcError" msgid="5325116502080221346">"Problemi sa vezom ili nevažeći kôd funkcije."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Potvrdi"</string>
@@ -357,8 +372,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Napravi snimak ekrana"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može da napravi snimak ekrana."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"odbaci"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmena statusne trake"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"funkcionisanje kao statusna traka"</string>
@@ -1899,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN pre otkačinjanja"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži šablon za otključavanje pre otkačinjanja"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku pre otkačinjanja"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalirao je administrator.\nIdite u podešavanja da biste videli odobrene dozvole"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Potvrdi"</string>
@@ -2218,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite da prebacite na poslovnu aplikaciju?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija dozvoljava pozivanje samo iz poslovnih aplikacija"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija dozvoljava slanje poruka samo iz poslovnih aplikacija"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi lični pregledač"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni pregledač"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Pozovi"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 9f07bd4..0a009a2 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> праз <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не пераадрасоўваецца"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не пераадрасоўваецца"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Бяспека сотавай сеткі"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Праглядзець налады"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Доступ да ідэнтыфікатара прылады"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Сетка (падключэнне <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>) запісвала нумар IMSI вашай прылады некалькі разоў (<xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>) у перыяд з <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> да <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Зашыфраванае падключэнне да сеткі \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Цяпер вы падключаны да больш бяспечнай сотавай сеткі"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Незашыфраванае падключэнне да сеткі \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Вы падключаны да незашыфраванай сотавай сеткі. Вашы выклікі, паведамленні і даныя прыступныя да перахопу."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Налады бяспекі мабільнай сеткі"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Даведацца больш"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Код аб\'екта завершаны."</string>
<string name="fcError" msgid="5325116502080221346">"Праблема падлучэння ці няправільны код функцыі."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ОК"</string>
@@ -832,7 +847,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Устанавіць правілы паролю"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Кіраваць даўжынёй і сімваламі, дазволенымі пры ўводзе пароляў і PIN-кодаў блакіроўкі экрана."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Сачыць за спробамі разблакіроўкі экрана"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Сачыць за колькасцю няправільных набраных пароляў падчас разблакоўкі экрана і блакаваць планшэт або сціраць усе дадзеныя на ім, калі няправільны пароль набраны занадта шмат разоў."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакоўкі экрана і блакіраваць планшэт або сціраць усе даныя на ім, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і заблакіраваць прыладу Android TV або сцерці ўсе даныя на прыладзе, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Падчас разблакіроўкі экрана сачыць за колькасцю няправільна набраных пароляў і, калі няправільны пароль набраны занадта шмат разоў, заблакіраваць інфармацыйна-забаўляльную сістэму ці сцерці ў ёй усе даныя."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і блакіраваць тэлефон або сціраць усе даныя на ім, калі набрана занадта шмат няправільных пароляў."</string>
@@ -1900,8 +1915,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запытваць PIN-код перад адмацаваннем"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запытваць узор разблакіроўкі перад адмацаваннем"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запытваць пароль перад адмацаваннем"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Усталявана адміністратарам.\nКаб паглядзець дадзеныя дазволы, перайдзіце ў налады"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Абноўлены вашым адміністратарам"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Выдалены вашым адміністратарам"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
@@ -2219,6 +2233,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Пераключыцца на працоўную праграму?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша арганізацыя дазваляе рабіць выклікі толькі з працоўных праграм"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша арганізацыя дазваляе адпраўляць паведамленні толькі з працоўных праграм"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Скарыстаць асабісты браўзер"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Скарыстаць працоўны браўзер"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Выклікаць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index eefbdf6..134881d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> след <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не е пренасочено"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не е пренасочено"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Сигурност на мобилната мрежа"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Преглед на настройките"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Осъществен е достъп до идентификатора на устройството"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Мрежа, свързана с(ъс) <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>, записа уникалния идентификатор на устройството ви (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> пъти за периода <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> – <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Шифрована връзка с(ъс) <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Вече имате връзка с по-сигурна мобилна мрежа."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Нешифрована връзка с(ъс) <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Имате връзка с нешифрована мобилна мрежа. Обажданията, съобщенията и данните ви са уязвими от прехващане."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Настройки за сигурност на мобилната мрежа"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Научете повече"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Кодът за функцията се изпълни."</string>
<string name="fcError" msgid="5325116502080221346">"Има проблем с връзката или кодът за функцията е невалиден."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Създаване на екранна снимка"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да създава екранни снимки."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Визуализация на „<xliff:g id="DREAM_NAME">%1$s</xliff:g>“"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"отхвърляне"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"деактивиране или промяна на лентата на състоянието"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"изпълняване на ролята на лента на състоянието"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запитване за ПИН код преди освобождаване"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитване за фигура за отключване преди освобождаване"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитване за парола преди освобождаване"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Инсталирано от администратора ви.\nОтворете настройките, за да прегледате предоставените разрешения"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Актуализирано от администратора ви"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Изтрито от администратора ви"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Искате ли да превключите към служебното приложение?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Организацията ви разрешава да извършвате обаждания само от служебни приложения"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Организацията ви разрешава да изпращате съобщения само от служебни приложения"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Използване на личния браузър"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Използване на служебния браузър"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Обаждане"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Служебни 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Тестване"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Общи"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Деликатното съдържание в известието е скрито"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Съдържанието на приложението е скрито от функцията за споделяне на екрана от съображения за сигурност"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Автоматично установена връзка със сателит"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index d2ccc0d..866f71f 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> সেকেন্ড পরে"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফরওয়ার্ড করা হয়নি"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফরওয়ার্ড করা হয়নি"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"মোবাইল নেটওয়ার্কের সুরক্ষা"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"সেটিংস পর্যালোচনা করুন"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ডিভাইস শনাক্তকারী নম্বর অ্যাক্সেস করা হয়েছে"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> কানেকশনে থাকা একটি নেটওয়ার্ক <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> থেকে <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>-এর মধ্যে <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> বার আপনার ডিভাইসের অনন্য শনাক্তকারী নম্বর (IMSI) রেকর্ড করেছে।"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-এর এনক্রিপ্ট করা কানেকশন"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"এখন আপনি অনেক বেশি সুরক্ষিত মোবাইল নেটওয়ার্কের সাথে কানেক্ট করে আছেন।"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-এর এনক্রিপ্ট না করা কানেকশন"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"আপনি এমন একটি মোবাইল নেটওয়ার্কের সাথে কানেক্ট করে আছেন যা এনক্রিপ্ট করা নয়। আপনার কল, মেসেজ ও ডেটায় হস্তক্ষেপের ঝুঁকি আছে।"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"মোবাইল সুরক্ষা সেটিংস"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"আরও জানুন"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"বৈশিষ্ট্যসূচক কোড সম্পূর্ণ হয়েছে৷"</string>
<string name="fcError" msgid="5325116502080221346">"সংযোগ সমস্যা বা অবৈধ বৈশিষ্ট্যসূচক কোড৷"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ঠিক আছে"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন করার আগে পিন চান"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন করার আগে আনলক প্যাটার্ন চান"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"আপনার অ্যাডমিন ইনস্টল করেছেন।\nঅনুমোদন করা অনুমতি দেখতে সেটিংসে যান"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"আপনার প্রশাসক আপডেট করেছেন"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"আপনার প্রশাসক মুছে দিয়েছেন"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ঠিক আছে"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"অফিসের অ্যাপে পরিবর্তন করবেন?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"আপনার সংস্থা শুধু অফিসের অ্যাপ থেকেই আপনাকে কল করার অনুমতি দেয়"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"আপনার সংস্থা শুধু অফিসের অ্যাপ থেকেই আপনাকে মেসেজ পাঠানোর অনুমতি দেয়"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ব্যক্তিগত ব্রাউজার ব্যবহার করুন"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"অফিস ব্রাউজার ব্যবহার করুন"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"কল করুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 0ee66fc..d641d5a 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> za <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundi"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđen"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Poziv nije proslijeđen"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sigurnost mobilne mreže"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Pregledajte postavke"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Pristupljeno je identifikatoru uređaja"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Mreža na <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> vezi je zabilježila jedinstveni identifikator (IMSI) vašeg uređaja <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> put(a) u periodu između <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> i <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifrirana veza s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Sada ste povezani sa sigurnijom mobilnom mrežom."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifrirana veza s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Povezani ste s nešifriranom mobilnom mrežom. Vaši pozivi, poruke i podaci su izloženi presretanju."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Postavke sigurnosti mobilne mreže"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saznajte više"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kôd za posebne usluge potpun."</string>
<string name="fcError" msgid="5325116502080221346">"Problem sa povezivanjem ili nevažeći kôd za posebne usluge."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Uredu"</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN prije nego se otkači"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje prije poništavanja kačenja"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku prije nego se otkači"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalirao je vaš administrator.\nIdite u postavke da pregledate data odobrenja"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je vaš administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je vaš administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Uredu"</string>
@@ -2179,7 +2193,7 @@
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Obavještenja"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Brze postavke"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Dijaloški okvir za napajanje"</string>
- <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključavanje ekrana"</string>
+ <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključani ekran"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimak ekrana"</string>
<string name="accessibility_system_action_headset_hook_label" msgid="8524691721287425468">"Kuka za slušalice"</string>
<string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Prečica za pristupačnost na ekranu"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Prebaciti na poslovnu aplikaciju?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija vam dozvoljava da upućujete pozive samo iz poslovnih aplikacija"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija vam dozvoljava da šaljete poruke samo iz poslovnih aplikacija"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi lični preglednik"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni preglednik"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Pozovi"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 48ebcad..79afa25 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> després de <xliff:g id="TIME_DELAY">{2}</xliff:g> segons"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no s\'ha desviat"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no s\'ha desviat"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Seguretat de la xarxa mòbil"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Revisa la configuració"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"S\'ha accedit a l\'identificador del dispositiu"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Una xarxa connectada a <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> va gravar l\'identificador únic del teu dispositiu (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> vegades en el període entre els dies <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> i <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Connexió encriptada a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Ara ja tens connexió a una xarxa mòbil més segura."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Connexió no encriptada a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Tens connexió a una xarxa mòbil no encriptada. Els teus missatges, trucades i dades són vulnerables a intercepcions."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Configuració de seguretat de la xarxa mòbil"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Més informació"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Codi de funció completat."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de connexió o codi de funció no vàlid."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"D\'acord"</string>
@@ -831,14 +846,14 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Definir les normes de contrasenya"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Permet controlar la longitud i el nombre de caràcters permesos a les contrasenyes i als PIN del bloqueig de pantalla."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar els intents de desbloqueig de la pantalla"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
- <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han introduït en intentar desbloquejar la pantalla i bloqueja el dispositiu Android TV o esborra totes les dades del dispositiu si s\'introdueixen massa contrasenyes incorrectes."</string>
- <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el sistema d\'informació i entreteniment o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el telèfon o esborra totes les dades del telèfon si s\'introdueixen massa contrasenyes incorrectes."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han escrit en intentar desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades de l\'usuari si s\'escriuen massa contrasenyes incorrectes."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han introduït en intentar desbloquejar la pantalla i bloqueja el dispositiu Android TV o n\'esborra totes les dades de l\'usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el sistema d\'informació i entreteniment o esborra totes les dades d\'aquest perfil si s\'introdueixen massa contrasenyes incorrectes."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han escrit en intentar desbloquejar la pantalla i bloqueja el telèfon o n\'esborra totes les dades de l\'usuari si s\'escriuen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el dispositiu Android TV o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el sistema d\'informació i entreteniment o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el telèfon o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o esborra totes les dades d\'aquest usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el dispositiu Android TV o esborra totes les dades d\'aquest usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el sistema d\'informació i entreteniment o esborra totes les dades d\'aquest perfil si s\'introdueixen massa contrasenyes incorrectes."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el telèfon o esborra totes les dades d\'aquest usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
<string name="policylab_resetPassword" msgid="214556238645096520">"Canviar el bloqueig de pantalla"</string>
<string name="policydesc_resetPassword" msgid="4626419138439341851">"Canvia el bloqueig de pantalla."</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"Bloquejar la pantalla"</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sol·licita el PIN per deixar de fixar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sol·licita el patró de desbloqueig per deixar de fixar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demana la contrasenya per deixar de fixar"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instal·lat per l\'administrador.\nVes a la configuració per veure els permisos concedits."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualitzat per l\'administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Suprimit per l\'administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"D\'acord"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vols canviar a l\'aplicació de treball?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"La teva organització només et permet fer trucades des d\'aplicacions de treball"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"La teva organització només et permet enviar missatges des d\'aplicacions de treball"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilitza el navegador personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilitza el navegador de treball"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Truca"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index fef6fa6..d6565c1 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepřesměrováno"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepřesměrováno"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Zabezpečení mobilní sítě"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Zkontrolovat nastavení"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Byl sdílen identifikátor zařízení"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"V období od <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> do <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> síť na připojení <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> zaznamenala <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>krát jedinečný identifikátor vašeho zařízení (IMSI)."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifrované připojení k síti <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Nyní jste připojeni k zabezpečenější mobilní síti."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifrované připojení k síti <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Jste připojeni k nešifrované mobilní síti. Vaše hovory, zprávy a data by někdo mohl zachytit."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Nastavení zabezpečení mobilní sítě"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Další informace"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Požadavek zadaný pomocí kódu funkce byl úspěšně dokončen."</string>
<string name="fcError" msgid="5325116502080221346">"Problém s připojením nebo neplatný kód funkce."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -358,8 +373,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pořídit snímek obrazovky"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Může pořídit snímek obrazovky."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Náhled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"zavřít"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zakázání či změny stavového řádku"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vydávání se za stavový řádek"</string>
@@ -832,7 +846,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nastavit pravidla pro heslo"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Ovládání délky a znaků povolených v heslech a kódech PIN zámku obrazovky."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovat pokusy o odemknutí obrazovky"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout tablet nebo vymazat z tabletu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitoruje se počet nesprávných hesel zadaných při odemykání obrazovky, a pokud bylo zadáno příliš mnoho nesprávných hesel, tablet se uzamkne nebo se z něj vymažou všechna data."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud jich bude zadáno příliš mnoho, uzamknout zařízení Android TV nebo z něj vymazat všechna data."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout informační a zábavní systém nebo vymazat veškerá data v informačním a zábavním systému, pokud je zadáno příliš mnoho nesprávných hesel."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sleduje počet nesprávných hesel zadaných při odemykání obrazovky a uzamkne telefon nebo vymaže z telefonu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string>
@@ -845,7 +859,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Uzamknout obrazovku"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Určíte, jak a kdy se obrazovka uzamkne."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Mazat všechna data"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez upozornění smazat všechna data tabletu obnovením továrních dat."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez upozornění se smažou všechna data tabletu obnovením továrních dat."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Provést obnovení továrních dat a bez upozornění tím vymazat data v zařízení Android TV."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Bez upozornění se smažou všechna data informačního a zábavního systému obnovením továrních dat."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Bez upozornění se smažou všechna data telefonu obnovením továrních dat."</string>
@@ -1900,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Před uvolněním požádat o PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Před uvolněním požádat o bezpečnostní gesto"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Před odepnutím požádat o heslo"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Nainstalováno administrátorem.\nUdělená oprávnění si můžete prohlédnout v nastavení."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Aktualizováno administrátorem"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Smazáno administrátorem"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2219,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Přepnout na pracovní aplikaci?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaše organizace dovoluje volat jen z pracovních aplikací"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaše organizace dovoluje odesílat zprávy jen z pracovních aplikací"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Použít osobní prohlížeč"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Použít pracovní prohlížeč"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Volat"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 03b17b0..9fb4605 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderestillet"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderestillet"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sikkerhed for mobilnetværk"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Gennemgå indstillinger"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Enheds-id\'et er blevet tilgået"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Et netværk på <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>-forbindelsen registrerede din enheds unikke id (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> gange i tidsrummet <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> og <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Der er oprettet krypteret forbindelse til <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Du har nu forbindelse til et mere sikkert mobilnetværk."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Der er oprettet ikke-krypteret forbindelse til <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Du har forbindelse til et ikke-krypteret mobilnetværk. Dine opkald, beskeder og data er sårbare over for aflytning og læsning af andre."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Sikkerhedsindstillinger for mobilnetværk"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Få flere oplysninger"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Funktionskoden er komplet."</string>
<string name="fcError" msgid="5325116502080221346">"Forbindelsesproblemer eller ugyldig funktionskode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Bed om pinkode inden frigørelse"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Bed om oplåsningsmønster ved deaktivering"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bed om adgangskode inden frigørelse"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installeret af din administrator.\nGå til Indstillinger for at se de tilladelser, der er blevet givet"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Opdateret af din administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet af din administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vil du skifte til en arbejdsapp?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Din organisation tillader kun, at du foretager opkald via arbejdsapps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Din organisation tillader kun, at du sender beskeder via arbejdsapps"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Brug personlig browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Brug arbejdsbrowser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ring op"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index ae1da16..7210fa7 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> nach <xliff:g id="TIME_DELAY">{2}</xliff:g> Sekunden."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nicht weitergeleitet"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nicht weitergeleitet"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sicherheit von Mobilfunknetzen"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Einstellungen prüfen"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Zugriff auf die Gerätekennung"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Ein Netzwerk, das mit <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> verbunden ist, hat die eindeutige Kennung (IMSI) deines Geräts zwischen <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> und <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> Mal aufgezeichnet."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Verschlüsselte Verbindung zu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Du bist jetzt mit einem sichereren Mobilfunknetzwerk verbunden."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nicht verschlüsselte Verbindung zu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Du bist mit einem nicht verschlüsselten Mobilfunknetzwerk verbunden. Deine Anrufe, Nachrichten und Daten sind nicht davor geschützt, abgefangen zu werden."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Sicherheitseinstellungen für Mobilfunknetze"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Weitere Informationen"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Funktionscode abgeschlossen"</string>
<string name="fcError" msgid="5325116502080221346">"Verbindungsproblem oder ungültiger Funktionscode"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Ok"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot erstellen"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Es kann ein Screenshot des Displays erstellt werden."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Vorschau – <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"Schließen"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Statusleiste deaktivieren oder ändern"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Statusleiste darstellen"</string>
@@ -830,7 +844,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Passwortregeln festlegen"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Versuche zum Entsperren des Displays überwachen"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Tablet sperren oder alle Daten auf dem Tablet löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Tablet sperren oder alle Daten auf dem Tablet löschen, wenn zu häufig ein falsches Passwort eingegeben wird"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Es wird überwacht, wie oft beim Versuch, den Bildschirm zu entsperren, ein falsches Passwort eingegeben wird. Wenn es zu viele Fehlversuche gibt, wird das Android TV-Gerät gesperrt oder alle Daten darauf werden gelöscht."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays erfassen und Infotainmentsystem sperren oder alle Daten des Infotainmentsystems löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Bildschirms überwachen und Telefon sperren oder alle Daten auf dem Telefon löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vor dem Beenden nach PIN fragen"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vor dem Beenden nach Entsperrungsmuster fragen"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vor dem Beenden nach Passwort fragen"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Von deinem Administrator installiert.\nRufe die Einstellungen auf, um gewährte Berechtigungen anzusehen."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Von deinem Administrator aktualisiert"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Von deinem Administrator gelöscht"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Zu geschäftlicher App wechseln?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Deine Organisation lässt das Telefonieren nur über geschäftliche Apps zu"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Deine Organisation lässt das Senden von Nachrichten nur über geschäftliche Apps zu"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Privaten Browser verwenden"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Arbeitsbrowser verwenden"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Anrufen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index b9d9c3c..c585376 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> μετά από <xliff:g id="TIME_DELAY">{2}</xliff:g> δευτερόλεπτα"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Δεν προωθήθηκε"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Δεν προωθήθηκε"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Ασφάλεια δικτύου κινητής τηλεφωνίας"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Έλεγχος ρυθμίσεων"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Αναγνωριστικό συσκευής στο οποίο αποκτήθηκε πρόσβαση"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Ένα δίκτυο στη σύνδεση <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> κατέγραψε το μοναδικό αναγνωριστικό της συσκευής σας (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> φορές στην περίοδο μεταξύ <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> και <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Κρυπτογραφημένη σύνδεση στο δίκτυο <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Τώρα είστε συνδεδεμένοι σε ένα πιο ασφαλές δίκτυο κινητής τηλεφωνίας."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Μη κρυπτογραφημένη σύνδεση στο δίκτυο <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Είστε συνδεδεμένοι σε μη κρυπτογραφημένο δίκτυο κινητής τηλεφωνίας. Οι κλήσεις, τα μηνύματα και τα δεδομένα σας είναι ευάλωτα σε υποκλοπή."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Ρυθμίσεις ασφαλείας κινητής τηλεφωνίας"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Μάθετε περισσότερα"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Ο κωδικός λειτουργίας ολοκληρώθηκε."</string>
<string name="fcError" msgid="5325116502080221346">"Πρόβλημα σύνδεσης ή μη έγκυρος κώδικας δυνατότητας."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Λήψη στιγμιότυπου οθόνης"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Μπορεί να τραβήξει στιγμιότυπο της οθόνης."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Προεπισκόπηση, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"παράβλεψη"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ορίζεται ως γραμμή κατάστασης"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Εγκαταστάθηκε από τον διαχειριστή σας.\nΜεταβείτε στις ρυθμίσεις για να δείτε τις άδειες που έχουν εκχωρηθεί"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ενημερώθηκε από τον διαχειριστή σας"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Διαγράφηκε από τον διαχειριστή σας"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Εναλλαγή σε εφαρμογή εργασιών;"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ο οργανισμός σας επιτρέπει την πραγματοποίηση κλήσεων μόνο από εφαρμογές εργασιών"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ο οργανισμός σας επιτρέπει την αποστολή μηνυμάτων μόνο από εφαρμογές εργασιών"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Χρήση προσωπικού προγράμματος περιήγησης"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Χρήση προγράμματος περιήγησης εργασίας"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Κλήση"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index e825eae..aa22491 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobile network security"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Review settings"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Device identifier accessed"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"A network on the <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> connection recorded your device\'s unique identifier (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> times in the period between <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> and <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"You\'re now connected to a more secure mobile network."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Non-encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"You\'re connected to a non-encrypted mobile network. Your calls, messages and data are vulnerable to interception."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobile security settings"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installed by your admin.\nGo to Settings to view granted permissions"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Auto-connected to satellite"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 71b5903..ad376b8 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -153,16 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Cellular network security"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Review settings"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Device identifier accessed"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"A network on the <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> connection recorded your device\'s unique identifier (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> times in the period between <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> and <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"You\'re now connected to a more secure cellular network."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Non-encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"You\'re connected to a non-encrypted cellular network. Your calls, messages, and data are vulnerable to interception."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Cellular security settings"</string>
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobile network security"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encryption, notifications for unencrypted networks"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Device ID accessed"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nThis means that your location, activity, or identity have been logged. This is common practice but may be an issue for people concerned about privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connected to encrypted network <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM connection is more secure now"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connected to unencrypted network"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Calls, messages, and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Calls, messages, and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nWhen your connection is encrypted again, you\'ll get another notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobile network security settings"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Got it"</string>
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dismiss"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -2216,6 +2218,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organization only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organization only allows you to send messages from work apps"</string>
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"You can only make phone calls from your personal Phone app. Calls made with personal Phone will be added to your personal call history."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"You can only send SMS messages from your personal Messages app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index f0c5d7a..e9bd5b3 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobile network security"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Review settings"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Device identifier accessed"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"A network on the <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> connection recorded your device\'s unique identifier (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> times in the period between <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> and <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"You\'re now connected to a more secure mobile network."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Non-encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"You\'re connected to a non-encrypted mobile network. Your calls, messages and data are vulnerable to interception."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobile security settings"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installed by your admin.\nGo to Settings to view granted permissions"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Auto-connected to satellite"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 648693f..ec45a4c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobile network security"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Review settings"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Device identifier accessed"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"A network on the <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> connection recorded your device\'s unique identifier (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> times in the period between <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> and <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"You\'re now connected to a more secure mobile network."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Non-encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"You\'re connected to a non-encrypted mobile network. Your calls, messages and data are vulnerable to interception."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobile security settings"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installed by your admin.\nGo to Settings to view granted permissions"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Auto-connected to satellite"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 25d6c18..4c72d6a 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -153,16 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Cellular network security"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Review settings"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Device identifier accessed"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"A network on the <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> connection recorded your device\'s unique identifier (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> times in the period between <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> and <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"You\'re now connected to a more secure cellular network."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Non-encrypted connection to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"You\'re connected to a non-encrypted cellular network. Your calls, messages, and data are vulnerable to interception."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Cellular security settings"</string>
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"Mobile network security"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"Encryption, notifications for unencrypted networks"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"Device ID accessed"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"At <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> SIM.\n\nThis means that your location, activity, or identity have been logged. This is common practice but may be an issue for people concerned about privacy."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"Connected to encrypted network <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM connection is more secure now"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"Connected to unencrypted network"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"Calls, messages, and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"Calls, messages, and data are currently more vulnerable while using your <xliff:g id="NETWORK_NAME">%1$s</xliff:g> SIM.\n\nWhen your connection is encrypted again, you\'ll get another notification."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"Mobile network security settings"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Learn more"</string>
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"Got it"</string>
<string name="fcComplete" msgid="1080909484660507044">"Feature code complete."</string>
<string name="fcError" msgid="5325116502080221346">"Connection problem or invalid feature code."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dismiss"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -2216,6 +2218,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Your organization only allows you to make calls from work apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organization only allows you to send messages from work apps"</string>
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"You can only make phone calls from your personal Phone app. Calls made with personal Phone will be added to your personal call history."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"You can only send SMS messages from your personal Messages app."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 953bfbd..387381f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> después de <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Seguridad de red móvil"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Revisar la configuración"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Acceso al identificador del dispositivo"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Una red de la conexión <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> registró el identificador inequívoco (IMSI) del dispositivo <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> veces entre la(s) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> y la(s) <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Conexión encriptada a la red <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Ahora tienes conexión a una red móvil más segura"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Conexión no encriptada a la red <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Ahora tienes conexión a una red móvil que no está encriptada. Tus llamadas, mensajes y datos son vulnerables a ser interceptados."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Parámetros de seguridad del celular"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Más información"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Código de función completo."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexión o código de función no válido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Aceptar"</string>
@@ -844,7 +859,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear la pantalla"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Controla cómo y cuándo se bloquea la pantalla."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Borrar todos los datos"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Eliminar los datos de la tablet sin avisar y restablecer la configuración de fábrica"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borra los datos de la tablet sin avisar y restablece la configuración de fábrica."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Restablece la configuración de fábrica para borrar los datos del dispositivo Android TV sin previo aviso."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Permite borrar los datos del sistema de infoentretenimiento sin previo aviso mediante el restablecimiento de la configuración de fábrica."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Borra los datos del dispositivo sin avisar y restablece la configuración de fábrica."</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para quitar fijación"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicitar desbloqueo para quitar fijación"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para quitar fijación"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Tu administrador realizó la instalación.\nVe a la configuración para ver los permisos otorgados"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Tu administrador actualizó este paquete"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Tu administrador borró este paquete"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"¿Quieres cambiar a una app de trabajo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tu organización solo te permite realizar llamadas desde apps de trabajo"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tu organización solo te permite enviar mensajes desde apps de trabajo"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar un navegador personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar un navegador de trabajo"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Llamar"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ba2c5e5..bad3cdd 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> transcurridos <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Seguridad de la red móvil"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Revisar ajustes"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Se ha accedido al identificador del dispositivo"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Una red de la conexión <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ha registrado el identificador único (IMSI) de tu dispositivo <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> veces entre las <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> y las <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Conexión cifrada a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Ahora tu dispositivo está conectado a una red móvil más segura"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Conexión no cifrada a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Te has conectado a una red móvil sin cifrar. Tus llamadas, mensajes y datos son susceptibles y pueden interceptarse."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Ajustes de seguridad de la red móvil"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Más información"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Código de función completo"</string>
<string name="fcError" msgid="5325116502080221346">"Se ha producido un problema de conexión o el código de la función no es válido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Aceptar"</string>
@@ -831,7 +846,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Establecimiento de reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla la longitud y los caracteres permitidos en los PIN y en las contraseñas de bloqueo de pantalla."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar los intentos de desbloqueo de pantalla"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el tablet o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea la tablet o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Comprueba cuántas veces se han introducido contraseñas incorrectas para desbloquear la pantalla y, si te parece que han sido demasiadas, bloquea tu dispositivo Android TV o borra todos sus datos."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el sistema de infoentretenimiento o borra todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el teléfono o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
@@ -844,7 +859,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear la pantalla"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Controla cómo y cuándo se bloquea la pantalla"</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Borrar todos los datos"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borrar los datos del tablet sin avisar restableciendo el estado de fábrica"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borra los datos de la tablet sin avisar restableciendo el estado de fábrica"</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Restablece los datos de fábrica de tu dispositivo Android TV, eliminando sin previo aviso los datos que tuviera."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Borra los datos del sistema de infoentretenimiento sin avisar restableciendo el estado de fábrica."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Borra los datos del teléfono sin avisar restableciendo el estado de fábrica"</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para desactivar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir patrón de desbloqueo para dejar de fijar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para desactivar"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalado por tu administrador.\nVe a Ajustes para ver los permisos concedidos."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado por el administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado por el administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"¿Cambiar a la aplicación de trabajo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tu organización solo te permite hacer llamadas desde aplicaciones de trabajo"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tu organización solo te permite enviar mensajes desde aplicaciones de trabajo"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabajo"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Llamar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b100016..7364183 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundi pärast"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: pole suunatud"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: pole edastatud"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobiilsidevõrgu turvalisus"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Vaadake seaded üle"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Seadme identifikaatorile pääseti juurde"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Ühenduse <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> võrk salvestas teie seadme kordumatu identifikaatori (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> korda ajavahemikus <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> kuni <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Krüpteeritud ühendus võrguga <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Olete nüüd ühendatud turvalisema mobiilsidevõrguga."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Krüpteerimata ühendus võrguga <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Olete ühendatud krüpteerimata mobiilsidevõrguga. Võõrad võivad teie kõnedele, sõnumitele ja andmetele juurde pääseda."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobiilside turvaseaded"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Lisateave"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Funktsioonikood valmis."</string>
<string name="fcError" msgid="5325116502080221346">"Ühendusprobleem või kehtetu funktsioonikood."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -843,7 +858,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Ekraani lukustamine"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Määrake, kuidas ja millal ekraan lukustub."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Kõikide andmete kustutamine"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Kustutage tahvelarvuti andmed hoiatamata, lähtestades arvuti tehaseandmetele."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Kustutab tahvelarvuti andmed hoiatamata, lähtestades arvuti tehaseandmetele."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Kustutatakse teie Android TV seadme andmed ilma hoiatamata, lähtestades seadme tehase andmetele."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Teabe ja meelelahutuse süsteemi andmete hoiatamata kustutamine tehase andmetele lähtestamise abil."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Kustutab telefoniandmed hoiatuseta, lähtestades telefoni tehaseseadetele."</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Enne vabastamist küsi PIN-koodi"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Enne vabastamist küsi avamismustrit"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Enne vabastamist küsi parooli"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installis teie administraator.\nAntud õiguste vaatamiseks avage seaded"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administraator on seda värskendanud"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administraator on selle kustutanud"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Kas lülituda töörakendusele?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Teie organisatsioon lubab helistada ainult töörakendustest."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Teie organisatsioon lubab sõnumeid saata ainult töörakendustest."</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Kasuta isiklikku brauserit"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Kasuta tööbrauserit"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Helista"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Töö 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Jagatud"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Märguande delikaatne sisu peideti"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Rakenduse sisu on ekraani jagamises turvalisuse huvides peidetud"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Satelliidiga loodi automaatselt ühendus"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 4613ac6..b4c054b 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> zenbakira <xliff:g id="TIME_DELAY">{2}</xliff:g> segundotan"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ez da desbideratu"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ez da desbideratu"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sare mugikorraren segurtasuna"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Berrikusi ezarpenak"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Gailuaren identifikatzailea atzitu da"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> konexioko sare batek gailuaren identifikatzaile esklusiboa (IMSIa) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> aldiz erregistratu du <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> eta <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> artean."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> sarearekiko konexio enkriptatua"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Sare mugikor seguruago batera zaude konektatuta orain."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> sarearekiko konexio enkriptatu gabea"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Enkriptatu gabeko sare mugikor batera konektatuta zaude. Deiak, mezuak eta datuak atzemateko arriskua dago."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Sare mugikorraren segurtasunaren ezarpenak"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Lortu informazio gehiago"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Eginbide-kodea osatu da."</string>
<string name="fcError" msgid="5325116502080221346">"Konexio-arazo bat gertatu da edo eginbide-kodea baliogabea da."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Ados"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Eskatu PINa aingura kendu aurretik"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Eskatu pasahitza aingura kendu aurretik"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Administratzaileak instalatu du.\nEmandako baimenak ikusteko, joan ezarpenetara."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administratzaileak eguneratu du"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratzaileak ezabatu du"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Ados"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Laneko aplikaziora aldatu nahi duzu?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Laneko aplikazioetatik soilik deitzeko baimena ematen du zure erakundeak"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Mezuak laneko aplikazioetatik soilik bidaltzeko baimena ematen du zure erakundeak"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Erabili arakatzaile pertsonala"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Erabili laneko arakatzailea"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Deitu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 439eb9b..db06309 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> پس از <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانیه"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: هدایت نشده"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: هدایت نشده"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"امنیت شبکه تلفن همراه"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"مرور تنظیمات"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"شناسه دستگاه دردسترس قرار گرفت"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"شبکهای در اتصال <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> شناسه یکتای (IMSI) دستگاه شما را <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> بار در بازه زمانی <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> و <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> ضبط کرده است."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"اتصال رمزگذاریشده به <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"اکنون به شبکه تلفن همراه ایمنتری متصلشدهاید."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"اتصال رمزگذارینشده به <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"اکنون به یک شبکه تلفن همراه رمزگذارینشده متصل شدهاید. تماسها، پیامها، و دادههایتان دربرابر شنود آسیبپذیر هستند."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"تنظیمات امنیتی شبکه همراه"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"بیشتر بدانید"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"کد ویژگی کامل شد."</string>
<string name="fcError" msgid="5325116502080221346">"مشکل در اتصال یا کد ویژگی نامعتبر."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"تأیید"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"گرفتن نماگرفت"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"میتواند از نمایشگر نماگرفت بگیرد."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"پیشنما، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"بستن"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"به برنامه اجازه میدهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"نوار وضعیت باشد"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"درخواست کد پین قبل از برداشتن پین"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"درخواست الگوی بازگشایی قفل قبلاز برداشتن سنجاق"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"درخواست گذرواژه قبل از برداشتن سنجاق"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"سرپرست شما آن را نصب کرده است.\nبرای مشاهده اجازههای اعطاشده به تنظیمات بروید"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"توسط سرپرست سیستم بهروزرسانی شد"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"توسط سرپرست سیستم حذف شد"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"تأیید"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"به برنامه کاری جابهجا شوید؟"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"سازمانتان به شما اجازه میدهد فقط ازطریق برنامههای کاری تماس بگیرید"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"سازمانتان به شما اجازه میدهد فقط ازطریق برنامههای کاری پیام ارسال کنید"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"استفاده از مرورگر شخصی"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"استفاده از مرورگر کاری"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"تماس گرفتن"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index aa87f24..1a6e7c4 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunnin päästä"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ei siirretty"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ei siirretty"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobiiliverkon tietoturva"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Tarkista asetukset"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Laitteen tunnistinta käytettiin"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Yhteys verkossa (<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>) tallensi laitteesi yksilöllisen tunnisteen (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> kertaa <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> – <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> välillä."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Salattu yhteys verkkoon: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Olet yhteydessä turvallisempaan mobiiliverkkoon."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Ei-salattu yhteys verkkoon: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Olet yhteydessä ei-salattuun mobiiliverkkoon. Puhelusi, viestisi ja datasi ovat alttiita sieppaukselle."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobiiliverkon suojausasetukset"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Lue lisää"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Ominaisuuskoodi valmis."</string>
<string name="fcError" msgid="5325116502080221346">"Yhteysongelma tai virheellinen ominaisuuskoodi."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pyydä PIN ennen irrotusta"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pyydä salasana ennen irrotusta"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Järjestelmänvalvojan asentama.\nTarkista myönnetyt luvat asetuksista."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Järjestelmänvalvoja päivitti tämän."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Järjestelmänvalvoja poisti tämän."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vaihdetaanko työsovellukseen?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisaatio sallii soittamisen vain työsovelluksilla"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisaatio sallii viestien lähettämisen vain työsovelluksilla"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Käytä henkilökohtaista selainta"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Käytä työselainta"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Soita"</string>
diff --git a/core/res/res/values-fr-feminine/strings.xml b/core/res/res/values-fr-feminine/strings.xml
index c9c3675..2ad85d1 100644
--- a/core/res/res/values-fr-feminine/strings.xml
+++ b/core/res/res/values-fr-feminine/strings.xml
@@ -20,7 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connectée à un réseau mobile plus sécurisé."</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connectée à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonnée"</string>
</resources>
diff --git a/core/res/res/values-fr-masculine/strings.xml b/core/res/res/values-fr-masculine/strings.xml
index 288c2ca..744ef2b 100644
--- a/core/res/res/values-fr-masculine/strings.xml
+++ b/core/res/res/values-fr-masculine/strings.xml
@@ -20,7 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connecté à un réseau mobile plus sécurisé."</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string>
</resources>
diff --git a/core/res/res/values-fr-neuter/strings.xml b/core/res/res/values-fr-neuter/strings.xml
index 15e3076..b4f4cc7 100644
--- a/core/res/res/values-fr-neuter/strings.xml
+++ b/core/res/res/values-fr-neuter/strings.xml
@@ -20,7 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connecté·e à un réseau mobile plus sécurisé."</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté·e à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné·e"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 1ce5ba0..749fcf6 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sécurité du réseau cellulaire"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Vérifiez les paramètres"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Accès à l\'identifiant de l\'appareil"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Un réseau doté de la connexion <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> a enregistré l\'identifiant unique (IMSI) de votre appareil <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> fois entre les périodes suivantes : <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> et <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Connexion chiffrée à <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes maintenant connecté à un réseau cellulaire plus sécuritaire."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Connexion non chiffrée à <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté à un réseau cellulaire non chiffré. Vos appels, vos données et vos messages risquent d\'être interceptés."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Paramètres de sécurité du réseau cellulaire"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"En savoir plus"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Code de service terminé"</string>
<string name="fcError" msgid="5325116502080221346">"Problème de connexion ou code de service non valide"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -357,8 +372,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre une capture de l\'écran."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"Ignorer"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"désactiver ou modifier la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"servir de barre d\'état"</string>
@@ -1899,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le NIP avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installé par votre administrateur.\nAccédez aux paramètres pour consulter les autorisations accordées"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Mise à jour par votre administrateur"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2218,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Passer à l\'application professionnelle?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Votre organisation vous autorise à passer des appels uniquement à partir d\'applications professionnelles"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Votre organisation vous autorise à envoyer des messages uniquement à partir d\'applications professionnelles"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utiliser le navigateur du profil personnel"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utiliser le navigateur du profil professionnel"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Appeler"</string>
@@ -2397,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Professionnel 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Commun"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Le contenu confidentiel des notifications est masqué"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Le contenu de l\'application est masqué du Partage d\'écran par mesure de sécurité"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Connecté au satellite automatiquement"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f94ebac..4e5154e 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sécurité des réseaux mobiles"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Vérifier les paramètres"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Identifiant de l\'appareil accessible"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Un réseau sur la connexion <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> a enregistré l\'identifiant unique de votre appareil (IMSI)<xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> fois entre<xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> et<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Connexion chiffrée au réseau <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connecté à un réseau mobile plus sécurisé."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Connexion non chiffrée au réseau <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Paramètres de sécurité des réseaux mobiles"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"En savoir plus"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Code de service terminé"</string>
<string name="fcError" msgid="5325116502080221346">"Problème de connexion ou code de service non valide"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le code avant de retirer l\'épingle"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant de retirer l\'épingle"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant de retirer l\'épingle"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installé par votre administrateur.\nAllez dans les paramètres pour consulter les autorisations accordées."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Mis à jour par votre administrateur"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Passer à une appli professionnelle ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Votre organisation ne vous autorise à passer des appels que depuis des applis professionnelles"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Votre organisation ne vous autorise à envoyer des messages que depuis des applis professionnelles"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utiliser le navigateur personnel"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utiliser le navigateur professionnel"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Appeler"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e3f2f3a..2187fed 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> tras <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: non desviada"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: non reenviada"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Seguranza da rede de telefonía móbil"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Revisa a configuración"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Acceso ao identificador do dispositivo"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Unha rede da conexión <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> rexistrou o identificador único do teu dispositivo (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> veces entre a/s <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> e a/s <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Conexión encriptada a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Agora o teu dispositivo está conectado a unha rede de telefonía móbil máis segura."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Conexión non encriptada a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"O teu dispositivo está conectado a unha rede de telefonía móbil non encriptada. As túas chamadas, mensaxes e datos son vulnerables e poden interceptarse."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Configuración da seguranza da rede de telefonía móbil"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Máis información"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Código de función completo"</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexión ou código de función non válido"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Aceptar"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar a fixación"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrón de desbloqueo antes de soltar a fixación"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir contrasinal antes de soltar a fixación"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalado pola persoa administradora.\nVai á configuración para ver os permisos concedidos"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado polo teu administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado polo teu administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Queres cambiar á aplicación do traballo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"A túa organización só che permite chamar desde aplicacións do traballo"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"A túa organización só che permite enviar mensaxes desde aplicacións do traballo"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilizar navegador persoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilizar navegador de traballo"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Chamar"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index e08a62b..b36b17c 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="TIME_DELAY">{2}</xliff:g> સેકન્ડ પછી <xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ફોરવર્ડ કર્યો નથી"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ફોરવર્ડ કર્યો નથી"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"સેલ્યુલર નેટવર્ક સંબંધી સુરક્ષા"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"સેટિંગ રિવ્યૂ કરો"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ઍક્સેસ કરવામાં આવેલા ડિવાઇસના ઓળખકર્તા"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> કનેક્શન પરના નેટવર્કે <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> અને <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> વચ્ચેના સમયગાળામાં તમારા ડિવાઇસના વિશિષ્ટ રીતે ઓળખી શકાય એવા (IMSI) નંબરને <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> વખત રેકોર્ડ કર્યો છે."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> માટે એન્ક્રિપ્ટેડ કનેક્શન"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"તમે હવે વધુ સુરક્ષિત સેલ્યુલર નેટવર્કથી કનેક્ટેડ છો."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> માટે એન્ક્રિપ્ટેડ ના હોય તેવું કનેક્શન"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"તમે એન્ક્રિપ્ટેડ ના હોય તેવા સેલ્યુલર નેટવર્ક સાથે કનેક્ટેડ છો. તમારા કૉલ, મેસેજ અને ડેટા ઇન્ટરસેપ્શન માટે સંવેદનશીલ છે."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"સેલ્યુલરની સુરક્ષા સંબંધી સેટિંગ"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"વધુ જાણો"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"સુવિધા કોડ પૂર્ણ."</string>
<string name="fcError" msgid="5325116502080221346">"કનેક્શન સમસ્યા અથવા અમાન્ય સુવિધા કોડ."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ઓકે"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"અનપિન કરતા પહેલાં પિન માટે પૂછો"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"અનપિન કરતા પહેલાં અનલૉક પૅટર્ન માટે પૂછો"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"તમારા ઍડમિન દ્વારા ઇન્સ્ટૉલ કરવામાં આવ્યું છે.\nઆપેલી પરવાનગીઓ જોવા માટે સેટિંગ પર જાઓ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ કરવામાં આવેલ છે"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"તમારા વ્યવસ્થાપક દ્વારા કાઢી નાખવામાં આવેલ છે"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ઓકે"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"શું ઑફિસ માટેની ઍપ પર સ્વિચ કરીએ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"તમારી સંસ્થા તમને માત્ર ઑફિસ માટેની ઍપ પરથી કૉલ કરવાની મંજૂરી આપે છે"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"તમારી સંસ્થા તમને માત્ર ઑફિસ માટેની ઍપ પરથી મેસેજ મોકલવાની મંજૂરી આપે છે"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"વ્યક્તિગત બ્રાઉઝરનો ઉપયોગ કરો"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ઑફિસના બ્રાઉઝરના ઉપયોગ કરો"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"કૉલ કરો"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ઑફિસ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"પરીક્ષણ કરો"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"કૉમ્યુનલ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"સંવેદનશીલ માહિતીવાળા નોટિફિકેશનનું કન્ટેન્ટ છુપાવ્યું"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"સુરક્ષા માટે સ્ક્રીન શેર કરતી વખતે ઍપનું કન્ટેન્ટ છુપાવેલું છે"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"સેટેલાઇટ સાથે ઑટોમૅટિક રીતે કનેક્ટેડ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f393074..40470cd 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंड के बाद"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित नहीं किया गया"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित नहीं किया गया"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"मोबाइल नेटवर्क की सुरक्षा"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"सेटिंग देखें"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"डिवाइस आइडेंटिफ़ायर की जानकारी ऐक्सेस की गई"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> कनेक्शन से जुड़े किसी नेटवर्क ने, <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> से <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> के बीच आपके डिवाइस के यूनीक आइडेंटिफ़ायर (IMSI) की जानकारी <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> बार रिकॉर्ड की."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> के साथ एन्क्रिप्ट यानी सुरक्षित किया गया कनेक्शन"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"अब आपका डिवाइस ज़्यादा सुरक्षित मोबाइल नेटवर्क से कनेक्ट है."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> के साथ एन्क्रिप्ट नहीं किया गया कनेक्शन"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"आपका डिवाइस ऐसे मोबाइल नेटवर्क से कनेक्ट है जिसे एन्क्रिप्ट नहीं किया गया है. आपके कॉल, मैसेज, और डेटा को ऐक्सेस किया जा सकता है."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"मोबाइल नेटवर्क की सुरक्षा सेटिंग"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ज़्यादा जानें"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"सुविधा कोड पूरा हुआ."</string>
<string name="fcError" msgid="5325116502080221346">"कनेक्शन समस्या या अमान्य सुविधा कोड."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ठीक है"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट लें"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिसप्ले का स्क्रीनशॉट लिया जा सकता है."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> की झलक"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"खारिज करें"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार को अक्षम करें या बदलें"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ऐप को, स्टेटस बार को बंद करने या सिस्टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार को रहने दें"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करने से पहले पिन के लिए पूछें"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करने से पहले लॉक खोलने के पैटर्न के लिए पूछें"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"इसे आपके एडमिन ने इंस्टॉल किया है.\nजिन अनुमतियों को मंज़ूरी मिली है उन्हें देखने के लिए, सेटिंग में जाएं"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"आपके व्यवस्थापक ने अपडेट किया है"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"आपके व्यवस्थापक ने हटा दिया है"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ठीक है"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"क्या आपको वर्क ऐप्लिकेशन पर स्विच करना है?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"आपके संगठन ने, सिर्फ़ वर्क ऐप्लिकेशन से कॉल करने की अनुमति दी है"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"आपके संगठन ने, सिर्फ़ वर्क ऐप्लिकेशन से मैसेज भेजने की अनुमति दी है"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"निजी ब्राउज़र का इस्तेमाल करें"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ऑफ़िस के काम से जुड़े ब्राउज़र का इस्तेमाल करें"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"कॉल करें"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ऑफ़िस 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"टेस्ट"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"कम्यूनिटी"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"संवेदनशील जानकारी वाली सूचना का कॉन्टेंट छिपा है"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रीन शेयर करने के दौरान सुरक्षा के लिए, ऐप्लिकेशन का कॉन्टेंट छिपाया गया"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"सैटलाइट से अपने-आप कनेक्ट हो गया"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 33cde13..64f1368 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđeno"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nije proslijeđeno"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sigurnost mobilne mreže"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Pregledaj postavke"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Pristupljeno je identifikatoru uređaja"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Mreža na vezi <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> zabilježila je jedinstveni identifikacijski broj vašeg uređaja (IMSI) sljedeći broj puta: <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> u razdoblju između <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> i <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifrirana je veza s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Sad ste povezani sa sigurnijom mobilnom mrežom."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifrirana veza s mobilnom mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Sad ste povezani s nešifriranom mobilnom mrežom. Vaši su pozivi, poruke i podaci ranjivi na presretanje."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Postavke sigurnosti mobilne mreže"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saznajte više"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kôd značajke je potpun."</string>
<string name="fcError" msgid="5325116502080221346">"Problem s vezom ili nevažeći kôd značajke."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"U redu"</string>
@@ -831,7 +846,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Nadzor pokušaja otključavanja zaslona"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadziri broj netočnih zaporki unesenih pri otključavanju zaslona i zaključaj tabletno računalo ili izbriši sve podatke na njemu ako je uneseno previše netočnih zaporki."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadzire se broj netočnih zaporki unesenih pri otključavanju zaslona, a tablet se zaključava ili se s njega brišu svi podaci ako je uneseno previše netočnih zaporki."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava Android TV uređaj ili s njega briše sve podatke ako se unese previše netočnih zaporki."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava sustav za informiranje i zabavu ili briše sve njegove podatke ako se unese previše netočnih zaporki."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Nadzire broj netočno unesenih zaporki pri otključavanju zaslona i zaključava telefon ili briše sve podatke na telefonu ako je uneseno previše netočnih zaporki."</string>
@@ -844,7 +859,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Zaključavanje zaslona"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Upravlja se načinom i vremenom zaključavanja zaslona."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Brisanje svih podataka"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vraćanjem u tvorničko stanje izbriši podatke tabletnog računala bez upozorenja."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vraćanjem na tvorničke postavke brišu se podaci tableta bez upozorenja."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Podatke Android TV uređaja izbrišite bez upozorenja vraćanjem uređaja na tvorničke postavke."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Briše podatke sustava za informiranje i zabavu bez upozorenja vraćanjem na tvorničko stanje."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Vraćanjem na tvorničke postavke brišu se podaci s telefona bez upozorenja."</string>
@@ -1537,7 +1552,7 @@
<string name="vpn_lockdown_config" msgid="8331697329868252169">"Promijenite mrežu ili postavke VPN-a"</string>
<string name="upload_file" msgid="8651942222301634271">"Odaberite datoteku"</string>
<string name="no_file_chosen" msgid="4146295695162318057">"Nema odabranih datoteka"</string>
- <string name="reset" msgid="3865826612628171429">"Ponovo postavi"</string>
+ <string name="reset" msgid="3865826612628171429">"Poništi"</string>
<string name="submit" msgid="862795280643405865">"Pošalji"</string>
<string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Pokrenuta je aplikacija za vožnju"</string>
<string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Dodirnite za zatvaranje aplikacije za vožnju."</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN radi otkvačivanja"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje radi otkvačivanja"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži zaporku radi otkvačivanja"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalirao vaš administrator.\nOtvorite postavke da biste pregledali dodijeljena dopuštenja"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"U redu"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite li prebaciti na poslovnu aplikaciju?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija dopušta upućivanje poziva samo iz poslovnih aplikacija"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija dopušta slanje poruka samo iz poslovnih aplikacija"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi osobni preglednik"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni preglednik"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Nazovi"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index acf2266..b4ac675 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> másodperc után"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nincs átirányítva"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nincs átirányítva"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobilhálózat biztonsága"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Beállítások áttekintése"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Hozzáférés az eszközazonosítóhoz"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"A(z) <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> kapcsolat egyik hálózata <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> alkalommal rögzítette az Ön eszközének egyedi azonosítóját (IMSI) a következő időszakban: <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> – <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Titkosított kapcsolat ezzel: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Mostantól biztonságosabb mobilhálózathoz csatlakozik."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nem titkosított kapcsolat ezzel: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Nem titkosított mobilhálózathoz van csatlakozva. Könnyebben elfoghatják a hívásait, üzeneteit és adatait."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobilhálózat-biztonsági beállítások"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"További információ"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"A funkciókód kész."</string>
<string name="fcError" msgid="5325116502080221346">"Kapcsolódási probléma vagy érvénytelen funkciókód."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-kód kérése a kitűzés feloldásához"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Feloldási minta kérése a kitűzés feloldásához"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Jelszó kérése a rögzítés feloldásához"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"A rendszergazda által telepítve.\nLépjen a beállításokhoz a megadott engedélyek megtekintéséhez."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"A rendszergazda által frissítve"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"A rendszergazda által törölve"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Átvált a munkahelyi alkalmazásra?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Szervezete csak munkahelyi alkalmazásokból engedélyezi a hívásindítást"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Szervezete csak munkahelyi alkalmazásokból engedélyezi az üzenetküldést"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Személyes böngésző használata"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Munkahelyi böngésző használata"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Hívás"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 8ca4708..609810a 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> վայրկյանից"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Չի վերահասցեավորվել"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Չի վերահասցեավորվել"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Բջջային ցանցի անվտանգություն"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Ստուգել կարգավորումները"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Սարքի նույնացուցիչը հասանելի է դարձել"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ցանցային կապը <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> - <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> ժամանակահատվածում <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> անգամ գրանցել է ձեր սարքի եզակի նույնացուցիչը (IMSI)։"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> գաղտնագրված կապ"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Դուք միացել եք ավելի հուսալի բջջային ցանցի։"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Չգաղտնագրված միացում <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ցանցին"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Դուք միացել եք չգաղտնագրված բջջային ցանցի։ Ձեր զանգերը, հաղորդագրությունները և բջջային ինտերնետը խոցելի են։"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Բջջային կապի անվտանգության կարգավորումներ"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Իմանալ ավելին"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Հատկության կոդը ամբողջական է:"</string>
<string name="fcError" msgid="5325116502080221346">"Կապի խնդիր կամ անվավեր գործառույթի կոդ:"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Եղավ"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Հարցնել PIN կոդը"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Հարցնել ապակողպող նախշը"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Հարցնել գաղտնաբառը"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Տեղադրվել է ադմինիստրատորի կողմից։\nԱնցեք կարգավորումներ՝ տրամադրված թույլտվությունները դիտելու համար"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Թարմացվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Ջնջվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Եղավ"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Անցնե՞լ աշխատանքային հավելվածի"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ձեր կազմակերպությունը թույլատրում է ձեզ զանգեր կատարել միայն աշխատանքային հավելվածներից"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ձեր կազմակերպությունը թույլատրում է ձեզ հաղորդագրություններ ուղարկել միայն աշխատանքային հավելվածներից"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Օգտագործել անձնական դիտարկիչը"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Օգտագործել աշխատանքային դիտարկիչը"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Զանգել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5d2ffd4..1956c92 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> setelah <xliff:g id="TIME_DELAY">{2}</xliff:g> detik"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak diteruskan"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak diteruskan"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Keamanan jaringan seluler"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Tinjau setelan"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ID perangkat diakses"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Jaringan di koneksi <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> yang direkam identitas yang dapat dikenali (IMSI) perangkat Anda sebanyak <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> kali selama periode antara <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> dan <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Koneksi yang dienkripsi ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Anda kini terhubung ke jaringan seluler yang lebih aman."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Koneksi yang tidak dienkripsi ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Anda terhubung ke jaringan seluler yang tidak dienkripsi. Panggilan, pesan, dan data Anda rentan terhadap penyadapan."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Setelan keamanan seluler"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Pelajari lebih lanjut"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kode fitur selesai."</string>
<string name="fcError" msgid="5325116502080221346">"Masalah sambungan atau kode fitur tidak valid."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Oke"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Meminta PIN sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Meminta sandi sebelum melepas sematan"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Diinstal oleh admin Anda.\nBuka setelan untuk melihat izin yang diberikan"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Diupdate oleh admin Anda"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dihapus oleh admin Anda"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Oke"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Beralih ke aplikasi kerja?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasi Anda hanya mengizinkan menelepon dari aplikasi kerja"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasi Anda hanya mengizinkan pengiriman pesan dari aplikasi kerja"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gunakan browser pribadi"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gunakan browser kerja"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Telepon"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Pengujian"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Konten notifikasi sensitif disembunyikan"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Konten aplikasi disembunyikan dari berbagi layar untuk alasan keamanan"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Menghubungkan otomatis ke satelit"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b304edc..2a02c0c 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> eftir <xliff:g id="TIME_DELAY">{2}</xliff:g> sekúndur"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ekki áframsent"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ekki áframsent"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Öryggi farsímakerfis"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Yfirfara stillingar"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Auðkenni tækis opnað"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Netkerfi á <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>-tengingunni skráði einkvæmt auðkenni (IMSI-númer) tækisins <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> sinnum frá <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> til <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Dulkóðuð tenging við <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Nú ertu með tengingu við öruggara farsímakerfi."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Ódulkóðuð tenging við <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Þú ert með tengingu við farsímakerfi sem er ekki dulkóðað. Símtöl, skilaboð og gögn eru berskjölduð fyrir hlerun."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Öryggisstillingar farsímakerfis"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Nánar"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kóðaskipun framkvæmd."</string>
<string name="fcError" msgid="5325116502080221346">"Vandamál með tengingu eða ógild kóðaskipun."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Í lagi"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Biðja um PIN-númer til að losa"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Biðja um opnunarmynstur til að losa"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Biðja um aðgangsorð til að losa"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Sett upp af stjórnanda.\nFarðu í stillingar til að sjá heimildir"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Kerfisstjóri uppfærði"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Skipta yfir í vinnuforrit?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Fyrirtækið heimilar þér aðeins að hringja úr vinnuforritum"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Fyrirtækið heimilar þér aðeins að senda skilaboð úr vinnuforritum"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Nota einkavafra"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Nota vinnuvafra"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Hringja"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 00b79b6..b943073 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> dopo <xliff:g id="TIME_DELAY">{2}</xliff:g> secondi"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sicurezza rete mobile"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Controlla le impostazioni"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Accesso all\'identificatore del dispositivo"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Una rete sulla connessione <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ha registrato l\'identificatore univoco (IMSI) del tuo dispositivo per <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> volte nel periodo compreso tra: <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> e: <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Connessione criptata a: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Hai ora eseguito la connessione a una rete mobile più protetta."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Connessione non criptata a: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Hai eseguito la connessione a una rete mobile non criptata. Chiamate, messaggi e dati sono vulnerabili alle intercettazioni."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Impostazioni sicurezza rete mobile"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Scopri di più"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Codice funzione completo."</string>
<string name="fcError" msgid="5325116502080221346">"Problema di connessione o codice funzione non valido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -844,7 +859,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Bloccare lo schermo"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Controlla come e quando si blocca lo schermo."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Cancellare tutti i dati"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Cancella i dati del tablet senza preavviso eseguendo un ripristino dati di fabbrica."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Cancella i dati del tablet senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Consente di cancellare i dati del dispositivo Android TV senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Cancella i dati del sistema di infotainment senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Cancella i dati del telefono senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Richiedi il PIN per lo sblocco"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Richiedi sequenza di sblocco prima di sbloccare"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Richiedi password prima di sbloccare"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installato dall\'amministratore.\nVai alle impostazioni per visualizzare le autorizzazioni"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Aggiornato dall\'amministratore"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminato dall\'amministratore"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vuoi passare all\'app di lavoro?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"La tua organizzazione consente di fare chiamate solo dalle app di lavoro"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"La tua organizzazione consente di inviare messaggi solo dalle app di lavoro"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usa il browser personale"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usa il browser di lavoro"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Chiama"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 861e294..62ed6fc 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> אחרי <xliff:g id="TIME_DELAY">{2}</xliff:g> שניות"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"אבטחת הרשת הסלולרית"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"בדיקת ההגדרות"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"בוצעה גישה למזהה המכשיר"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"רשת בחיבור <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> רשמה את המזהה הייחודי של המכשיר שלך (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> פעמים בתקופה שבין <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ל-<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"חיבור מוצפן אל <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"התחברת עכשיו לרשת סלולרית מאובטחת יותר."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"חיבור לא מוצפן אל <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"התחברת עכשיו לרשת סלולרית לא מוצפנת. השיחות, ההודעות והנתונים שלך חשופים ליירוט."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"הגדרות אבטחה סלולרית"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"מידע נוסף"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"קוד תכונה הושלם."</string>
<string name="fcError" msgid="5325116502080221346">"בעיה בחיבור או קוד תכונה לא תקין."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"אישור"</string>
@@ -357,8 +372,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"צילום המסך"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ניתן לצלם צילום מסך של התצוגה."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"תצוגה מקדימה, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"סגירה"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"השבתה או שינוי של שורת הסטטוס"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשרת לאפליקציה להשבית את שורת הסטטוס או להוסיף ולהסיר סמלי מערכת."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string>
@@ -1656,9 +1670,9 @@
<string name="default_audio_route_category_name" msgid="5241740395748134483">"מערכת"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="4214648773120426288">"אודיו Bluetooth"</string>
<string name="wireless_display_route_description" msgid="8297563323032966831">"צג אלחוטי"</string>
- <string name="media_route_button_content_description" msgid="2299223698196869956">"העברה (cast)"</string>
+ <string name="media_route_button_content_description" msgid="2299223698196869956">"הפעלת Cast"</string>
<string name="media_route_chooser_title" msgid="6646594924991269208">"התחברות למכשיר"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"העברת מסך אל מכשיר"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"הפעלת Cast של התוכן במסך אל מכשיר"</string>
<string name="media_route_chooser_searching" msgid="6119673534251329535">"המערכת מחפשת מכשירים…"</string>
<string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"הגדרות"</string>
<string name="media_route_controller_disconnect" msgid="7362617572732576959">"ניתוק"</string>
@@ -1899,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"יש לבקש קוד אימות לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"צריך לבקש קו ביטול נעילה לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"יש לבקש סיסמה לפני ביטול הצמדה"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"החבילה הותקנה על ידי האדמין.\nצריך לעבור להגדרות כדי לראות את ההרשאות שניתנו"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"עודכנה על ידי מנהל המערכת"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"נמחקה על ידי מנהל המערכת"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"אישור"</string>
@@ -2218,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"לעבור לאפליקציה לעבודה?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"בארגון שלך מאפשרים לבצע שיחות רק מאפליקציות לעבודה"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"בארגון שלך מאפשרים לשלוח הודעות רק מאפליקציות לעבודה"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"בדפדפן האישי"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"בדפדפן של העבודה"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"שיחה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a9365d5..61eb776 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g> (<xliff:g id="TIME_DELAY">{2}</xliff:g>秒後)"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"モバイル ネットワークのセキュリティ"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"設定を確認する"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"デバイス ID にアクセスしました"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> 接続のネットワークは、<xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>~<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>の間にデバイスの一意の ID(IMSI)を <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> 回記録しました。"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> への接続が暗号化されています"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"より安全なモバイル ネットワークに接続しました。"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> への接続が暗号化されていません"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"接続先のモバイル ネットワークは暗号化されていません。通話、メッセージ、データが傍受に対し脆弱です。"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"モバイル セキュリティの設定"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"詳細"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"機能コードが完了しました。"</string>
<string name="fcError" msgid="5325116502080221346">"接続エラーまたは無効な機能コードです。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"スクリーンショットの撮影"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ディスプレイのスクリーンショットを撮影できます。"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"プレビュー - <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"閉じる"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ステータスバーの無効化や変更"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ステータスバーへの表示"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"オフライン再生を解除する前にPINの入力を求める"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"オフライン再生を解除する前にパスワードの入力を求める"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"管理者によりインストールされています。\n付与された権限を確認するには、設定に移動してください"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"管理者により更新されています"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"管理者により削除されています"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"仕事用アプリに切り替えますか?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"組織では、仕事用アプリからの通話のみ許可されています"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"組織では、仕事用アプリからのメッセージ送信のみ許可されています"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"個人用ブラウザを使用"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"仕事用ブラウザを使用"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"通話"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"仕事用 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"テスト"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"プライベートな通知内容は表示されません"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"セキュリティ上、画面共有ではアプリの内容は非表示となります"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"衛星に自動接続しました"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 9cfc999..2beae01 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> წამის შემდეგ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: არ არის გადამისამართებული"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: არ არის გადამისამართებული"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"ფიჭური ქსელის უსაფრთხოება"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"პარამეტრების მიმოხილვა"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"მოწყობილობის იდენტიფიკატორზე წვდომა მიღებულია"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>-ზე კავშირის ქსელმა ჩაიწერა მოწყობილობის უნიკალური იდენტიფიკატორი (IMSI) მოცემული პერიოდის განმავლობაში <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>-ჯერ: <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>-დან — <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>-მდე."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-თან დაშიფრული კავშირი"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"უფრო უსაფრთხო ფიჭურ ქსელთან ხართ დაკავშირებული."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-თან დაუშიფრავი კავშირი."</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"დაუშიფრავ ფიჭურ ქსელთან ხართ დაკავშირებული. თქვენი ზარები, შეტყობინებები და მონაცემები ჩარევების მიმართ მოწყვლადია."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"ფიჭური უსაფრთხოების პარამეტრები"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"შეიტყვეთ მეტი"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"ფუნქციის კოდი შესრულდა."</string>
<string name="fcError" msgid="5325116502080221346">"კავშირის პრობლემაა ან არასწორი ფუნქციური კოდია."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"კარგი"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"დაინსტალირებულია თქვენი ადმინისტრატორის მიერ.\nდაშვებული ნებართვების სანახავად გადადით პარამეტრებზე"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"წაიშალა თქვენი ადმინისტრატორის მიერ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"კარგი"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"გადაერთვებით სამუშაო აპზე?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"თქვენი ორგანიზაცია ნებას გრთავთ, რომ დარეკოთ მხოლოდ სამსახურის აპებიდან"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"თქვენი ორგანიზაცია ნებას გრთავთ, მხოლოდ სამსახურის აპებიდან გაგზავნოთ შეტყობინებები"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"პირადი ბრაუზერის გამოყენება"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"სამსახურის ბრაუზერის გამოყენება"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"დარეკვა"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"სამსახური 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"სატესტო"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"საერთო"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"სენსიტიური შეტყობინების კონტენტი დამალულია"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ეკრანის გაზიარებიდან აპის კონტენტი დამალულია უსაფრთხოების მიზნით"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"სატელიტთან ავტომატურად დაკავშირებულია"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index ebfd196..6f02f52 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секундтан кейін"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Басқа нөмірге бағытталмады"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: қайта бағытталған жоқ."</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Ұялы желі қауіпсіздігі"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Параметрлерді қарап шығу"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Құрылғы идентификаторы пайдаланылды"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Желі (<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> байланысы) құрылғының бірегей идентификаторын (IMSI) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> және <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> аралығында <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> рет жазып алды."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"\"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\" желісіне қосылу шифрланды"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Қазір қауіпсіздеу ұялы желіге қосылып тұрсыз."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"\"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\" желісіне қосылу шифрланбаған"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Шифрланбаған ұялы желіге қосылғансыз. Қоңырауларды, хабарлар мен деректерді басқалар қолға түсіруі мүмкін."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Ұялы желі қауіпсіздігінің параметрлері"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Толық ақпарат"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Функция коды толық."</string>
<string name="fcError" msgid="5325116502080221346">"Байланыс мәселесі немесе функция коды жарамсыз."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Жарайды"</string>
@@ -830,7 +845,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Құпия сөз ережелерін тағайындау"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Экран бекітпесінің құпия сөздерінің және PIN кодтарының ұзындығын және оларда рұқсат етілген таңбаларды басқару."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Экран құлпын ашу әрекеттерін бақылау"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Экран бекітпесін ашқан кезде терілген қате құпия сөздердің санын бақылау және планшетті бекіту немесе тым көп қате құпия сөздер терілген болса, планшеттің бүкіл деректерін өшіру."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Экран құлпын ашқан кезде терілген қате құпия сөздердің саны бақыланып, тым көп қате құпия сөз терілген жағдайда, планшет құлыпталады немесе оның ішіндегі бүкіл дерек өшеді."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Экранның құлпын ашу кезінде қате енгізілген құпия сөздердің санын бақылау, құпия сөз тым көп қате енгізілген жағдайда, Android TV құрылғысын құлыптау және Android TV құрылғыңыздың барлық деректерінен тазарту."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Экран құлпын ашқан кезде, терілген қате құпия сөздердің саны бақыланады, сондай-ақ құпия сөздер бірнеше рет қате терілсе, ақпараттық-сауықтық жүйе құлыпталады немесе оның барлық дерегі жойылады."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Экран құлпын ашқан кезде терілген қате құпия сөздердің санын бақылау және құпия сөз тым көп рет қате терілгенде, телефонды құлыптау немесе оның бүкіл деректерін өшіру."</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Босату алдында PIN кодын сұрау"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Босату алдында бекітпесін ашу өрнегін сұрау"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Босату алдында құпия сөзді сұрау"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Әкімшіңіз орнатты.\nБерілген рұқсаттарды көру үшін параметрлерге өтіңіз."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Әкімші жаңартқан"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Әкімші жойған"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Жарайды"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Жұмыс қолданбасына ауысу керек пе?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ұйымыңыз тек жұмыс қолданбаларынан қоңырау шалуға рұқсат етеді."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ұйымыңыз тек жұмыс қолданбаларынан хабар жіберуге рұқсат етеді."</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Жеке браузерді пайдалану"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Жұмыс браузерін пайдалану"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Қоңырау шалу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 5f6cd38..55d7366 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> បន្ទាប់ពី <xliff:g id="TIME_DELAY">{2}</xliff:g> វិនាទី"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិនបានបញ្ជូនបន្ត"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិនបានបញ្ជូនបន្ត"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"សុវត្ថិភាពបណ្ដាញចល័ត"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ពិនិត្យមើលការកំណត់"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"បានចូលប្រើលេខកូដសម្គាល់ឧបករណ៍"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"បណ្តាញនៅលើការតភ្ជាប់ <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> បានកត់ត្រាលេខកូដសម្គាល់ខុសពីគេ (IMSI) របស់ឧបករណ៍អ្នក <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ដងក្នុងរយៈពេលចន្លោះពី <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ដល់ <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>។"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"បានអ៊ីនគ្រីបការតភ្ជាប់ទៅ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ឥឡូវនេះ អ្នកបានភ្ជាប់ទៅបណ្ដាញចល័តដែលមានសុវត្ថិភាពជាងមុន។"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"ការតភ្ជាប់ដែលមិនមានការអ៊ីនគ្រីបទៅ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"អ្នកបានភ្ជាប់ទៅបបណ្ដាញចល័តដែលមិនមានការអ៊ីនគ្រីប។ ការហៅទូរសព្ទ សារ និងទិន្នន័យរបស់អ្នកងាយរងគ្រោះពីការស្កាត់យក។"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"ការកំណត់សុវត្ថិភាពបណ្ដាញចល័ត"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ស្វែងយល់បន្ថែម"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"កូដលក្ខណៈពេញលេញ។"</string>
<string name="fcError" msgid="5325116502080221346">"បញ្ហាការតភ្ជាប់ ឬកូដលក្ខណៈមិនត្រឹមត្រូវ។"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"យល់ព្រម"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ថតអេក្រង់"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"អាចថតអេក្រង់នៃផ្ទាំងអេក្រង់បាន។"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"មើលសាកល្បង <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ច្រានចោល"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"បិទ ឬកែរបារស្ថានភាព"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ឲ្យកម្មវិធីបិទរបារស្ថានភាព ឬបន្ថែម និងលុបរូបតំណាងប្រព័ន្ធ។"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ធ្វើជារបារស្ថានភាព"</string>
@@ -843,7 +857,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"ចាក់សោអេក្រង់"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"គ្រប់គ្រងវិធី និងពេលវេលាចាក់សោអេក្រង់។"</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"លុបទិន្នន័យទាំងអស់"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"លុបទិន្នន័យកុំព្យូទ័របន្ទះដោយមិនព្រមានដោយអនុវត្តការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ។"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"លុបទិន្នន័យថេប្លេតដោយគ្មានការព្រមានដោយធ្វើការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ។"</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"លុបទិន្នន័យឧបករណ៍ Android TV របស់អ្នកដោយមិនមានការព្រមាន ដោយធ្វើការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ។"</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"លុបទិន្នន័យរបស់ប្រព័ន្ធព័ត៌មាន និងកម្សាន្តដោយមិនមានការព្រមាន ដោយធ្វើការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ។"</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"លុបទិន្នន័យទូរសព្ទដោយមិនមានការព្រមានជាមុន ដោយអនុវត្តការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ ។"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"សួររកកូដ PIN មុនពេលដកខ្ទាស់"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"សួររកលំនាំដោះសោមុនពេលដោះខ្ទាស់"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"សួររកពាក្យសម្ងាត់មុនពេលផ្ដាច់"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"បានដំឡើងដោយអ្នកគ្រប់គ្រងរបស់អ្នក។\nចូលទៅកាន់ការកំណត់ ដើម្បីមើលការអនុញ្ញាតដែលផ្ដល់ឱ្យ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"ធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"លុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"យល់ព្រម"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ប្ដូរទៅកម្មវិធីការងារឬ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ស្ថាប័នរបស់អ្នកអនុញ្ញាតឱ្យអ្នកធ្វើការហៅទូរសព្ទពីកម្មវិធីការងារតែប៉ុណ្ណោះ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ស្ថាប័នរបស់អ្នកអនុញ្ញាតឱ្យអ្នកផ្ញើសារពីកម្មវិធីការងារតែប៉ុណ្ណោះ"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ប្រើកម្មវិធីរុករកតាមអ៊ីនធឺណិតផ្ទាល់ខ្លួន"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ប្រើកម្មវិធីរុករកតាមអ៊ីនធឺណិតសម្រាប់ការងារ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ហៅទូរសព្ទ"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ការងារទី 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ការធ្វើតេស្ត"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ទូទៅ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"បានលាក់ខ្លឹមសារជូនដំណឹងដែលមានលក្ខណៈរសើប"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"បានលាក់ខ្លឹមសារកម្មវិធីពីការបង្ហាញអេក្រង់ដើម្បីសុវត្ថិភាព"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"ភ្ជាប់ដោយស្វ័យប្រវត្តិទៅផ្កាយរណប"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index ec92812..1ffcf10 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> ಸೆಕೆಂಡುಗಳ ನಂತರ <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"ಸೆಲ್ಯುಲಾರ್ ನೆಟ್ವರ್ಕ್ ಭದ್ರತೆ"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ಸಾಧನ ಗುರುತಿಸುವಿಕೆಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲಾಗಿದೆ"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ಕನೆಕ್ಷನ್ಲ್ಲಿರುವ ನೆಟ್ವರ್ಕ್ ನಿಮ್ಮ ಸಾಧನದ ಅನನ್ಯ ಗುರುತಿಸುವಿಕೆಯನ್ನು (IMSI) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ಮತ್ತು <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> ರ ನಡುವಿನ ಅವಧಿಯಲ್ಲಿ <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ಬಾರಿ ದಾಖಲಿಸಿದೆ."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ಗೆ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಕನೆಕ್ಷನ್"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ನೀವು ಈಗ ಹೆಚ್ಚು ಸುರಕ್ಷಿತ ಸೆಲ್ಯುಲಾರ್ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದ್ದೀರಿ."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ಗೆ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡದ ಕನೆಕ್ಷನ್"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"ನೀವು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡದ ಸೆಲ್ಯುಲಾರ್ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದ್ದೀರಿ. ನಿಮ್ಮ ಕರೆಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಡೇಟಾಗೆ ಹೆಚ್ಚು ಬಾರಿ ಅಡಚಣೆಯಾಗುತ್ತದೆ."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"ಸೆಲ್ಯುಲಾರ್ ಭದ್ರತಾ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"ವೈಶಿಷ್ಟ್ಯದ ಕೋಡ್ ಪೂರ್ಣಗೊಂಡಿದೆ."</string>
<string name="fcError" msgid="5325116502080221346">"ಸಂಪರ್ಕದ ಸಮಸ್ಯೆ ಅಥವಾ ಅಮಾನ್ಯ ವೈಶಿಷ್ಟ್ಯದ ಕೋಡ್."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ಸರಿ"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ಪ್ರದರ್ಶನದ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಲ್ಲದು."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"ಪೂರ್ವವೀಕ್ಷಣೆ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ವಜಾಗೊಳಿಸಿ"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -830,7 +844,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"ಪಾಸ್ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ಪರದೆ ಲಾಕ್ನಲ್ಲಿನ ಪಾಸ್ವರ್ಡ್ಗಳು ಮತ್ತು ಪಿನ್ಗಳ ಅನುಮತಿಸಲಾದ ಅಕ್ಷರಗಳ ಪ್ರಮಾಣವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"ಪರದೆಯ ಅನ್ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಟ್ಯಾಬ್ಲೆಟ್ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ಸ್ಕ್ರೀನ್ ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಟ್ಯಾಬ್ಲೆಟ್ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ Android TV ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡುತ್ತದೆ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದರೆ ನಿಮ್ಮ ಎಲ್ಲಾ Android TV ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕುತ್ತದೆ."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ ಮತ್ತು ಇನ್ಫೋಟೈನ್ಮೆಂಟ್ ಸಿಸ್ಟಂ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಇನ್ಫೋಟೈನ್ಮೆಂಟ್ ಸಿಸ್ಟಂನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿದಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಫೋನ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಫೋನ್ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ಅನ್ಪಿನ್ ಮಾಡಲು ಪಿನ್ ಕೇಳು"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ಅನ್ಪಿನ್ ಮಾಡಲು ಅನ್ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ಅನ್ಪಿನ್ ಮಾಡಲು ಪಾಸ್ವರ್ಡ್ ಕೇಳು"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿದ್ದಾರೆ.\nನೀಡಲಾದ ಅನುಮತಿಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಅಪ್ಡೇಟ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಅಳಿಸಿದ್ದಾರೆ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ಸರಿ"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗೆ ಬದಲಿಸಬೇಕೇ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳಿಂದ ಮಾತ್ರ ಕರೆಗಳನ್ನು ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳಿಂದ ಮಾತ್ರ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ವೈಯಕ್ತಿಕ ಬ್ರೌಸರ್ ಬಳಸಿ"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ಉದ್ಯೋಗ ಬ್ರೌಸರ್ ಬಳಸಿ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ಕರೆ ಮಾಡಿ"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ಕೆಲಸ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ಪರೀಕ್ಷೆ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ಸಮುದಾಯ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"ಸೂಕ್ಷ್ಮ ನೋಟಿಫಿಕೇಶನ್ ಕಂಟೆಂಟ್ ಅನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ಭದ್ರತೆಗಾಗಿ ಸ್ಕ್ರೀನ್ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯಲ್ಲಿ ಆ್ಯಪ್ ಕಂಟೆಂಟ್ ಅನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"ಸ್ಯಾಟಲೈಟ್ಗೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5a1af5e..a6cfe2a 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g><xliff:g id="TIME_DELAY">{2}</xliff:g>초 후"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: 착신전환 안됨"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: 착신전환 안됨"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"셀룰러 네트워크 보안"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"설정 검토"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"기기 식별자에 액세스됨"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> 연결의 네트워크가 <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>부터 <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>의 기간 동안 기기의 고유 식별자(IMSI)에 <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>회 기록되었습니다."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"암호화된 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> 연결"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"이제 더 안전한 셀룰러 네트워크에 연결되었습니다."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"암호화되지 않은 <xliff:g id="NETWORK_NAME">%1$s</xliff:g> 연결"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"암호화되지 않은 셀룰러 네트워크에 연결되어 있습니다. 통화, 메시지, 데이터가 가로채기에 취약합니다."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"셀룰러 네트워크 보안 설정"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"자세히 알아보기"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"기능 코드가 완료되었습니다."</string>
<string name="fcError" msgid="5325116502080221346">"연결에 문제가 있거나 기능 코드가 잘못되었습니다."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"확인"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"고정 해제 이전에 PIN 요청"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"고정 해제 시 잠금 해제 패턴 요청"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"고정 해제 이전에 비밀번호 요청"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"관리자에 의해 설치되었습니다.\n부여된 권한을 확인하려면 설정으로 이동하세요."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"관리자에 의해 업데이트되었습니다."</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"관리자에 의해 삭제되었습니다."</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"확인"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"직장 앱으로 전환할까요?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"귀하의 조직에서 직장 앱을 사용한 통화만 허용합니다."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"귀하의 조직에서 직장 앱을 사용한 메시지 전송만 허용합니다."</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"개인 브라우저 사용"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"직장 브라우저 사용"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"통화"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 6731984..e21a76c 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секунддан кийин"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Багытталган эмес"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Багытталган эмес"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Мобилдик тармактын коопсуздугу"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Параметрлерди карап чыгуу"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Түзмөк идентификаторун пайдалануу"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Тармак (<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> туташуусу) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> баштап <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> чейинки аралыкта түзмөгүңүздүн так аныкталуучу номерин (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> жолу жаздырып алды."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> тармагына шифрленген туташуу"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Сиз эми коопсуз мобилдик тармакка туташтыңыз."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> тармагына шифрленбеген туташуу"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Сиз шифрленбеген мобилдик тармакка туташкансыз. Чалууларыңыз, билдирүүлөрүңүз жана маалыматыңыз кармалып калышы мүмкүн."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Мобилдик тармактын коопсуздук параметрлери"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Кеңири маалымат"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Функция коду аткарылды."</string>
<string name="fcError" msgid="5325116502080221346">"Туташууда көйгөй чыкты же функция коду жараксыз."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Жарайт"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бошотуудан мурун PIN суралсын"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бошотуудан мурун графикалык ачкыч суралсын"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Бошотуудан мурун сырсөз суралсын"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Администраторуңуз орнотту.\nБерилген уруксаттарды көрүү үчүн параметрлерге өтүңүз"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Администраторуңуз жаңыртып койгон"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Администраторуңуз жок кылып салган"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ЖАРАЙТ"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Жумуш колдонмосуна которуласызбы?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Уюмуңуз жумуш колдонмолорунан гана чалууга уруксат берет"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Уюмуңуз билдирүүлөрдү жумуш колдонмолорунан гана жөнөтүүгө уруксат берет"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Жеке серепчини колдонуу"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Жумуш серепчисин колдонуу"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Чалуу"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 12adb17..4624d5e 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -153,16 +153,19 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ຫຼັງຈາກ <xliff:g id="TIME_DELAY">{2}</xliff:g> ວິນາທີ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ບໍ່ຖືກສົ່ງຕໍ່"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ບໍ່ຖືກສົ່ງຕໍ່"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"ຄວາມປອດໄພຂອງເຄືອຂ່າຍມືຖື"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ກວດສອບການຕັ້ງຄ່າ"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ເຂົ້າເຖິງຕົວລະບຸອຸປະກອນແລ້ວ"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"ເຄືອຂ່າຍຢູ່ການເຊື່ອມຕໍ່ <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ທີ່ບັນທຶກຕົວລະບຸທີ່ບໍ່ຊ້ຳກັນ (IMSI) ໃນອຸປະກອນຂອງທ່ານ <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ເທື່ອໃນໄລຍະເວລາລະຫວ່າງ <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ຫາ <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"ການເຊື່ອມຕໍ່ທີ່ໄດ້ຖືກເຂົ້າລະຫັດໄວ້ກັບ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ຕອນນີ້ທ່ານເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍມືຖືທີ່ປອດໄພຍິ່ງຂຶ້ນແລ້ວ."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"ການເຊື່ອມຕໍ່ທີ່ບໍ່ໄດ້ຖືກເຂົ້າລະຫັດໄວ້ກັບ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"ທ່ານເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍມືຖືທີ່ບໍ່ໄດ້ຖືກເຂົ້າລະຫັດໄວ້. ການໂທ, ຂໍ້ຄວາມ ແລະ ຂໍ້ມູນຂອງທ່ານແມ່ນມີໂອກາດສ່ຽງທີ່ຈະຖືກສະກັດກັ້ນ."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"ການຕັ້ງຄ່າຄວາມປອດໄພຂອງເຄືອຂ່າຍມືຖື"</string>
+ <string name="scCellularNetworkSecurityTitle" msgid="7752521808690294384">"ຄວາມປອດໄພເຄືອຂ່າຍມືຖື"</string>
+ <string name="scCellularNetworkSecuritySummary" msgid="7042036754550545005">"ການເຂົ້າລະຫັດ, ການແຈ້ງເຕືອນສຳລັບເຄືອຂ່າຍທີ່ບໍ່ໄດ້ຖືກເຂົ້າລະຫັດ"</string>
+ <string name="scIdentifierDisclosureIssueTitle" msgid="2898888825129970328">"ເຂົ້າເຖິງ ID ອຸປະກອນແລ້ວ"</string>
+ <string name="scIdentifierDisclosureIssueSummaryNotification" msgid="3699930821270580416">"ເມື່ອເວລາ <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, ເຄືອຂ່າຍໃກ້ຄຽງໄດ້ບັນທຶກ ID ທີ່ບໍ່ຊ້ຳກັນຂອງອຸປະກອນຂອງທ່ານ (IMSI ຫຼື IMEI) ໃນລະຫວ່າງທີ່ໃຊ້ຊິມ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ຂອງທ່ານ"</string>
+ <string name="scIdentifierDisclosureIssueSummary" msgid="7283387338827749276">"ເມື່ອເວລາ <xliff:g id="DISCLOSURE_TIME">%1$s</xliff:g>, ເຄືອຂ່າຍໃກ້ຄຽງໄດ້ບັນທຶກ ID ທີ່ບໍ່ຊ້ຳກັນຂອງອຸປະກອນຂອງທ່ານ (IMSI ຫຼື IMEI) ໃນລະຫວ່າງທີ່ໃຊ້ຊິມ <xliff:g id="DISCLOSURE_NETWORK">%2$s</xliff:g> ຂອງທ່ານ.\n\nເຊິ່ງໝາຍຄວາມວ່າສະຖານທີ່, ການເຄື່ອນໄຫວ ຫຼື ຂໍ້ມູນລະບຸຕົວຕົນຂອງທ່ານໄດ້ຖືກບັນທຶກໄວ້ແລ້ວ. ນີ້ແມ່ນແນວທາງປະຕິບັດທົ່ວໄປ ແຕ່ອາດເປັນບັນຫາສຳລັບຜູ້ທີ່ກັງວົນກ່ຽວກັບຄວາມເປັນສ່ວນຕົວ."</string>
+ <string name="scNullCipherIssueEncryptedTitle" msgid="234717016411824969">"ເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ທີ່ໄດ້ຖືກເຂົ້າລະຫັດແລ້ວ"</string>
+ <string name="scNullCipherIssueEncryptedSummary" msgid="8577510708842150475">"ການເຊື່ອມຕໍ່ຊິມ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ປອດໄພຍິ່ງຂຶ້ນແລ້ວ"</string>
+ <string name="scNullCipherIssueNonEncryptedTitle" msgid="3978071464929453915">"ເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍທີ່ບໍ່ໄດ້ຖືກເຂົ້າລະຫັດແລ້ວ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummaryNotification" msgid="7386936934128110388">"ຕອນນີ້ການໂທ, ຂໍ້ຄວາມ ແລະ ຂໍ້ມູນກຳລັງຢູ່ໃນຄວາມສ່ຽງໃນລະຫວ່າງທີ່ໃຊ້ຊິມ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ຂອງທ່ານ"</string>
+ <string name="scNullCipherIssueNonEncryptedSummary" msgid="5093428974513703253">"ຕອນນີ້ການໂທ, ຂໍ້ຄວາມ ແລະ ຂໍ້ມູນກຳລັງຢູ່ໃນຄວາມສ່ຽງໃນລະຫວ່າງທີ່ໃຊ້ຊິມ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ຂອງທ່ານ.\n\nເມື່ອການເຊື່ອມຕໍ່ຂອງທ່ານໄດ້ຖືກເຂົ້າລະຫັດອີກຄັ້ງ, ທ່ານຈະໄດ້ຮັບການແຈ້ງເຕືອນອີກຄັ້ງ."</string>
+ <string name="scNullCipherIssueActionSettings" msgid="5888857706424639946">"ການຕັ້ງຄ່າຄວາມປອດໄພເຄືອຂ່າຍມືຖື"</string>
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ສຶກສາເພີ່ມເຕີມ"</string>
+ <string name="scNullCipherIssueActionGotIt" msgid="8747796640866585787">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="fcComplete" msgid="1080909484660507044">"ລະຫັດຄຸນສົມບັດສຳເລັດແລ້ວ."</string>
<string name="fcError" msgid="5325116502080221346">"ເກີດບັນຫາການເຊື່ອມຕໍ່ ຫຼືລະຫັດການເຮັດວຽກບໍ່ຖືກຕ້ອງ."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ຕົກລົງ"</string>
@@ -356,8 +359,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ຖ່າຍຮູບໜ້າຈໍ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"ຕົວຢ່າງ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ປິດໄວ້"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ເປັນແຖບສະຖານະ"</string>
@@ -830,7 +832,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ຄວບຄຸມຄວາມຍາວ ແລະຕົວອັກສອນທີ່ອະນຸຍາດໃຫ້ຢູ່ໃນລະຫັດລັອກໜ້າຈໍ ແລະ PIN."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະລັອກແທັບເລັດ ຫຼືລຶບຂໍ້ມູນທັງໝົດຂອງແທັບເລັດ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະ ລັອກແທັບເລັດ ຫຼື ລຶບຂໍ້ມູນທັງໝົດຂອງແທັບເລັດ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ຕິດຕາມຈຳນວນລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງທີ່ພິມຕອນກຳລັງປົດລັອກໜ້າຈໍ ແລະ ລັອກອຸປະກອນ Android TV ຂອງທ່ານ ຫຼື ລຶບຂໍ້ມູນຂອງອຸປະກອນ Android TV ຂອງທ່ານຫາກພິມລະຫັດຜ່ານຜິດຫຼາຍເທື່ອເກີນໄປ."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ຕິດຕາມຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງໃນເວລາປົດລັອກໜ້າຈໍ ແລະ ລັອກລະບົບສາລະບັນເທີງ ຫຼື ລຶບຂໍ້ມູນຂອງລະບົບສາລະບັນເທີງທັງໝົດຫາກມີການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງຫຼາຍເກີນໄປ."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະລັອກໂທລະສັບ ຫຼືລຶບຂໍ້ມູນທັງໝົດຂອງໂປລະສັບ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string>
@@ -1898,8 +1900,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ຖາມຫາ PIN ກ່ອນຍົກເລີກການປັກໝຸດ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ຖາມຫາຮູບແບບປົດລັອກກ່ອນຍົກເລີກການປັກໝຸດ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ຖາມຫາລະຫັດຜ່ານກ່ອນຍົກເລີກການປັກໝຸດ"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"ຕິດຕັ້ງໂດຍຜູ້ເບິ່ງແຍງຂອງທ່ານ.\nເຂົ້າໄປການຕັ້ງຄ່າເພື່ອເບິ່ງສິດທີ່ໄດ້ຮັບອະນຸຍາດ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"ຖືກອັບໂຫລດໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ຖືກລຶບອອກໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ຕົກລົງ"</string>
@@ -2217,6 +2218,8 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ສະຫຼັບໄປເປັນແອັບບ່ອນເຮັດວຽກບໍ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ອົງການຂອງທ່ານອະນຸຍາດໃຫ້ທ່ານໂທຈາກແອັບບ່ອນເຮັດວຽກເທົ່ານັ້ນ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ອົງການຂອງທ່ານອະນຸຍາດໃຫ້ທ່ານສົ່ງຂໍ້ຄວາມໄດ້ຈາກແອັບບ່ອນເຮັດວຽກເທົ່ານັ້ນ"</string>
+ <string name="miniresolver_private_space_phone_information" msgid="4469511223312488570">"ທ່ານສາມາດໂທໄດ້ຈາກແອັບໂທລະສັບສ່ວນຕົວຂອງທ່ານເທົ່ານັ້ນ. ລະບົບຈະເພີ່ມການໂທດ້ວຍແອັບໂທລະສັບສ່ວນຕົວໃສ່ໃນປະຫວັດການໂທສ່ວນຕົວຂອງທ່ານ."</string>
+ <string name="miniresolver_private_space_messages_information" msgid="111285656327622118">"ທ່ານສາມາດສົ່ງຂໍ້ຄວາມ SMS ໄດ້ຈາກແອັບ Messages ສ່ວນຕົວຂອງທ່ານເທົ່ານັ້ນ."</string>
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ໃຊ້ໂປຣແກຣມທ່ອງເວັບສ່ວນຕົວ"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ໃຊ້ໂປຣແກຣມທ່ອງເວັບບ່ອນເຮັດວຽກ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ໂທ"</string>
@@ -2396,8 +2399,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ວຽກ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ທົດສອບ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"ສ່ວນກາງ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"ເນື້ອຫາການແຈ້ງເຕືອນທີ່ລະອຽດອ່ອນເຊື່ອງຢູ່"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ເນື້ອຫາແອັບຖືກເຊື່ອງໄວ້ຈາກການແບ່ງປັນໜ້າຈໍເພື່ອຄວາມປອດໄພ"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"ເຊື່ອມຕໍ່ກັບດາວທຽມໂດຍອັດຕະໂນມັດ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 3a95d2c..31ede33 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neperadresuota"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neperadresuota"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobiliojo ryšio tinklo sauga"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Žr. nustatymus"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Įrenginio identifikatorius pasiektas"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Tinklo, esančio „<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>“, ryšys įrašė jūsų įrenginio unikalų identifikatorių (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> k. laikotarpiu nuo <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> iki <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifruotas ryšys su „<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Esate prisijungę prie saugesnio mobiliojo ryšio tinklo."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifruotas ryšys su „<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Esate prisijungę prie nešifruoto mobiliojo ryšio tinklo. Jūsų skambučiai, pranešimai bei duomenys yra pažeidžiami ir gali būti perimti."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobiliojo ryšio saugos nustatymai"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Sužinokite daugiau"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Funkcijos kodas baigtas."</string>
<string name="fcError" msgid="5325116502080221346">"Ryšio problema arba neteisingas funkcijos kodas."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Gerai"</string>
@@ -358,8 +373,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrano kopijos kūrimas"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Galima sukurti vaizdo ekrano kopiją."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Peržiūra, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"uždaryti"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"išjungti ar keisti būsenos juostą"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"būti būsenos juosta"</string>
@@ -832,7 +846,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nustatyti slaptažodžio taisykles"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Valdykite, kokio ilgio ekrano užrakto slaptažodžius ir PIN kodus galima naudoti."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Stebėti bandymus atrakinti ekraną"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Stebimas neteisingai įvestų slaptažodžių skaičius atrakinant ekraną ir užrakinti planšetinį kompiuterį arba ištrinti visus jame esančius duomenis, jei įvedama per daug neteisingų slaptažodžių."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Stebimas neteisingai įvestų slaptažodžių skaičius atrakinant ekraną ir užrakinamas planšetinis kompiuteris arba ištrinami visi jame esantys duomenys, jei įvedama per daug neteisingų slaptažodžių."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Stebėkite atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinkite „Android TV“ įrenginį arba ištrinkite visus „Android TV“ įrenginio duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Stebėti atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinti informacinę pramoginę sistemą arba ištrinti visus informacinės pramoginės sistemos duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Atrakindami ekraną stebėkite neteisingai įvestų slaptažodžių skaičių ir užrakinkite telefoną ar ištrinkite visus telefono duomenis, jei įvedama per daug neteisingų slaptažodžių."</string>
@@ -1900,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prašyti PIN kodo prieš atsegant"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Prašyti atrakinimo piešinio prieš atsegant"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Prašyti slaptažodžio prieš atsegant"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Įdiegė administratorius.\nEikite į nustatymus ir peržiūrėkite suteiktus leidimus"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atnaujino administratorius"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Ištrynė administratorius"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Gerai"</string>
@@ -2219,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Perjungti į darbo programą?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Jūsų organizacija leidžia skambinti tik iš darbo programų"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Jūsų organizacija leidžia siųsti pranešimus tik iš darbo programų"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Naudoti asmeninę naršyklę"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Naudoti darbo naršyklę"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Skambinti"</string>
@@ -2398,8 +2415,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Darbas (3)"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Bandymas"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Bendruomenės"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Neskelbtinos informacijos pranešimo turinys paslėptas"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Programos turinys paslėptas bendrinant ekraną saugumo sumetimais"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatiškai prisijungta prie palydovinio ryšio"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 7e5ee3b..93d6a4f 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pēc <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundes(-ēm)"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nav pāradresēts"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nav pāradresēts"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobilā tīkla drošība"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Pārskatīt iestatījumus"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Notikusi piekļuve ierīces identifikatoram"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Kāds tīkls savienojumā <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> reizi(-es) reģistrēja jūsu ierīces unikālo identifikatoru (IMSI) šajā laika periodā: <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>–<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifrēts savienojums ar tīklu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Tagad ir izveidots savienojums ar drošāku mobilo tīklu."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifrēts savienojums ar tīklu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Ir izveidots savienojums ar nešifrētu mobilo tīklu. Jūsu zvani, ziņojumi un dati nav aizsargāti pret pārtveršanu."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobilā tīkla drošības iestatījumi"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Uzzināt vairāk"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Funkcijas kods ir pabeigts."</string>
<string name="fcError" msgid="5325116502080221346">"Savienojuma problēma vai nederīgs funkcijas kods."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Labi"</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prasīt PIN kodu pirms atspraušanas"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pirms atspraušanas pieprasīt atbloķēšanas kombināciju"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pirms atspraušanas pieprasīt paroli"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalēja jūsu administrators.\nPārejiet uz iestatījumiem, lai skatītu piešķirtās atļaujas."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atjaunināja administrators"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dzēsa administrators"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Labi"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vai pārslēgties uz darba lietotni?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Jūsu organizācija ļauj jums veikt zvanus tikai no darba lietotnēm."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Jūsu organizācija ļauj jums sūtīt ziņojumus tikai no darba lietotnēm."</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Izmantot personīgo pārlūku"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Izmantot darba pārlūku"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Zvanīt"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 3df020a..0166b67 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> по <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не е препратено"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не е проследен"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Безбедност на мобилната мрежа"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Преглед на поставките"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Пристапено е до идентификаторот на уредот"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Мрежа на врската <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> го снимила уникатниот идентификатор (IMSI) на вашиот уред <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> пати во периодот меѓу <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> и <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Шифрирана врска на <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Сега сте поврзани на побезбедна мобилна мрежа."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Нешифрирана врска на <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Се поврзавте на нешифрирана мобилна мрежа. Постои опасност од проследување на вашите повици, пораки и податоци."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Поставки за безбедност на мобилната мрежа"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Дознајте повеќе"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Кодот за карактеристиката заврши."</string>
<string name="fcError" msgid="5325116502080221346">"Проблем со поврзувањето или неважечки код за карактеристиката."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Во ред"</string>
@@ -827,7 +842,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Дозволува сопственикот да ја ажурира апликацијата што претходно ја инсталирал без дејство од корисникот"</string>
<string name="permlab_writeVerificationStateE2eeContactKeys" msgid="3990742344778360457">"ажурирање на состојбите за потврда на контактните клучеви за обострано шифрирање што се во сопственост на други апликации"</string>
<string name="permdesc_writeVerificationStateE2eeContactKeys" msgid="8453156829747427041">"Дозволува апликацијата да ги ажурира состојбите за потврда на контактните клучеви за обострано шифрирање што се во сопственост на други апликации"</string>
- <string name="policylab_limitPassword" msgid="4851829918814422199">"Постави правила за лозинката"</string>
+ <string name="policylab_limitPassword" msgid="4851829918814422199">"Поставување правила за лозинката"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролирај ги должината и знаците што се дозволени за лозинки и PIN-броеви за отклучување екран."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Следење на обидите за отклучување на екранот"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Го следи бројот на неточни лозинки што се внесени за отклучување на екранот и го заклучува таблетот или ги брише сите податоци од него ако се внесат голем број неточни лозинки."</string>
@@ -838,31 +853,31 @@
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Го следи бројот на погрешно внесени лозинки при отклучување на екранот и го заклучува уредот Android TV или ги брише сите податоци од овој корисник доколку се внесени премногу погрешни лозинки."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Набљудувај го бројот на погрешно внесени лозинки при отклучување на екранот и заклучи го системот за информации и забава или избриши ги сите податоци од овој профил доколку се внесени премногу погрешни лозинки."</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Набљудувај го бројот на погрешно внесени лозинки при отклучување на екранот и заклучи го телефонот или избриши ги сите податоци од овој корисник доколку се внесени премногу погрешни лозинки."</string>
- <string name="policylab_resetPassword" msgid="214556238645096520">"Промени го заклучувањето на екранот"</string>
- <string name="policydesc_resetPassword" msgid="4626419138439341851">"Промени го заклучувањето на екранот."</string>
- <string name="policylab_forceLock" msgid="7360335502968476434">"Заклучи го екранот"</string>
- <string name="policydesc_forceLock" msgid="1008844760853899693">"Контролирај како и кога се заклучува екранот."</string>
+ <string name="policylab_resetPassword" msgid="214556238645096520">"Менување на заклучувањето на екранот"</string>
+ <string name="policydesc_resetPassword" msgid="4626419138439341851">"Го менува заклучувањето на екранот."</string>
+ <string name="policylab_forceLock" msgid="7360335502968476434">"Заклучување на екранот"</string>
+ <string name="policydesc_forceLock" msgid="1008844760853899693">"Контролира како и кога се заклучува екранот."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Бришење на сите податоци"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Избриши ги податоците во таблетот без предупредување со ресетирање на фабрички податоци."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Ги брише податоците од таблетот без предупредување вршејќи ресетирање на фабрички податоци."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Ги брише податоците на вашиот уред Android TV без предупредување, така што ќе изврши ресетирање на фабричките податоци."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Избриши ги податоците во системот за информации и забава без предупредување со ресетирање на фабрички податоци."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Ги брише податоците од телефонот без предупредување вршејќи ресетирање на фабрички податоци."</string>
- <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Избриши ги податоците на профилот"</string>
- <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Избриши ги податоците на корисникот"</string>
+ <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Бришење на податоците на профилот"</string>
+ <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Бришење на податоците на корисникот"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Избриши ги податоците на овој корисник на таблетот без предупредување."</string>
<string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Ги брише податоците на овој корисник на уредов Android TV без предупредување."</string>
<string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Избриши ги податоците на профилов во системот за информации и забава без предупредување."</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Избриши ги податоците на овој корисник на телефонот без предупредување."</string>
- <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Постави го глобалниот прокси на уредот"</string>
+ <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Поставување глобален прокси на уредот"</string>
<string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Поставете го глобалниот прокси на уредот да се користи додека политиката е овозможена. Само сопственикот на уредот може да го поставува глобалниот прокси."</string>
<string name="policylab_expirePassword" msgid="6015404400532459169">"Рок на лозинка за закл. екран"</string>
<string name="policydesc_expirePassword" msgid="9136524319325960675">"Измени колку често мора да се менува лозинката, PIN-бројот или шемата за заклучување екран."</string>
<string name="policylab_encryptedStorage" msgid="9012936958126670110">"Постави шифрирање на меморија"</string>
<string name="policydesc_encryptedStorage" msgid="1102516950740375617">"Барај зачуваните податоци за апликација да се шифрирани."</string>
- <string name="policylab_disableCamera" msgid="5749486347810162018">"Оневозможи фотоапарати"</string>
+ <string name="policylab_disableCamera" msgid="5749486347810162018">"Оневозможување на камерите"</string>
<string name="policydesc_disableCamera" msgid="3204405908799676104">"Спречи употреба на сите камери на уредот."</string>
- <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"Онев. функции од заклуч. екран"</string>
- <string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"Спречи користење на некои функции од заклучување на екранот."</string>
+ <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"Оневозможување функции за заклучување на екранот"</string>
+ <string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"Го спречува користењето на некои функции за заклучување на екранот."</string>
<string-array name="phoneTypes">
<item msgid="8996339953292723951">"Дома"</item>
<item msgid="7740243458912727194">"Мобилен"</item>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Побарај PIN пред откачување"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Побарај шема за откл. пред откачување"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Побарај лозинка пред откачување"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Инсталирано од администраторот.\nОдете во „Поставки“ за да ги прегледате доделените дозволи"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирано од администраторот"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Избришано од администраторот"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Во ред"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Да се префрли на работна апликација?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Вашата организација ви дозволува да упатувате повици само од работни апликации"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Вашата организација ви дозволува да испраќате пораки само од работни апликации"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Користи личен прелистувач"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Користи работен прелистувач"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Повикај"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index b719ba1..f90eddc 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> നിമിഷത്തിനുശേഷം <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: കൈമാറിയില്ല"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: കൈമാറിയിട്ടില്ല"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"സെല്ലുലാർ നെറ്റ്വർക്ക് സുരക്ഷ"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ക്രമീകരണം അവലോകനം ചെയ്യുക"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ഉപകരണ ഐഡന്റിഫയർ ആക്സസ് ചെയ്തു"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> കണക്ഷനിൽ ഉള്ള ഒരു നെറ്റ്വർക്ക്, നിങ്ങളുടെ ഉപകരണത്തിന്റെ തനതായ ഐഡന്റിഫയർ (IMSI)<xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>-നും <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>-നും ഇടയിൽ <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> തവണ റെക്കോർഡ് ചെയ്തു."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> എന്നതിലേക്കുള്ള എൻക്രിപ്റ്റ് ചെയ്ത കണക്ഷൻ"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"കൂടുതൽ സുരക്ഷിതമായ സെല്ലുലാർ നെറ്റ്വർക്കിലേക്ക് നിങ്ങൾ കണക്റ്റ് ചെയ്തിരിക്കുന്നു."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> എന്നതിലേക്കുള്ള എൻക്രിപ്റ്റ് ചെയ്യാത്ത കണക്ഷൻ"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"എൻക്രിപ്റ്റ് ചെയ്യാത്ത സെല്ലുലാർ നെറ്റ്വർക്കിലേക്ക് നിങ്ങൾ കണക്റ്റ് ചെയ്തിരിക്കുന്നു. നിങ്ങളുടെ കോളുകൾ, സന്ദേശങ്ങൾ, ഡാറ്റ എന്നിവ തടസ്സപ്പെടാൻ സാധ്യതയുണ്ട്."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"സെല്ലുലാർ സുരക്ഷാ ക്രമീകരണം"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"കൂടുതലറിയുക"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"ഫീച്ചർ കോഡ് പൂർണ്ണമാണ്."</string>
<string name="fcError" msgid="5325116502080221346">"കണക്ഷൻ പ്രശ്നം അല്ലെങ്കിൽ ഫീച്ചർ കോഡ് അസാധുവാണ്."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ശരി"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"സ്ക്രീന്ഷോട്ട് എടുക്കുക"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ഡിസ്പ്ലേയുടെ സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിയും."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"പ്രിവ്യൂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ഡിസ്മിസ് ചെയ്യുക"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്ക്കരിക്കുക"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"അൺപിന്നിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടൂ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"അൺപിന്നിനുമുമ്പ് പാസ്വേഡ് ആവശ്യപ്പെടൂ"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"നിങ്ങളുടെ അഡ്മിൻ ഇൻസ്റ്റാൾ ചെയ്തത്.\nനൽകിയ അനുമതികൾ കാണാൻ ക്രമീകരണത്തിലേക്ക് പോകുക"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"നിങ്ങളുടെ അഡ്മിൻ അപ്ഡേറ്റ് ചെയ്യുന്നത്"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"നിങ്ങളുടെ അഡ്മിൻ ഇല്ലാതാക്കുന്നത്"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ശരി"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ഔദ്യോഗിക ആപ്പിലേക്ക് മാറണോ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"സ്ഥാപനം ഔദ്യോഗിക ആപ്പുകളിൽ നിന്ന് കോളുകൾ ചെയ്യാൻ മാത്രമേ നിങ്ങളെ അനുവദിക്കുന്നുള്ളൂ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"സ്ഥാപനം ഔദ്യോഗിക ആപ്പുകളിൽ നിന്ന് സന്ദേശമയയ്ക്കാൻ മാത്രമേ നിങ്ങളെ അനുവദിക്കുന്നുള്ളൂ"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"വ്യക്തിപരമായ ബ്രൗസർ ഉപയോഗിക്കുക"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ഔദ്യോഗിക ബ്രൗസർ ഉപയോഗിക്കുക"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"കോൾ ചെയ്യുക"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ഔദ്യോഗികം 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ടെസ്റ്റ്"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"കമ്മ്യൂണൽ"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"സൂക്ഷ്മമായി കൈകാര്യം ചെയ്യേണ്ട അറിയിപ്പ് ഉള്ളടക്കം മറച്ചിരിക്കുന്നു"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ആപ്പ് ഉള്ളടക്കം, അതിന്റെ സുരക്ഷയ്ക്കായി സ്ക്രീൻ പങ്കിടലിൽ നിന്ന് മറച്ചിരിക്കുന്നു"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"സാറ്റലൈറ്റിലേക്ക് സ്വയമേവ കണക്റ്റ് ചെയ്തു"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index e6f57a3..45eacc0 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секундын дараа"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: дамжуулагдаагүй"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: дамжуулагдаагүй"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Үүрэн холбооны сүлжээний аюулгүй байдал"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Тохиргоог хянах"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Төхөөрөмжийн таниулбарт хандсан"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> холболт дээрх сүлжээ таны төхөөрөмжийн өвөрмөц таниулбарыг (IMSI) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>-с <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>-н хоорондох хугацаанд <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> удаа бүртгэсэн."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-н шифрлэгдсэн холболт"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Та одоо илүү аюулгүй үүрэн холбооны сүлжээнд холбогдлоо."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-н шифрлэгдээгүй холболт"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Та шифрлэгдээгүй үүрэн холбооны сүлжээнд холбогдсон. Таны дуудлага, мессеж болон өгөгдлийг дундаас нь авах эрсдэлтэй."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Үүрэн холбооны аюулгүй байдлын тохиргоо"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Нэмэлт мэдээлэл авах"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Онцлог код дуусав."</string>
<string name="fcError" msgid="5325116502080221346">"Холболтын асуудал эсвэл буруу функцын код."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ОК"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бэхэлснийг болиулахаасаа өмнө ПИН асуух"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бэхэлснийг болиулахаас өмнө түгжээ тайлах хээ асуух"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Танай админ суулгасан.\nОлгосон зөвшөөрлүүдийг харахын тулд тохиргоо руу очно уу"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Таны админ шинэчилсэн"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Таны админ устгасан"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ажлын апп руу сэлгэх үү?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Танай байгууллага танд зөвхөн ажлын аппуудаас дуудлага хийхийг зөвшөөрдөг"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Танай байгууллага танд зөвхөн ажлын аппуудаас мессеж илгээхийг зөвшөөрдөг"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Хувийн хөтөч ашиглах"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Ажлын хөтөч ашиглах"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Залгах"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index a052966..c2a9c73 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंदांनंतर <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: फॉरवर्ड केला नाही"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: फॉरवर्ड केला नाही"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"मोबाइल नेटवर्कची सुरक्षा"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"सेटिंग्जचे पुनरावलोकन करा"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"डिव्हाइस आयडेंटिफायर अॅक्सेस केला आहे"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> कनेक्शनवरील नेटवर्कने <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> आणि <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> या कालावधीदरम्यान तुमच्या डिव्हाइसचा युनिक आयडेंटिफायर (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> वेळा रेकॉर्ड केला."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> वर कनेक्शन एन्क्रिप्ट केले आहे"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"तुम्ही आता आणखी सुरक्षित मोबाइल नेटवर्कशी कनेक्ट केले आहे."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> वर कनेक्शन एन्क्रिप्ट केलेले नाही"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"तुम्ही एन्क्रिप्ट न केलेल्या मोबाइल नेटवर्कशी कनेक्ट केले आहे. तुमचे कॉल, मेसेज आणि डेटा यामध्ये व्यत्यय येण्याचा धोका आहे."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"मोबाइल सुरक्षा सेटिंग्ज"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"अधिक जाणून घ्या"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"वैशिष्ट्य कोड पूर्ण."</string>
<string name="fcError" msgid="5325116502080221346">"कनेक्शन समस्या किंवा अवैध फीचर कोड."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ठीक"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट घ्या"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेचा स्क्रीनशॉट घेऊ शकतो."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"पूर्वावलोकन, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"डिसमिस करा"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार होऊ द्या"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करण्यापूर्वी पिन विचारा"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करण्यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करण्यापूर्वी संकेतशब्दासाठी विचारा"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"तुमच्या ॲडमिनने इंस्टॉल केले आहे.\nदिलेल्या परवानग्या पाहण्यासाठी सेटिंग्जवर जा"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"आपल्या प्रशासकाने अपडेट केले"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"आपल्या प्रशासकाने हटवले"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ओके"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"work app वर स्विच करायचे आहे का?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"तुमची संस्था तुम्हाला फक्त work app वरून कॉल करण्याची अनुमती देते"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"तुमची संस्था तुम्हाला फक्त work app वरून मेसेज पाठवण्याची अनुमती देते"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"वैयक्तिक ब्राउझर वापरा"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"कार्य ब्राउझर वापरा"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"कॉल करा"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ऑफिस ३"</string>
<string name="profile_label_test" msgid="9168641926186071947">"चाचणी"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"संवेदनशील नोटिफिकेशनचा आशय लपवलेला आहे"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रीन शेअर करताना सुरक्षेसाठी अॅपमधील आशय लपवला आहे"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"उपग्रहाशी आपोआप कनेक्ट केलेले आहे"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 904d9150..5e9ce27 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> selepas <xliff:g id="TIME_DELAY">{2}</xliff:g> saat"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak dimajukan"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak dimajukan"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Keselamatan rangkaian selular"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Semak tetapan"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Pengecam peranti diakses"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Rangkaian pada sambungan <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> merekodkan pengecam unik (IMSI) peranti anda <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> kali dalam tempoh antara <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> hingga <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Sambungan yang disulitkan pada <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Kini anda disambungkan kepada rangkaian selular yang lebih selamat."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Sambungan yang tidak disulitkan pada <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Anda disambungkan kepada rangkaian selular yang tidak disulitkan. Panggilan, mesej dan data anda terdedah kepada pintasan sekat."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Tetapan keselamatan selular"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Ketahui lebih lanjut"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kod ciri selesai."</string>
<string name="fcError" msgid="5325116502080221346">"Masalah sambungan atau kod ciri tidak sah."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil tangkapan skrin"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Boleh mengambil tangkapan skrin paparan."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Pratonton, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ketepikan"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"lumpuhkan atau ubah suai bar status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"jadi bar status"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Minta PIN sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Minta corak buka kunci sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Minta kata laluan sebelum menyahsemat"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Dipasang oleh pentadbir anda.\nAkses tetapan untuk melihat kebenaran yang diberikan"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Dikemas kini oleh pentadbir anda"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dipadamkan oleh pentadbir anda"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Beralih kepada apl kerja?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasi anda hanya membenarkan anda membuat panggilan daripada apl kerja"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasi anda hanya membenarkan anda menghantar mesej daripada apl kerja"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gunakan penyemak imbas peribadi"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gunakan penyemak imbas kerja"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Panggil"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Ujian"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Kandungan pemberitahuan yang sensitif disembunyikan"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Kandungan apl disembunyikan daripada perkongsian skrin untuk keselamatan"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Disambungkan secara automatik kepada satelit"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index e965f47..81a79cf 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> နောက် <xliff:g id="TIME_DELAY">{2}</xliff:g> စက္ကန့်"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ထပ်ဆင့်မပို့နိုင်ပါ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ထပ်ဆင့်မပို့နိုင်ပါ"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"ဆယ်လူလာ ကွန်ရက် လုံခြုံရေး"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ဆက်တင်များကို စိစစ်ရန်"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"စက်ပစ္စည်းသတ်မှတ်မှုစနစ်ကို ဝင်ကြည့်ထားသည်"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> နှင့် ချိတ်ဆက်ထားသော ကွန်ရက်တစ်ခုသည် သင့်စက်ပစ္စည်း၏ သီးသန့်သတ်မှတ်မှုစနစ် (IMSI) ကို <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> နှင့် <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> ကြား ကာလအတွင်း <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ကြိမ် မှတ်တမ်းတင်ထားသည်။"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> နှင့် ချိတ်ဆက်မှုကို အသွင်ဝှက်ထားသည်"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ပိုမိုလုံခြုံသော ဆယ်လူလာ ကွန်ရက်နှင့် ယခုချိတ်ဆက်ထားပါပြီ။"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> နှင့် ချိတ်ဆက်မှုကို အသွင်ဝှက်မထားပါ"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"အသွင်ဝှက်မထားသော ဆယ်လူလာ ကွန်ရက်ကို သင်ချိတ်ဆက်ထားသည်။ သင်၏ ခေါ်ဆိုမှု၊ မက်ဆေ့ဂျ်နှင့် ဒေတာများကို ကြားဖြတ်ယူခံရနိုင်ခြေရှိသည်။"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"ဆယ်လူလာလုံခြုံရေး ဆက်တင်များ"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ပိုမိုလေ့လာရန်"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"ပုံစံကုတ်ပြီးဆုံးသည်"</string>
<string name="fcError" msgid="5325116502080221346">"ဆက်သွယ်မှုဆိုင်ရာပြသနာ သို့မဟုတ် တရားမဝင်သောပုံစံကုတ်"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ပင်မဖြုတ်မီ လော့ခ်ဖွင့်ပုံစံကို မေးရန်"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"သင့်စီမံခန့်ခွဲသူက ထည့်သွင်းထားသည်။\nပေးထားသည့် ခွင့်ပြုချက်များကို ကြည့်ရန် ဆက်တင်များသို့ သွားပါ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"သင်၏ စီမံခန့်ခွဲသူက အပ်ဒိတ်လုပ်ထားသည်"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"သင်၏ စီမံခန့်ခွဲသူက ဖျက်လိုက်ပါပြီ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"အလုပ်သုံးအက်ပ်သို့ ပြောင်းမလား။"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"သင့်အဖွဲ့အစည်းသည် သင့်အား အလုပ်သုံးအက်ပ်များမှသာ ဖုန်းဆက်ခွင့်ပြုသည်"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"သင့်အဖွဲ့အစည်းသည် သင့်အား အလုပ်သုံးအက်ပ်များမှသာ မက်ဆေ့ဂျ်ပို့ခွင့်ပြုသည်"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ကိုယ်ပိုင်ဘရောင်ဇာ သုံးရန်"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"အလုပ်သုံးဘရောင်ဇာ သုံးရန်"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ဖုန်းဆက်ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index c6a2f44..efaae18 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> etter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderekoblet"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderekoblet"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Sikkerhet for mobilnettverk"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Gå gjennom innstillingene"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Enhetsidentifikatoren er brukt"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Et nettverk på <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>-tilkoblingen har registrert den unike identifikatoren til enheten (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ganger i perioden mellom <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> og <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Kryptert tilkobling til <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Nå er du koblet til et tryggere mobilnettverk."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Ikke-kryptert tilkobling til <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Du er koblet til et ikke-kryptert mobilnettverk. Anropene, meldingene og dataene dine er sårbare for å bli fanget opp."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Sikkerhetsinnstillinger for mobil"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Finn ut mer"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Funksjonskode utført."</string>
<string name="fcError" msgid="5325116502080221346">"Tilkoblingsproblem eller ugyldig funksjonskode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Krev PIN-kode for å løsne app"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Krev opplåsingsmønster for å løsne apper"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Krev passord for å løsne apper"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Installert av administratoren din.\nGå til innstillingene for å se hvilke tillatelser som er gitt"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Oppdatert av administratoren din"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet av administratoren din"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vil du bytte til en jobbapp?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasjonen din tillater bare at du ringer fra jobbapper"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasjonen din tillater bare at du sender meldinger fra jobbapper"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Bruk den personlige nettleseren"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Bruk jobbnettleseren"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ring"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 230e701..cce955f 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> पछि <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकेन्ड"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अगाडि बढाइएको छैन"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अगाडि बढाइएको छैन"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"मोबाइल नेटवर्कको सुरक्षा"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"सेटिङको समीक्षा गर्नुहोस्"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"डिभाइसको आइडेन्टिफायर एक्सेस गरियो"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> मा कनेक्ट गरिएको कुनै नेटवर्कले <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> र <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> बिचको अवधिमा तपाईंको डिभाइसको अद्वितीय आइडेन्टिफायर (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> पटक रेकर्ड गर्यो।"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> सँगको कनेक्सन इन्क्रिप्ट गरिएको छ"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"तपाईं अब अझ सुरक्षित मोबाइल नेटवर्कमा कनेक्ट हुनुभएको छ।"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> सँगको कनेक्सन इन्क्रिप्ट गरिएको छैन"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"तपाईं इन्क्रिप्ट नगरिएको मोबाइल नेटवर्कमा कनेक्ट हुनुहुन्छ। तपाईंका कल, म्यासेज र जानकारी इन्टरसेप्ट हुन सक्ने जोखिम छ।"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"मोबाइल नेटवर्कको सुरक्षासम्बन्धी सेटिङ"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"थप जान्नुहोस्"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"विशेषता कोड पुरा भयो।"</string>
<string name="fcError" msgid="5325116502080221346">"जडान समस्या वा अमान्य सुविधा कोड।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ठिक छ"</string>
@@ -830,14 +845,14 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रिन अनलक गर्न गरिएको प्रयासको अनुगमन गर्ने"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप भएको संख्या निरीक्षण गर्नुहोस् र यदि निकै धेरै गलत पासवर्डहरू टाइप भएका छन भने ट्याब्लेट लक गर्नुहोस् वा ट्याब्लेटका सबै डेटा मेट्नुहोस्।"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुराको रेकर्ड राख्नुहोस् र धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा ट्याबलेट लक गर्नुहोस् वा यसका सबै डेटा मेटाउनुहोस्।"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा डिभाइसमा भएको सम्पूर्ण डेटा मेटाउनुहोस्।"</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गर्नुहोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गर्नुहोस् वा यस इन्फोटेनमेन्ट प्रणालीका सबै डेटा मेटाउनुहोस्।"</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप भएको छ हेर्नुहोस् र निकै धेरै पटक गलत पासवर्ड टाइप भएको भने फोन लक गर्नुहोस् वा फोनका सबै डेटा मेट्नुहोस्।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा ट्याब्लेट लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुराको रेकर्ड राख्नुहोस् र धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा ट्याबलेट लक गर्नुहोस् वा प्रयोगकर्ताका सबै डेटा मेटाउनुहोस्।"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा यो प्रयोगकर्ताको सम्पूर्ण डेटा मेटाउनुहोस्।"</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गर्नुहोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गर्नुहोस् वा यस प्रोफाइलका सबै डेटा मेटाउनुहोस्।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा फोन लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुराको रेकर्ड राख्नुहोस् र धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा फोन लक गर्नुहोस् वा प्रयोगकर्ताका सबै डेटा मेटाउनुहोस्।"</string>
<string name="policylab_resetPassword" msgid="214556238645096520">"स्क्रिन लक परिवर्तन गर्ने"</string>
<string name="policydesc_resetPassword" msgid="4626419138439341851">"स्क्रिन लक परिवर्तन गर्नुहोस्।"</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"स्क्रिन लक गर्ने"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन गर्नुअघि PIN मागियोस्"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन गर्नअघि अनलक प्याटर्न माग्नुहोस्"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"यो प्याकेज तपाईंका एड्मिनले इन्स्टल गर्नुभएको हो।\nप्रदान गरिएका अनुमतिसम्बन्धी जानकारी हेर्न सेटिङमा जानुहोस्"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"तपाईंका प्रशासकले अद्यावधिक गर्नुभएको"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"तपाईंका प्रशासकले मेट्नुभएको"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ठिक छ"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"कामसम्बन्धी एप प्रयोग गर्ने हो?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र कल गर्ने अनुमति दिएको छ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र म्यासेज पठाउने अनुमति दिएको छ"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"व्यक्तिगत ब्राउजर प्रयोग गर्नुहोस्"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"कार्य ब्राउजर प्रयोग गर्नुहोस्"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"कल गर्नुहोस्"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"कार्य प्रोफाइल ३"</string>
<string name="profile_label_test" msgid="9168641926186071947">"परीक्षण"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"संवेदनशील सूचनासम्बन्धी सामग्री लुकाइएको छ"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रिन सेयर गर्दा सुरक्षाका लागि एपमा भएको सामग्री लुकाइएको छ"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"स्याटलाइटमा स्वतः कनेक्ट गरियो"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5de3287..40744589 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> seconden"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: niet doorgeschakeld"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: niet doorgeschakeld"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Beveiliging van mobiele netwerken"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Instellingen checken"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Toegang gehad tot apparaat-ID"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Een netwerk op de <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>-verbinding heeft de unieke ID van je apparaat (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> keer geregistreerd in de periode tussen <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> en <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Verbinding met <xliff:g id="NETWORK_NAME">%1$s</xliff:g> versleuteld"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Je bent nu verbonden met beter beveiligd mobiel netwerk."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Niet-versleutelde verbinding met <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Je bent verbonden met een niet-versleuteld mobiel netwerk. Je gesprekken, berichten en gegevens zijn kwetsbaar voor onderschepping."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobiele beveiligingsinstellingen"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Meer informatie"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Functiecode voltooid."</string>
<string name="fcError" msgid="5325116502080221346">"Verbindingsprobleem of ongeldige functiecode."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Voorbeeld, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"sluiten"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitzetten of wijzigen"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitzetten of systeemiconen toevoegen en verwijderen."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vraag pin voor losmaken"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ontgrendelingspatroon vragen om app los te maken"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vraag wachtwoord voor losmaken"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Geïnstalleerd door je beheerder.\nGa naar instellingen om verleende rechten te bekijken."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Geüpdatet door je beheerder"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Verwijderd door je beheerder"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Overschakelen naar werk-app?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Je organisatie staat je alleen toe om te bellen vanuit werk-apps"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Je organisatie staat je alleen toe om berichten te sturen vanuit werk-apps"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Persoonlijke browser gebruiken"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Werkbrowser gebruiken"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Bellen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 6f186ff..3ffc5b9 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ସେକେଣ୍ଡ ପରେ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫରୱାର୍ଡ କରାଯାଇନାହିଁ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫର୍ୱର୍ଡ କରାଗଲା ନାହିଁ"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"ସେଲୁଲାର ନେଟୱାର୍କ ସୁରକ୍ଷା"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ସେଟିଂସର ସମୀକ୍ଷା କରନ୍ତୁ"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ଡିଭାଇସ ଚିହ୍ନଟକାରୀକୁ ଆକ୍ସେସ କରାଯାଇଛି"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> କନେକ୍ସନରେ ଥିବା ଏକ ନେଟୱାର୍କ <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ଏବଂ <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> ମଧ୍ୟରେ ଥିବା ଅବଧିରେ <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ଥର ଆପଣଙ୍କ ଡିଭାଇସର ସ୍ୱତନ୍ତ୍ର ଚିହ୍ନଟକାରୀ (IMSI)କୁ ରେକର୍ଡ କରିଛି।"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ସହ ଏନକ୍ରିପ୍ଟ କରାଯାଇଥିବା କନେକ୍ସନ"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ଆପଣ ବର୍ତ୍ତମାନ ଅଧିକ ସୁରକ୍ଷିତ ଏକ ସେଲୁଲାର ନେଟୱାର୍କ ସହ କନେକ୍ଟ ଅଛନ୍ତି।"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ସହ ଅଣ-ଏନକ୍ରିପ୍ଟ କରାଯାଇଥିବା କନେକ୍ସନ"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"ଆପଣ ଏକ ଅଣ-ଏନକ୍ରିପ୍ଟ କରାଯାଇଥିବା ସେଲୁଲାର ନେଟୱାର୍କ ସହ କନେକ୍ଟ ଅଛନ୍ତି। ଆପଣଙ୍କ କଲ, ମେସେଜ ଏବଂ ଡାଟା ଇଣ୍ଟରସେପସନ ପାଇଁ ଅସୁରକ୍ଷିତ ଅଟେ।"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"ସେଲୁଲାର ସୁରକ୍ଷା ସେଟିଂସ"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"ଫିଚର୍ କୋଡ୍ ସମ୍ପୂର୍ଣ୍ଣ।"</string>
<string name="fcError" msgid="5325116502080221346">"ସଂଯୋଗରେ ସମସ୍ୟା କିମ୍ୱା ଅମାନ୍ୟ ଫିଚର୍ କୋଡ୍।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ଠିକ ଅଛି"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ସ୍କ୍ରିନସଟ୍ ନିଅନ୍ତୁ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ଡିସପ୍ଲେର ଏକ ସ୍କ୍ରିନସଟ୍ ନିଆଯାଇପାରେ।"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"ପ୍ରିଭ୍ୟୁ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ଖାରଜ କରନ୍ତୁ"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ଷ୍ଟାଟସ୍ ବାର୍କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ଆପ୍କୁ, ସ୍ଥିତି ବାର୍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍ ଆଇକନ୍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ଷ୍ଟାଟସ୍ ବାର୍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
@@ -830,7 +844,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"ପାସ୍ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ଲକ୍ ସ୍କ୍ରୀନ୍ ପାସ୍ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"ସ୍କ୍ରିନ-ଅନଲକ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରିବା"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟ୍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ ହୋଇଥିବା ଭୁଲ ପାସୱାର୍ଡ ସଂଖ୍ୟା ମନିଟର କରେ ଏବଂ ଟାବଲେଟକୁ ଲକ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟର ସବୁ ଡାଟା ଖାଲି ହୋଇଯାଏ।"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ସ୍କ୍ରିନ୍ ଅନ୍ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍ର ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ମନିଟର କରନ୍ତୁ ଏବଂ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମକୁ ଲକ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ସମସ୍ତ ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ଫୋନ ଅନଲକ କରିବା ବେଳେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରିବା ଏବଂ ଯଦି ଏକାଧିକ ଥର ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଫୋନକୁ ଲକ କରିବା ବା ଫୋନର ସମସ୍ତ ଡାଟା ଇରେଜ କରିବା।"</string>
@@ -843,7 +857,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"ସ୍କ୍ରିନ୍ ଲକ୍ କରିବା"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"ସ୍କ୍ରିନ୍ କିପରି ଓ କେତେବେଳେ ଲକ୍ କରାଯିବ, ତାହା ନିୟନ୍ତ୍ରଣ କରେ।"</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"ସମସ୍ତ ଡାଟା ଖାଲି କରିବା"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଟାବ୍ଲେଟ୍ର ଡାଟା ଲିଭାଇଥାଏ।"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ଫେକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ବିନା ଚେତାବନୀରେ ଟାବଲେଟର ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ବିନା ଚେତାବନୀରେ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ର ଡାଟା ଲିଭାନ୍ତୁ।"</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ବିନା ଚେତାବନୀରେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ବିନା ଚେତାବନୀରେ ଫେକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ଫୋନର ଡାଟା ଇରେଜ କରିବା।"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ଅନପିନ୍ କରିବା ପୂର୍ବରୁ PIN ପଚାରନ୍ତୁ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ଅନପିନ୍ କରିବା ପୂର୍ବରୁ ଲକ୍ ଖୋଲିବା ପାଟର୍ନ ପଚାରନ୍ତୁ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ଅନପିନ୍ କରିବା ପୂର୍ବରୁ ପାସ୍ୱର୍ଡ ପଚାରନ୍ତୁ"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଇନଷ୍ଟଲ କରାଯାଇଛି।\nଅନୁମୋଦିତ ଅମୁମତିଗୁଡ଼ିକ ଭ୍ୟୁ କରିବା ପାଇଁ ସେଟିଂସକୁ ଯାଆନ୍ତୁ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"ଆପଣଙ୍କ ଆଡମିନ୍ ଅପଡେଟ୍ କରିଛନ୍ତି"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ଆପଣଙ୍କ ଆଡମିନ୍ ଡିଲିଟ୍ କରିଛନ୍ତି"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ଠିକ ଅଛି"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ୱାର୍କ ଆପକୁ ସୁଇଚ କରିବେ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ଆପଣଙ୍କ ସଂସ୍ଥା ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ଆପ୍ସରୁ କଲ କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ଆପଣଙ୍କ ସଂସ୍ଥା ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ଆପ୍ସରୁ ମେସେଜ ପଠାଇବା ପାଇଁ ଅନୁମତି ଦିଏ"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ବ୍ୟକ୍ତିଗତ ବ୍ରାଉଜର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ୱାର୍କ ବ୍ରାଉଜର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"କଲ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 7f83ddb..42a229e 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ਸਕਿੰਟਾਂ ਬਾਅਦ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ਅੱਗੇ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ਅੱਗੇ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"ਸੈਲਿਊਲਰ ਨੈੱਟਵਰਕ ਸੁਰੱਖਿਆ"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ਸੈਟਿੰਗਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰੋ"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"ਡੀਵਾਈਸ ਪਛਾਣਕਰਤਾ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ ਗਈ"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ਕਨੈਕਸ਼ਨ ਵਾਲੇ ਨੈੱਟਵਰਕ ਨੇ <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ਅਤੇ <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> ਦੇ ਵਿਚਕਾਰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਵਿਲੱਖਣ ਪਛਾਣ (IMSI) ਨੂੰ <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ਵਾਰ ਰਿਕਾਰਡ ਕੀਤਾ।"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ਦੇ ਨਾਲ ਇਨਕ੍ਰਿਪਟਡ ਕਨੈਕਸ਼ਨ"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ਤੁਸੀਂ ਹੁਣ ਇੱਕ ਵਧੇਰੇ ਸੁਰੱਖਿਅਤ ਸੈਲਿਊਲਰ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੋ।"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ਦੇ ਨਾਲ ਗੈਰ-ਇਨਕ੍ਰਿਪਟਡ ਕਨੈਕਸ਼ਨ"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"ਤੁਸੀਂ ਕਿਸੇ ਗੈਰ-ਇਨਕ੍ਰਿਪਟਡ ਸੈਲਿਊਲਰ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੋ। ਤੁਹਾਡੀਆਂ ਕਾਲਾਂ, ਸੁਨੇਹੇ ਅਤੇ ਡਾਟੇ ਵਿੱਚ ਰੁਕਾਵਟ ਪੈਣ ਦਾ ਖਤਰਾ ਹੈ।"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"ਸੈਲਿਊਲਰ ਸੁਰੱਖਿਆ ਸੈਟਿੰਗਾਂ"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ਹੋਰ ਜਾਣੋ"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"ਵਿਸ਼ੇਸ਼ਤਾ ਕੋਡ ਪੂਰਾ।"</string>
<string name="fcError" msgid="5325116502080221346">"ਕਨੈਕਸ਼ਨ ਸਮੱਸਿਆ ਜਾਂ ਅਵੈਧ ਵਿਸ਼ੇਸ਼ਤਾ ਕੋਡ।"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ਠੀਕ ਹੈ"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ਡਿਸਪਲੇ ਦਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈ ਸਕਦੀ ਹੈ।"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"ਪੂਰਵ-ਝਲਕ ਦੇਖੋ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ਖਾਰਜ ਕਰੋ"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਿੰਨ ਮੰਗੋ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਣਲਾਕ ਪੈਟਰਨ ਵਾਸਤੇ ਪੁੱਛੋ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ਅਣਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤਾ ਗਿਆ।\nਦਿੱਤੀਆਂ ਗਈਆਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਮਿਟਾਇਆ ਗਿਆ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ਠੀਕ ਹੈ"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ਕੀ ਕੰਮ ਸੰਬੰਧੀ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰਨਾ ਹੈ?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਕਾਲਾਂ ਕਰਨ ਦਿੰਦੀ ਹੈ"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਹੀ ਸੁਨੇਹੇ ਭੇਜਣ ਦਿੰਦੀ ਹੈ"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ਨਿੱਜੀ ਬ੍ਰਾਊਜ਼ਰ ਵਰਤੋ"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ਕੰਮ ਸੰਬੰਧੀ ਬ੍ਰਾਊਜ਼ਰ ਵਰਤੋ"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"ਕਾਲ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a6937d2..2dccba9 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundach"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nieprzekierowane"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nieprzekierowane"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Zabezpieczenia sieci komórkowej"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Sprawdź ustawienia"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Uzyskano dostęp do identyfikatora urządzenia"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Sieć <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>, z którą masz połączenie, zarejestrowała jednoznaczny identyfikator Twojego urządzenia (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> razy w okresie od <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> do <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Szyfrowane połączenie z siecią <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Korzystasz z połączenia z bezpieczniejszą siecią komórkową."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nieszyfrowane połączenie z siecią <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Korzystasz z nieszyfrowanego połączenia z siecią komórkową. Twoje połączenia, wiadomości i dane są narażone na przechwycenie."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Ustawienia bezpieczeństwa sieci komórkowej"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Więcej informacji"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Wykonano kod funkcji."</string>
<string name="fcError" msgid="5325116502080221346">"Problem z połączeniem lub nieprawidłowy kod funkcji."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -832,7 +847,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Określ reguły hasła"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorowanie prób odblokowania ekranu"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Przy odblokowywaniu ekranu monitoruj, ile razy wpisano nieprawidłowe hasło i blokuj tablet lub usuń z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło i blokuje tablet lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitorowanie liczby nieudanych prób odblokowania ekranu za pomocą hasła oraz blokowanie urządzenia z Androidem TV lub kasowanie z niego wszystkich danych w razie wpisania błędnego hasła zbyt wiele razy."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorowanie przypadków nieprawidłowego wpisania hasła podczas odblokowywania ekranu i blokowanie systemu multimedialno-rozrywkowego lub usuwanie z niego wszystkich danych przy zbyt dużej liczbie błędnych prób."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło, i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
@@ -1267,7 +1282,7 @@
<string name="screen_compat_mode_scale" msgid="8627359598437527726">"Skala"</string>
<string name="screen_compat_mode_show" msgid="5080361367584709857">"Zawsze pokazuj"</string>
<string name="screen_compat_mode_hint" msgid="4032272159093750908">"Włącz ponownie, wybierając Ustawienia systemu > Aplikacje > Pobrane."</string>
- <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje obecnie ustawionego rozmiaru wyświetlacza i może działać niestabilnie."</string>
+ <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje obecnie ustawionego rozmiaru wyświetlanych elementów i może działać niestabilnie."</string>
<string name="unsupported_display_size_show" msgid="980129850974919375">"Zawsze pokazuj"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> została skompilowana pod niezgodną wersję systemu Android i może zachowywać się niezgodnie z oczekiwaniami. Sprawdź, czy jest dostępna zaktualizowana wersja aplikacji."</string>
<string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"Zawsze pokazuj"</string>
@@ -1900,8 +1915,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Podaj PIN, aby odpiąć"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Aby odpiąć, poproś o wzór odblokowania"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Aby odpiąć, poproś o hasło"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Zainstalowany przez administratora.\nOtwórz ustawienia, aby wyświetlić przyznane uprawnienia"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Zaktualizowany przez administratora"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Usunięty przez administratora"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2219,6 +2233,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Przełączyć na aplikację służbową?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Twoja organizacja zezwala na nawiązywanie połączeń tylko z aplikacji służbowych"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Twoja organizacja zezwala na wysyłanie wiadomości tylko z aplikacji służbowych"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Użyj przeglądarki osobistej"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Użyj przeglądarki służbowej"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Zadzwoń"</string>
@@ -2398,8 +2416,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Służbowy 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Testowy"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Wspólny"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Treść poufnego powiadomienia została ukryta"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Ze względów bezpieczeństwa zawartość aplikacji jest niewidoczna podczas udostępniania ekranu"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automatycznie połączono z satelitą"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index d0dcc33..8a03716 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Segurança da rede celular"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Revisar configurações"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Identificador do dispositivo acessado"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Uma rede na conexão <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> gravou o identificador exclusivo (IMSI) do seu dispositivo <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> vezes no período entre <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> e <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Conexão criptografada com <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Você se conectou a uma rede celular mais segura."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Conexão não criptografada com <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Você se conectou a uma rede celular não criptografada. Suas ligações, mensagens e dados estão vulneráveis a interceptação."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Configurações de segurança da rede celular"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saiba mais"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Código de recurso concluído."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexão ou código de recurso inválido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -844,7 +859,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear a tela"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Controla como e quando a tela é bloqueada."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Apagar todos os dados"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apague os dados do tablet sem aviso redefinindo a configuração original."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apaga os dados do tablet sem aviso redefinindo a configuração original."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Redefine o dispositivo Android TV para a configuração original e apaga os dados sem aviso."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apaga os dados sem aviso, redefinindo o sistema de infoentretenimento para a configuração original."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados sem aviso redefinindo o smartphone para a configuração original."</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalado pelo administrador.\nAcesse as configurações para conferir as permissões concedidas"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atualizado pelo seu administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Excluído pelo seu administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Trocar para o app de trabalho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Sua organização só permite o envio de mensagens usando apps de trabalho"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 4772ff8..5b130bc 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não reencaminhado"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não reencaminhado"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Segurança da rede móvel"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Reveja as definições"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Identificador do dispositivo acedido"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Uma rede na ligação <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> registou o identificador único (IMSI) do seu dispositivo <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> vezes no período entre a(s) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> e a(s) <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Ligação encriptada a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"O dispositivo está agora ligado a uma rede móvel mais segura."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Ligação não encriptada à rede <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"O dispositivo está ligado a uma rede móvel não encriptada. As suas chamadas, mensagens e dados estão vulneráveis a uma interceção."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Definições de segurança da rede móvel"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saber mais"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Código de funcionalidade completo."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de ligação ou código de funcionalidade inválido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -357,8 +372,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer captura de ecrã"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"É possível tirar uma captura de ecrã."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Pré-visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ignorar"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite à app desativar a barra de estado ou adicionar e remover ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser apresentada na barra de estado"</string>
@@ -838,7 +852,7 @@
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o tablet ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o dispositivo Android TV ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitorize o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloqueie o sistema de infoentretenimento ou apague todos os dados deste utilizador, se forem introduzidas demasiadas palavras-passe incorretas."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o telemóvel ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã, e bloquear o telemóvel ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
<string name="policylab_resetPassword" msgid="214556238645096520">"Alterar o bloqueio de ecrã"</string>
<string name="policydesc_resetPassword" msgid="4626419138439341851">"Altera o bloqueio de ecrã."</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear o ecrã"</string>
@@ -1899,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de soltar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir palavra-passe antes de soltar"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalado pelo seu administrador.\nAceda às definições para ver as autorizações concedidas"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atualizado pelo seu gestor"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado pelo seu gestor"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2218,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Mudar para a app de trabalho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"A sua organização só lhe permite fazer chamadas a partir de apps de trabalho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"A sua organização só lhe permite enviar mensagens a partir de apps de trabalho"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador pessoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabalho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d0dcc33..8a03716 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Segurança da rede celular"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Revisar configurações"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Identificador do dispositivo acessado"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Uma rede na conexão <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> gravou o identificador exclusivo (IMSI) do seu dispositivo <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> vezes no período entre <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> e <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Conexão criptografada com <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Você se conectou a uma rede celular mais segura."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Conexão não criptografada com <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Você se conectou a uma rede celular não criptografada. Suas ligações, mensagens e dados estão vulneráveis a interceptação."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Configurações de segurança da rede celular"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Saiba mais"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Código de recurso concluído."</string>
<string name="fcError" msgid="5325116502080221346">"Problema de conexão ou código de recurso inválido."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -844,7 +859,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear a tela"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Controla como e quando a tela é bloqueada."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Apagar todos os dados"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apague os dados do tablet sem aviso redefinindo a configuração original."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apaga os dados do tablet sem aviso redefinindo a configuração original."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Redefine o dispositivo Android TV para a configuração original e apaga os dados sem aviso."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apaga os dados sem aviso, redefinindo o sistema de infoentretenimento para a configuração original."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados sem aviso redefinindo o smartphone para a configuração original."</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalado pelo administrador.\nAcesse as configurações para conferir as permissões concedidas"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atualizado pelo seu administrador"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Excluído pelo seu administrador"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Trocar para o app de trabalho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Sua organização só permite o envio de mensagens usando apps de trabalho"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0a31bf8..ac33fa1 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> după <xliff:g id="TIME_DELAY">{2}</xliff:g> secunde"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționat"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționat"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Securitatea rețelei de date mobile"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Examinează setările"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"A fost accesat identificatorul dispozitivului"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"O rețea conectată la <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> a înregistrat identificatorul unic (IMSI) al dispozitivului tău de <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ori în intervalul <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> – <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Conexiune criptată la <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Te-ai conectat la o rețea de date mobile mai sigură."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Conexiune necriptată la <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Te-ai conectat la o rețea de date mobile necriptată. Apelurile, mesajele și datele tale ar putea fi interceptate."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Setările de securitate a rețelei de date mobile"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Află mai multe"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Cod de funcție complet."</string>
<string name="fcError" msgid="5325116502080221346">"Problemă de conectare sau cod de funcție nevalid."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1899,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicită codul PIN înainte de a anula fixarea"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicită mai întâi modelul pentru deblocare"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicită parola înainte de a anula fixarea"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalat de administrator.\nAccesează setările ca să vezi permisiunile acordate."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizat de administrator"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Șters de administrator"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2218,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Comuți la aplicația pentru lucru?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organizația îți permite să inițiezi apeluri numai din aplicațiile pentru lucru"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizația îți permite să trimiți mesaje numai din aplicațiile pentru lucru"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Folosește browserul personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Folosește browserul de serviciu"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Apelează"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 1ae0499..63992d6 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> через <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не переадресовано"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не переадресовано"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Безопасность мобильной сети"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Проверить настройки"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Зарегистрирован доступ к идентификатору устройства"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Сеть (подключение <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>) записывала номер IMSI вашего устройства несколько раз (всего <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>) в период с <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> до <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Зашифрованное подключение к сети \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Сейчас вы подключены к более безопасной мобильной сети."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Незашифрованное подключение к сети \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\""</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Вы подключены к незашифрованной мобильной сети. Ваши звонки, сообщения и данные уязвимы для перехвата."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Настройки безопасности мобильной сети"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Подробнее"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Код функции выполнен."</string>
<string name="fcError" msgid="5325116502080221346">"Неполадки подключения или неверный код функции."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ОК"</string>
@@ -1900,8 +1915,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запрашивать PIN-код"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запрашивать графический ключ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запрашивать пароль"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Установлено администратором.\nЧтобы посмотреть предоставленные разрешения, перейдите в настройки."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Обновлено администратором"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Удалено администратором"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
@@ -2219,6 +2233,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Перейти в рабочее приложение?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"В вашей организации разрешено звонить только из рабочих приложений."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"В вашей организации разрешено отправлять сообщения только из рабочих приложений."</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Использовать личный браузер"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Использовать рабочий браузер"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Позвонить"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index ee0cda2..764b051 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: තත්පර <xliff:g id="TIME_DELAY">{2}</xliff:g> ට පසුව <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ඉදිරියට නොයවන ලදි"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ඉදිරියට නොයවන ලදි"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"සෙලියුලර් ජාල ආරක්ෂාව"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"සැකසීම් සමාලෝචනය කරන්න"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"උපාංග හැඳුනුම්කාරකයට ප්රවේශ විය"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> සම්බන්ධතාවය මත ජාලයක් <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> සහ <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> අතර කාලසීමාව තුළ වාර <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>ක් ඔබේ උපාංගයේ අනන්ය හැඳුනුම්කාරකය (IMSI) වාර්තා කර ඇත."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> වෙත සංකේතනය කළ සම්බන්ධතාවය"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ඔබ දැන් වඩාත් සුරක්ෂිත සෙලියුලර් ජාලයකට සම්බන්ධ වී ඇත."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> වෙත සංකේතනය නොකළ සම්බන්ධතාවය"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"ඔබ සංකේතනය නොකළ සෙලියුලර් ජාලයකට සම්බන්ධ වී ඇත. ඔබේ ඇමතුම්, පණිවිඩ, සහ දත්ත බාධා කිරීම් වලට ගොදුරු විය හැක."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"සෙලියුලර් ආරක්ෂක සැකසීම්"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"තව දැන ගන්න"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"අංග කේතය සම්පූර්ණයි."</string>
<string name="fcError" msgid="5325116502080221346">"සම්බන්ධතා ගැටළුවක් හෝ අවලංගු විශේෂාංග කේතයකි."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"හරි"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ගැලවීමට පෙර PIN විමසන්න"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"ඔබේ පරිපාලකයා විසින් ස්ථාපන කරනු ලබයි.\nදෙන ලද අවසර බැලීමට සැකසීම් වෙත යන්න"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"ඔබගේ පරිපාලක මඟින් යාවත්කාලීන කර ඇත"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ඔබගේ පරිපාලක මඟින් මකා දමා ඇත"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"හරි"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"කාර්යාල යෙදුම වෙත මාරු වන්නද?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"ඔබේ සංවිධානය ඔබට කාර්යාල යෙදුම්වලින් ඇමතුම් කිරීමට පමණක් ඉඩ දෙයි"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"ඔබේ සංවිධානය ඔබට කාර්යාල යෙදුම්වලින් පණිවුඩ යැවීමට පමණක් ඉඩ දෙයි"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"පුද්ගලික බ්රව්සරය භාවිත කරන්න"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"කාර්යාල බ්රව්සරය භාවිත කරන්න"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"අමතන්න"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"කාර්යාලය 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"පරීක්ෂණය"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"වාර්ගික"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"සංවේදී දැනුම්දීම් අන්තර්ගතය සැඟවී ඇත"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ආරක්ෂාව සඳහා යෙදුම් අන්තර්ගතය තිරය බෙදා ගැනීමෙන් සඟවා ඇත"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"චන්ද්රිකාවට ස්වයංක්රීයව සම්බන්ධ වේ"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3058de5..35b1760 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepresmerované"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepresmerované"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Zabezpečenie mobilnej siete"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Kontrola nastavení"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Prístup k identifikátoru zariadenia"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Sieť v rámci pripojenia <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> zaznamenala v období od <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> do <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> jedinečný identifikátor (IMSI) vášho zariadenia <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>-krát."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifrované pripojenie k sieti <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Teraz využívate pripojenie k lepšie zabezpečenej mobilnej sieti."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifrované pripojenie k sieti <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Využívate pripojenie k nešifrovanej mobilnej sieti. Vaše hovory, správy aj údaje sú nedostatočne zabezpečené voči zachyteniu."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Nastavenia zabezpečenia v mobilnej sieti"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Ďalšie informácie"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Požiadavka zadaná pomocou kódu funkcie bola úspešne dokončená."</string>
<string name="fcError" msgid="5325116502080221346">"Problém s pripojením alebo neplatný kód funkcie."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1900,8 +1915,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pred odopnutím požiadať o číslo PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odopnutím požiadať o heslo"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Nainštaloval správca.\nAk si chcete zobraziť udelené povolenia, prejdite do nastavení."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Aktualizoval správca"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Odstránil správca"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2219,6 +2233,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Chcete prepnúť na pracovnú aplikáciu?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizácia vám povoľuje volať iba z pracovných aplikácií"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizácia vám povoľuje posielať správy iba z pracovných aplikácií"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Použiť osobný prehliadač"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Použiť pracovný prehliadač"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Volať"</string>
@@ -2398,8 +2416,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"3. pracovný"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Testovací"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Spoločný"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Obsah citlivého upozornenia je skrytý"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Obsah aplikácie bol na účely zabezpečenia skrytý v zdieľaní obrazovky"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Automaticky pripojené k satelitu"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0215c39..f80b5aa 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po toliko sekundah: <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Varnost mobilnega omrežja"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Pregled nastavitev"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Dostop do identifikatorja naprave"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Omrežje na povezavi <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> je <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>-krat zabeležilo enolični identifikator (IMSI) vaše naprave v obdobju od <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> do <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Šifrirana povezava z omrežjem <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Zdaj ste povezani z varnejšim mobilnim omrežjem."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Nešifrirana povezava z omrežjem <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Povezani ste z nešifriranim mobilnim omrežjem. Vaši klici, sporočila in podatki so ranljivi za prestrezanje."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Varnostne nastavitve mobilnega omrežja"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Več o tem"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Koda funkcije je dokončana."</string>
<string name="fcError" msgid="5325116502080221346">"Težava s povezavo ali neveljavna koda funkcije."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"V redu"</string>
@@ -358,8 +373,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ustvarjanje posnetka zaslona"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Lahko naredi posnetek zaslona."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Predogled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"opustitev"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogočanje ali spreminjanje vrstice stanja"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"postane vrstica stanja"</string>
@@ -1900,8 +1914,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zahtevaj PIN pred odpenjanjem"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odpenjanjem vprašaj za geslo"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Namestil skrbnik.\nV nastavitvah si oglejte odobrena dovoljenja."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Posodobil skrbnik"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisal skrbnik"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string>
@@ -2219,6 +2232,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite preklopiti na delovno aplikacijo?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organizacija vam omogoča klicanje samo iz delovnih aplikacij."</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizacija vam omogoča pošiljanje sporočil samo iz delovnih aplikacij."</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Uporabi osebni brskalnik"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Uporabi delovni brskalnik"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Pokliči"</string>
@@ -2398,8 +2415,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Delo 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Preizkus"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Skupno"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Občutljiva vsebina obvestila je bila skrita"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Pri deljenju zaslona je vsebina aplikacije skrita zaradi varnosti"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Samodejno vzpostavljena povezava s satelitom"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 1f42949..9f9907a4 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pas <xliff:g id="TIME_DELAY">{2}</xliff:g> sekondash"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nuk u transferua"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nuk u transferua"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Siguria e rrjetit celular"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Rishiko cilësimet"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Ka pasur qasje tek identifikuesi i pajisjes"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Një rrjet në lidhjen <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> regjistroi identifikuesin unik të pajisjes sate (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> herë në periudhën nga <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> deri në <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Lidhje e enkriptuar me <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Tani je lidhur me një rrjet celular më të sigurt."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Lidhje e paenkriptuar me <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Je lidhur me një rrjet celular të paenkriptuar. Telefonatat, mesazhet dhe të dhënat e tua mund të preken nga ndërhyrjet."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Cilësimet e sigurisë së rrjetit celular"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Mëso më shumë"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kodi i funksionit është i plotë."</string>
<string name="fcError" msgid="5325116502080221346">"Problem me lidhjen ose kod është i pavlefshëm."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Në rregull"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zhgozhdimi kërkon PIN-in"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Kërko motivin e shkyçjes para heqjes së gozhdimit"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Instaluar nga administratori.\nShko te cilësimet për të shikuar lejet e dhëna"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Përditësuar nga administratori"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Fshirë nga administratori"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Në rregull"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Të kalohet tek aplikacioni i punës?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organizata jote të lejon që të telefonosh vetëm nga aplikacionet e punës"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizata jote të lejon që të dërgosh mesazhe vetëm nga aplikacionet e punës"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Përdor shfletuesin personal"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Përdor shfletuesin e punës"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Telefono"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6768e29..c67819a 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -154,16 +154,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> након <xliff:g id="TIME_DELAY">{2}</xliff:g> секунде/и"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Безбедност мобилне мреже"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Прегледајте подешавања"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Приступљено је идентификатору уређаја"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Мрежа на <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> вези је забележила јединствени идентификатор (IMSI) уређаја <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> пут/а у периоду од <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> до <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Шифрована веза са: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Повезани сте на безбеднију мобилну мрежу."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Нешифрована веза са: <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Повезани сте на мобилну мрежу која није шифрована. Позиви, поруке и подаци су подложни пресретању."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Подешавања безбедности мобилне мреже"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Сазнајте више"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Кôд функције је извршен."</string>
<string name="fcError" msgid="5325116502080221346">"Проблеми са везом или неважећи кôд функције."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Потврди"</string>
@@ -357,8 +372,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Направи снимак екрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да направи снимак екрана."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"одбаци"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"онемогућавање или измена статусне траке"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"функционисање као статусна трака"</string>
@@ -1899,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Тражи PIN пре откачињања"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Тражи шаблон за откључавање пре откачињања"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тражи лозинку пре откачињања"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Инсталирао је администратор.\nИдите у подешавања да бисте видели одобрене дозволе"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирао је администратор"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Избрисао је администратор"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Потврди"</string>
@@ -2218,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Желите да пребаците на пословну апликацију?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша организација дозвољава позивање само из пословних апликација"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша организација дозвољава слање порука само из пословних апликација"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Користи лични прегледач"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Користи пословни прегледач"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Позови"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index fb0caa9..01b30d2 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Vidarebefordras inte"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Vidarebefordras inte"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Säkerhet för mobilnätverk"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Granska inställningarna"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Enhetsidentifierare har registrerats"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Ett nätverk anslutet till <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> registrerade din enhets unika identifierare (IMSI) <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> gånger mellan <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> och <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Krypterad anslutning till <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Nu är du ansluten till ett säkrare mobilnätverk."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Okrypterad anslutning till <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Du är ansluten till ett okrypterat mobilnätverk. Det finns risk för obehörig åtkomst till dina samtal, dina meddelanden och din data."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Säkerhetsinställningar för mobilnätverk"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Läs mer"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Funktionskoden är fullständig."</string>
<string name="fcError" msgid="5325116502080221346">"Anslutningsproblem eller ogiltig funktionskod."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Be om pinkod innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Be om lösenord innan skärmen slutar fästas"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Har installerats av administratören.\nÖppna inställningarna för att se behörigheter som beviljats"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administratören uppdaterade paketet"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratören raderade paketet"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vill du byta till jobbappen?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Organisationen tillåter endast att du ringer samtal med jobbappar"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisationen tillåter endast att du skickar meddelanden med jobbappar"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Använd privat webbläsare"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Använd jobbwebbläsare"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Ring"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 89ded88..df30800 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> baada ya sekunde <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Haijasambazwa"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Haijatumiwa mwingine"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Usalama wa mtandao wa simu"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Kagua mipangilio"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Kitambulishi cha kifaa kimefikiwa"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Mtandao fulani katika muunganisho wa <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> umerekodi kitambulishi cha kipekee (IMSI) cha kifaa chako mara <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> katika kipindi cha kati ya <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> na <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Muunganisho uliosimbwa kwa njia fiche kwenye <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Umeunganishwa sasa na mtandao salama zaidi wa simu."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Muunganisho usiosimbwa kwa njia fiche kwenye <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Umeunganishwa na mtandao wa simu usiosimbwa kwa njia fiche. Simu, ujumbe na data yako ziko katika hatari ya kuvamiwa."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mipangilio ya usalama wa mtandao wa simu"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Pata maelezo zaidi"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Msimbo wa kipengele umekamilika."</string>
<string name="fcError" msgid="5325116502080221346">"Tatizo la muunganisho au msimbo batili wa kipengele."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Sawa"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Piga picha ya skrini"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Inaweza kupiga picha ya skrini ya onyesho."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Onyesho la kukagua, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ondoa"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zima au rekebisha mwambaa hali"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa aikoni za mfumo."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"kuwa sehemu ya arifa"</string>
@@ -830,7 +844,7 @@
<string name="policylab_limitPassword" msgid="4851829918814422199">"Kuweka kanuni za nenosiri"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Dhibiti urefu na maandishi yanayokubalika katika nenosiri la kufunga skrini na PIN."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga kompyuta kibao au kufuta data yote iliyomo kama manenosiri mengi yasiyo sahihi yataingizwa."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Fuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga kishikwambi au kufuta data yote iliyomo ikiwa manenosiri mengi yasiyo sahihi yataingizwa."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Fuatilia idadi ya manenosiri yasiyo sahihi yanayowekwa wakati wa kufungua skrini na ufunge kifaa chako cha Android TV au ufute data yake yote ikiwa mtumiaji ataweka manenosiri mengi mno yasiyo sahihi."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Fuatilia idadi ya manenosiri yasiyo sahihi yanayowekwa wakati wa kufungua skrini, na ufunge mfumo wa burudani na habari au ufute data yote kwenye mfumo wa burudani na habari ikiwa manenosiri mengi mno yasiyo sahihi yatawekwa."</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga simu au kufuta data yote iliyomo kama manenosiri mengi sana yasiyo sahihi yataingizwa."</string>
@@ -843,7 +857,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"Kufunga skrini"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Kudhibiti jinsi na wakati skrini inapofunga."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"Kufuta data yote"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Futa data ya kompyuta kibao bila ilani kwa kurejesha mipangilio ambayo kompyuta ilitoka nayo kiwandani."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Futa data ya kishikwambi bila ilani kwa kurejesha mipangilio ambayo ilitoka nayo kiwandani."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Futa data ya kifaa chako cha Android TV bila onyo kwa kurejesha data kiliyotoka nayo kiwandani."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Futa data ya mfumo wa burudani na habari bila onyo kwa kurejesha data iliyotoka nayo kiwandani."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Kufuta data ya simu bila ilani kwa kurejesha mipangilio iliyotoka nayo kiwandani."</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Itisha PIN kabla hujabandua"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Omba mchoro wa kufungua kabla hujabandua"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Omba nenosiri kabla hujabandua"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Kimewekwa na msimamizi wako.\nNenda kwenye mipangilio ili uone ruhusa zilizotolewa"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Imesasishwa na msimamizi wako"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Imefutwa na msimamizi wako"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Sawa"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ungependa kutumia programu ya kazini?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Shirika lako linakuruhusu upige simu ukitumia programu za kazini pekee"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Shirika lako linakuruhusu utume ujumbe ukitumia programu za kazini pekee"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Tumia kivinjari cha binafsi"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Tumia kivinjari cha kazini"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Piga simu"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 1c65e61..69b3f9b 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> வினாடிகளுக்குப் பிறகு <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ஐப் பகிர்"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: பகிரப்படவில்லை"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: பகிரப்படவில்லை"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"மொபைல் நெட்வொர்க் பாதுகாப்பு"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"அமைப்புகளைச் சரிபார்க்கலாம்"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"சாதன அடையாளங்காட்டி பகிரப்பட்டது"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> இணைப்பில் உள்ள நெட்வொர்க் உங்கள் சாதனத்தின் தனித்துவ அடையாளங்காட்டியை (IMSI) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> முதல் <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> வரை <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> முறை ரெக்கார்டு செய்துள்ளது."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>க்கு என்க்ரிப்ட் செய்யப்பட்ட இணைப்பு"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"இப்போது கூடுதல் பாதுகாப்பான மொபைல் நெட்வொர்க்குடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>க்கு என்க்ரிப்ட் செய்யப்படாத இணைப்பு"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"என்க்ரிப்ட் செய்யப்படாத மொபைல் நெட்வொர்க்குடன் இணைக்கப்பட்டுள்ளீர்கள். உங்கள் அழைப்புகள், மெசேஜ்கள், தரவு ஆகியவை குறுக்கீடுகளால் பாதிக்கப்படக்கூடியவையாகும்."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"மொபைல் பாதுகாப்பு அமைப்புகள்"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"மேலும் அறிக"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"பிரத்தியேக குறியீடு முடிந்தது."</string>
<string name="fcError" msgid="5325116502080221346">"இணைப்பு சிக்கல் அல்லது தவறான அம்சக் குறியீடு."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"சரி"</string>
@@ -843,7 +858,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"திரையைப் பூட்டுதல்"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"திரை எப்படி, எப்போது பூட்டப்படுகிறது என்பதைக் கட்டுப்படுத்தலாம்."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"எல்லா டேட்டாவையும் அழித்தல்"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் டேப்லெட்டின் தரவை அழிக்கலாம்."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் டேப்லெட்டின் தரவை அழிக்கும்."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"தரவின் ஆரம்பநிலைக்கு மீட்டமைப்பதன் மூலம் எச்சரிக்கை செய்யாமல் Android TVயின் தரவை அழிக்கும்."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"தரவின் ஆரம்பநிலை மீட்டமைப்பைச் செயல்படுத்துவதன் மூலம் எச்சரிக்கை எதுவுமின்றி இன்ஃபோடெயின்மென்ட் சிஸ்டமின் தரவை அழிக்கும்."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் மொபைலின் தரவை அழிக்கலாம்."</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"அகற்றும் முன் PINஐக் கேள்"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"அகற்றும் முன் அன்லாக் பேட்டர்னைக் கேள்"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"உங்கள் நிர்வாகி நிறுவியுள்ளார்.\nவழங்கப்பட்டுள்ள அனுமதிகளை பார்க்க அமைப்புகளுக்குச் செல்லவும்"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"உங்கள் நிர்வாகி புதுப்பித்துள்ளார்"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"உங்கள் நிர்வாகி நீக்கியுள்ளார்"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"சரி"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"பணி ஆப்ஸுக்கு மாற வேண்டுமா?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"உங்கள் நிறுவனம் பணி ஆப்ஸில் இருந்து மட்டுமே அழைக்க உங்களை அனுமதிக்கிறது"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"உங்கள் நிறுவனம் பணி ஆப்ஸில் இருந்து மட்டுமே மெசேஜ்களை அனுப்ப உங்களை அனுமதிக்கிறது"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"தனிப்பட்ட உலாவியைப் பயன்படுத்து"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"பணி உலாவியைப் பயன்படுத்து"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"அழை"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 423cf88..b6c6086 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> సెకన్ల తర్వాత <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వర్డ్ చేయబడలేదు"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వర్డ్ చేయబడలేదు"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"సెల్యులర్ నెట్వర్క్ సెక్యూరిటీ"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"సెట్టింగ్లను రివ్యూ చేయండి"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"పరికర ఐడెంటిఫయర్ యాక్సెస్ చేయబడింది"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> కనెక్షన్లోని నెట్వర్క్ మీ పరికరంకు సంబంధించిన ప్రత్యేక ఐడెంటిఫయర్ను (IMSI) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> నుండి <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> మధ్య కాలంలో <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> సార్లు రికార్డ్ చేసింది."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>కు ఎన్క్రిప్ట్ చేసిన కనెక్షన్"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"మీరు ఇప్పుడు మరింత సురక్షితమైన సెల్యులార్ నెట్వర్క్కు కనెక్ట్ చేయబడ్డారు."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>కు ఎన్క్రిప్ట్ చేయని కనెక్షన్"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"మీరు ఎన్క్రిప్ట్ చేయని సెల్యులార్ నెట్వర్క్కు కనెక్ట్ చేయబడ్డారు. మీ కాల్స్, మెసేజ్లు, అలాగే డేటా అంతరాయానికి ఎక్కువగా గురవుతాయి."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"సెల్యులార్ సెక్యూరిటీ సెట్టింగ్లు"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"మరింత తెలుసుకోండి"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"లక్షణం కోడ్ పూర్తయింది."</string>
<string name="fcError" msgid="5325116502080221346">"కనెక్షన్ సమస్య లేదా లక్షణం కోడ్ చెల్లదు."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"సరే"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్షాట్ను తీయండి"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్ప్లే యొక్క స్క్రీన్షాట్ తీసుకోవచ్చు."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"ప్రివ్యూ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"విస్మరించండి"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"స్టేటస్ బార్ను డిజేబుల్ చేయడం లేదా మార్చడం"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"స్టేటస్ బార్ను డిజేబుల్ చేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"స్టేటస్ పట్టీగా ఉండటం"</string>
@@ -843,7 +857,7 @@
<string name="policylab_forceLock" msgid="7360335502968476434">"స్క్రీన్ను లాక్ చేయడానికి"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"స్క్రీన్ను ఎలా మరియు ఎప్పుడు లాక్ చేయాలనే దాన్ని నియంత్రిస్తుంది."</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"మొత్తం డేటాను ఎరేజ్ చేయడానికి"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ఫ్యాక్టరీ డేటా రీసెట్ను అమలు చేయడం ద్వారా హెచ్చరించకుండానే టాబ్లెట్ డేటాను ఎరేజ్ చేయండి."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"\'ఫ్యాక్టరీ డేటా రీసెట్\'ను అమలు చేయడం ద్వారా వార్నింగ్తో పని లేకుండా టాబ్లెట్ డేటాను ఎరేజ్ చేయండి."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"హెచ్చరించకుండానే మీ Android TV పరికరం డేటాను ఫ్యాక్టరీ డేటా రీసెట్ ద్వారా తొలగిస్తుంది."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ఫ్యాక్టరీ డేటా రీసెట్ను అమలు చేయడం ద్వారా, హెచ్చరిక లేకుండానే సమాచారంతో కూడిన వినోదం సిస్టమ్ డేటాను తొలగించి ఫ్యాక్టరీ రీసెట్ చేయబడుతుంది."</string>
<string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ఫ్యాక్టరీ డేటా రీసెట్ను అమలు చేయడం ద్వారా హెచ్చరించకుండానే ఫోన్ డేటాను ఎరేజ్ చేస్తుంది."</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"అన్పిన్ చేయడానికి ముందు పిన్ కోసం అడుగు"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"అన్పిన్ చేయడానికి ముందు అన్లాక్ ఆకృతి కోసం అడుగు"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"అన్పిన్ చేయడానికి ముందు పాస్వర్డ్ కోసం అడుగు"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"మీ అడ్మిన్ ఇన్స్టాల్ చేశారు.\nసెట్టింగ్లకు వెళ్లి, మంజూరు చేసిన అనుమతులు చూడండి"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"మీ నిర్వాహకులు అప్డేట్ చేశారు"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"మీ నిర్వాహకులు తొలగించారు"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"సరే"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"వర్క్ యాప్నకు మారాలా?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"మీ సంస్థ, వర్క్ యాప్ల నుండి మాత్రమే కాల్స్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"మీ సంస్థ, వర్క్ యాప్ల నుండి మాత్రమే మెసేజ్లను పంపడానికి మిమ్మల్ని అనుమతిస్తుంది"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"వ్యక్తిగత బ్రౌజర్ను ఉపయోగించండి"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"వర్క్ బ్రౌజర్ను ఉపయోగించండి"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"కాల్ చేయండి"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"ఆఫీస్ 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"పరీక్ష"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"కమ్యూనల్"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"గోప్యమైన నోటిఫికేషన్ కంటెంట్ దాచబడింది"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"సెక్యూరిటీ కోసం స్క్రీన్ షేర్ నుండి యాప్ కంటెంట్ దాచబడింది"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"శాటిలైట్కు ఆటోమేటిక్గా కనెక్ట్ చేయబడింది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 47d1c44..c9a2027 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> หลังผ่านไป <xliff:g id="TIME_DELAY">{2}</xliff:g> วินาที"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"การรักษาความปลอดภัยของเครือข่ายมือถือ"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ตรวจสอบการตั้งค่า"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"เข้าถึงตัวระบุของอุปกรณ์แล้ว"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"เครือข่ายในการเชื่อมต่อ <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> จะบันทึกตัวระบุที่ไม่ซ้ำ (IMSI) ของอุปกรณ์จำนวน <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> ครั้งในช่วงเวลาระหว่าง<xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ถึง <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"การเชื่อมต่อกับ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ที่เข้ารหัส"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"ตอนนี้คุณเชื่อมต่อกับเครือข่ายมือถือที่ปลอดภัยยิ่งขึ้นแล้ว"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"การเชื่อมต่อกับ <xliff:g id="NETWORK_NAME">%1$s</xliff:g> ที่ไม่ได้เข้ารหัส"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"คุณเชื่อมต่อกับเครือข่ายมือถือที่ไม่ได้เข้ารหัสอยู่ การโทร ข้อความ และข้อมูลของคุณเสี่ยงต่อการถูกดักข้อมูล"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"การตั้งค่าความปลอดภัยเครือข่ายมือถือ"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"ดูข้อมูลเพิ่มเติม"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"รหัสฟีเจอร์เสร็จสมบูรณ์"</string>
<string name="fcError" msgid="5325116502080221346">"พบปัญหาในการเชื่อมต่อหรือรหัสฟีเจอร์ไม่ถูกต้อง"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ตกลง"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ถ่ายภาพหน้าจอ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ถ่ายภาพหน้าจอได้"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"ตัวอย่าง <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ปิด"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"เป็นแถบสถานะ"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ขอ PIN ก่อนเลิกปักหมุด"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ขอรูปแบบการปลดล็อกก่อนเลิกปักหมุด"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ขอรหัสผ่านก่อนเลิกปักหมุด"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"ติดตั้งโดยผู้ดูแลระบบของคุณ\nไปที่การตั้งค่าเพื่อดูสิทธิ์ที่ได้รับอนุญาต"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"อัปเดตโดยผู้ดูแลระบบ"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"ลบโดยผู้ดูแลระบบ"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ตกลง"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"เปลี่ยนไปใช้แอปงานไหม"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"องค์กรอนุญาตให้คุณโทรออกได้จากแอปงานเท่านั้น"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"องค์กรอนุญาตให้คุณส่งข้อความได้จากแอปงานเท่านั้น"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ใช้เบราว์เซอร์ส่วนตัว"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ใช้เบราว์เซอร์งาน"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"โทร"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 1f9b48f..4428dc8 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pagkatapos ng <xliff:g id="TIME_DELAY">{2}</xliff:g> (na) segundo"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Hindi naipasa"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Hindi ipinasa"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Seguridad ng cellular network"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Suriin ang mga setting"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Na-access ang identifier ng device"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Naitala ng isang network sa koneksyon sa <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> ang unique identifier (IMSI) ng iyong device nang <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> (na) beses sa pagitan ng <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> at <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Naka-encrypt na koneksyon sa <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Nakakonekta ka na sa mas secure na cellular network."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Hindi naka-encrypt na koneksyon sa <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Nakakonekta ka sa hindi naka-encrypt na cellular network. Posibleng mahina ang proteksyon laban pag-intercept ng iyong mga tawag, mensahe, at data."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mga setting ng seguridad ng cellular"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Matuto pa"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Kumpleto na ang code ng tampok."</string>
<string name="fcError" msgid="5325116502080221346">"Problema sa koneksyon o di-wastong code ng tampok."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Humingi ng PIN bago mag-unpin"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Humingi ng password bago mag-unpin"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Na-install ng iyong admin.\nPumunta sa mga setting para makita ang mga ibinigay na pahintulot"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Na-update ng iyong admin"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Na-delete ng iyong admin"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Lumipat sa app para sa trabaho?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Pinapayagan ka lang ng iyong organisasyon na tumawag mula sa mga app para sa trabaho"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Pinapayagan ka lang ng iyong organisasyon na magpadala ng mga mensahe mula sa mga app para sa trabaho"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gamitin ang personal na browser"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gamitin ang browser sa trabaho"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Tumawag"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 60c4a70..3d022a8 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> saniye sonra <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönlendirilmedi"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönlendirilmedi"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Hücresel ağ güvenliği"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Ayarları incele"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Cihaz tanımlayıcısına erişildi"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Cihazınızın benzersiz tanımlayıcısı (IMSI), <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> ile <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> arasında <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> bağlantısındaki bir ağ tarafından <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> kez kaydedildi."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ağına şifrelenmiş bağlantı"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Artık daha güvenli bir hücresel ağa bağlısınız."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ağına şifrelenmemiş bağlantı"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Şifrelenmemiş bir hücresel ağa bağlısınız. Aramalarınız, mesajlarınız ve verileriniz takip edilebilir."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Hücresel güvenlik ayarları"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Daha fazla bilgi"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Özellik kodu tamamlandı."</string>
<string name="fcError" msgid="5325116502080221346">"Bağlantı sorunu veya geçersiz özellik kodu."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Tamam"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Yöneticiniz tarafından yüklendi.\nVerilen izinleri görüntülemek için ayarlara gidin"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Yöneticiniz tarafından güncellendi"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Yöneticiniz tarafından silindi"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Tamam"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"İş uygulamasına geçilsin mi?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Kuruluşunuz yalnızca iş uygulamalarından telefon etmenize izin veriyor"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Kuruluşunuz yalnızca iş uygulamalarından mesaj göndermenize izin veriyor"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Kişisel tarayıcıyı kullan"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"İş tarayıcısını kullan"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Telefon et"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f8f3a23..e272f5f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -155,16 +155,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> після <xliff:g id="TIME_DELAY">{2}</xliff:g> сек."</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переслано"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переслано"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Безпека мобільної мережі"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Перевірте налаштування"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Отримано доступ до ідентифікатора пристрою"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Мережа (з’єднання: <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>) записала унікальний ідентифікатор вашого пристрою (IMSI) кілька разів (<xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g>) у період між <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> і <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"З’єднання з мережею <xliff:g id="NETWORK_NAME">%1$s</xliff:g> зашифровано"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Тепер вас підключено до безпечнішої мобільної мережі."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"З’єднання з мережею <xliff:g id="NETWORK_NAME">%1$s</xliff:g> не зашифровано"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Вас підключено до незашифрованої мобільної мережі. Ваші дзвінки, повідомлення й дані вразливі, і їх можуть перехопити."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Налаштування безпеки мобільної мережі"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Докладніше"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Сервісний код виконано."</string>
<string name="fcError" msgid="5325116502080221346">"Пробл. підключення чи недійсний ідентифікатор."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1900,8 +1915,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-код для відкріплення"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитувати ключ розблокування перед відкріпленням"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитувати пароль перед відкріпленням"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Установлено адміністратором.\nПерейдіть у налаштування, щоб переглянути надані дозволи."</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Оновлено адміністратором"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Видалено адміністратором"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
@@ -2219,6 +2233,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Перейти в робочий додаток?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша організація дозволяє телефонувати лише з робочих додатків"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша організація дозволяє надсилати повідомлення лише з робочих додатків"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Використати особистий веб-переглядач"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Використати робочий веб-переглядач"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Телефонувати"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index a07189a..a2b7327 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد از <xliff:g id="TIME_DELAY">{2}</xliff:g> سیکنڈ"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : فارورڈ نہیں کی گئی"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: فارورڈ نہیں کی گئی"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"سیلولر نیٹ ورک سیکیورٹی"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"ترتیبات کا جائزہ لیں"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"آلے کے شناخت کار تک رسائی حاصل کر لی گئی"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> کنکشن پر موجود نیٹ ورک نے <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> اور <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> کے درمیان کی مدت میں آپ کے آلے کے منفرد شناخت کنندہ (IMSI) کو <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> بار ریکارڈ کیا۔"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> سے مرموز کردہ کنکشن"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"اب آپ زیادہ محفوظ سیلولر نیٹ ورک سے منسلک ہیں۔"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> سے غیر مرموز کردہ کنکشن"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"آپ ایک غیر مرموز کردہ سیلولر نیٹ ورک سے منسلک ہیں۔ آپ کی کالز، پیغامات اور ڈیٹا پر انٹرسیپشن کا خطرہ لاحق ہے۔"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"سیلولر سیکیورٹی کی ترتیبات"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"مزید جانیں"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"خصوصیت کوڈ مکمل۔"</string>
<string name="fcError" msgid="5325116502080221346">"کنکشن مسئلہ یا غلط خصوصیت کوڈ۔"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"ٹھیک ہے"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"پن ہٹانے سے پہلے PIN طلب کریں"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"آپ کے منتظم نے انسٹال کیا ہے۔\nدی گئی اجازتیں دیکھنے کیلئے ترتیبات پر جائیں"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"آپ کے منتظم کے ذریعے اپ ڈیٹ کیا گیا"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"آپ کے منتظم کے ذریعے حذف کیا گیا"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"ٹھیک ہے"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ورک ایپ پر سوئچ کریں؟"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"آپ کی تنظیم آپ کو صرف ورک ایپس سے کالز کرنے کی اجازت دیتی ہے"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"آپ کی تنظیم آپ کو صرف ورک ایپس سے پیغامات بھیجنے کی اجازت دیتی ہے"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ذاتی براؤزر استعمال کریں"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"ورک براؤزر استعمال کریں"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"کال کریں"</string>
@@ -2396,8 +2414,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"تیسری دفتری پروفائل"</string>
<string name="profile_label_test" msgid="9168641926186071947">"ٹیسٹ"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"کمیونل"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"حساس اطلاعی مواد چھپا ہوا ہے"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"سیکیورٹی کے مد نظر ایپ کا مواد اسکرین کے اشتراک سے چھپا ہوا ہے"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"سٹلائٹ سے خودکار طور پر منسلک ہے"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index b66d8c7..b35c33b 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> soniyadan so‘ng"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yo‘naltirilmadi"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: yo‘naltirilmadi"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Mobil tarmoq xavfsizligi"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Sozlamalarni tekshirish"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Qurilma identifikatoriga kirildi"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> nomli tarmoqqa ulanish qurilmangiz unikal identifikatorini (IMSI) <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> va <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> orasida <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> marta qayd qilgan."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> nomli tarmoqqa shifrlangan ulanish"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Endi siz yanada xavfsizroq mobil tarmoqqa ulangansiz."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> nomli tarmoqqa shifrlanmagan ulanish"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Shifrlanmagan mobil tarmoqqa ulangansiz. Chaqiruvlaringiz, xabarlaringiz va maʼlumotlaringiz tutib qolinishidan himoyasi kuchsiz."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Mobil tarmoq xavfsizligi sozlamalari"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Batafsil"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Maxsus kod bajarildi."</string>
<string name="fcError" msgid="5325116502080221346">"Tarmoqda xato yoki maxsus kod noto‘g‘ri."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Skrinshot olish"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekrandan skrinshot olishi mumkin."</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Razm solish, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"yopish"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"holat panelini o‘zgartirish yoki o‘chirish"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"holat qatorida ko‘rinishi"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Yechishda PIN kod talab qilinsin"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Yechishdan oldin grafik kalit so‘ralsin"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bo‘shatishdan oldin parol so‘ralsin"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Administrator oʻrnatgan.\nBerilgan ruxsatlarni koʻrish uchun sozlamalarni oching"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Administrator tomonidan yangilangan"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ishga oid ilovaga almashtirilsinmi?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tashkilotingiz faqat ishga oid ilovalar orqali chaqiruvga ruxsat beradi"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tashkilotingiz faqat ishga oid ilovalar orqali xabarlar yuborishga ruxsat beradi"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Shaxsiy brauzerdan foydalanish"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Ishga oid brauzerdan foydalanish"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Chaqiruv"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index e4aadac..e7c94d6 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> sau <xliff:g id="TIME_DELAY">{2}</xliff:g> giây"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Không được chuyển tiếp"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Không được chuyển tiếp"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Chế độ bảo mật mạng di động"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Xem lại các chế độ cài đặt"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Đã truy cập vào mã nhận dạng thiết bị"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Một mạng trong kết nối <xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> đã ghi lại giá trị nhận dạng duy nhất (IMSI) của thiết bị <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> lần trong khoảng thời gian từ <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> đến <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Đã mã hoá kết nối với <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Bạn hiện đã kết nối với một mạng di động an toàn hơn."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Chưa mã hoá kết nối với <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Bạn đã kết nối với một mạng di động chưa được mã hoá. Cuộc gọi, tin nhắn và dữ liệu của bạn dễ bị gián đoạn."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Chế độ cài đặt mạng di động"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Tìm hiểu thêm"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Mã tính năng đã hoàn tất."</string>
<string name="fcError" msgid="5325116502080221346">"Sự cố kết nối hoặc mã tính năng không hợp lệ."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"OK"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Hỏi mã PIN trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Hỏi mật khẩu trước khi bỏ ghim"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Do quản trị viên của bạn cài đặt.\nChuyển đến phần cài đặt để xem các quyền được cấp"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Do quản trị viên của bạn cập nhật"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Do quản trị viên của bạn xóa"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Chuyển sang ứng dụng công việc?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Tổ chức của bạn chỉ cho phép bạn gọi điện bằng ứng dụng công việc"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Tổ chức của bạn chỉ cho phép bạn gửi tin nhắn bằng ứng dụng công việc"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Dùng trình duyệt cá nhân"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Dùng trình duyệt công việc"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Gọi"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index ac4681b..10ceb5b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g>秒后<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"移动网络安全性"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"查看设置"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"设备标识符被访问了"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"在 <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> 至 <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g> 这个时段内,某个位于“<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g>”连接上的网络对您设备的唯一标识符 (IMSI) 进行了 <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> 次记录。"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"与“<xliff:g id="NETWORK_NAME">%1$s</xliff:g>”建立了加密连接"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"您现已连接到一个更安全的移动网络。"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"与“<xliff:g id="NETWORK_NAME">%1$s</xliff:g>”建立了未加密的连接"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"您已连接到一个未加密的移动网络。您的通话、消息和数据可能会遭到拦截。"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"移动网络安全性设置"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"了解详情"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"功能代码已拨完。"</string>
<string name="fcError" msgid="5325116502080221346">"出现连接问题或功能代码无效。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"确定"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"截取屏幕截图"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可截取显示画面的屏幕截图。"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"预览,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"关闭"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允许应用停用状态栏或者增删系统图标。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"用作状态栏"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消时要求输入PIN码"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定前要求绘制解锁图案"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消时要求输入密码"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"由您的管理员安装。\n前往设置可查看已授予的权限"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由您的管理员更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由您的管理员删除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"确定"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"切换到工作应用?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"贵组织仅允许您通过工作应用拨打电话"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"贵组织仅允许您通过工作应用发送消息"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用个人浏览器"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作浏览器"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"拨打电话"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1b1a9d5..541ea63 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> 於 <xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後轉接"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:尚未轉接"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:尚未轉接"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"流動網絡安全性"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"檢查設定"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"已存取裝置識別碼"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> 連線上的網絡已記錄裝置的專屬識別碼 (IMSI),次數為 <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> 次;記錄區間為 <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>至<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>。"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"已連線至加密的 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"你現已連線至較安全的流動網絡。"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"已連線至未加密的 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"你已連線至未加密的流動網絡。通話、訊息和資料會容易被攔截。"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"流動網絡安全性設定"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"瞭解詳情"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"功能碼輸入完成。"</string>
<string name="fcError" msgid="5325116502080221346">"連線問題或功能碼無效。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"確定"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須提供解鎖圖案"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"已由你的管理員安裝。\n請前往設定查看已授予的權限"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由你的管理員更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由你的管理員刪除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"好"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"要切換至工作應用程式嗎?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"你的機構只允許你透過工作應用程式打電話"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"你的機構只允許你透過工作應用程式傳送訊息"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用個人瀏覽器"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作瀏覽器"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"打電話"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 76ed403..8720a9d 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後 <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:未轉接"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:未轉接"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"行動網路安全性"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"查看設定"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"已存取裝置 ID"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> 連線上的網路已記錄裝置的專屬 ID (IMSI),次數為 <xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> 次;記錄區間為 <xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g>至 <xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>。"</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"已連上加密的 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"你現在已連上較安全的行動網路。"</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"已連上未加密的 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"你已連上未加密的行動網路。通話、訊息和資料會容易遭到攔截。"</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"行動網路安全性設定"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"瞭解詳情"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"功能碼輸入完成。"</string>
<string name="fcError" msgid="5325116502080221346">"連線發生問題或功能碼無效。"</string>
<string name="httpErrorOk" msgid="6206751415788256357">"確定"</string>
@@ -1898,8 +1913,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須畫出解鎖圖案"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"這是管理員安裝的套件。\n你可以前往設定查看授予的權限"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"已由你的管理員更新"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"已由你的管理員刪除"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"確定"</string>
@@ -2217,6 +2231,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"要切換到工作應用程式嗎?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"貴機構僅允許透過工作應用程式撥打電話"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"貴機構僅允許透過工作應用程式傳送訊息"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用個人瀏覽器"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作瀏覽器"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"撥號"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index b44d5cd..7f14f04 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -153,16 +153,31 @@
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> emuva kwamasekhondi angu-<xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
<string name="cfTemplateRegistered" msgid="5619930473441550596">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Akudlulisiwe"</string>
<string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: akudlulisiwe"</string>
- <string name="scCellularNetworkSecurityTitle" msgid="90330018476923559">"Ukuvikeleka kwenethiwekhi yeselula"</string>
- <string name="scCellularNetworkSecuritySummary" msgid="8659128412709908263">"Buyekeza amasethingi"</string>
- <string name="scIdentifierDisclosureIssueTitle" msgid="3737384845335568193">"Inkomba yedivayisi ifinyelelwe"</string>
- <string name="scIdentifierDisclosureIssueSummary" msgid="3870743771498510600">"Inethiwekhi exhunywe ku-<xliff:g id="DISCLOSURE_NETWORK">%4$s</xliff:g> irekhode inkomba eyingqayizivele yedivayisi yakho (IMSI) izikhathi ezingu-<xliff:g id="DISCLOSURE_COUNT">%1$d</xliff:g> phakathi kuka-<xliff:g id="DISCLOSURE_WINDOW_START_TIME">%2$tr</xliff:g> no-<xliff:g id="DISCLOSURE_WINDOW_END_TIME">%3$tr</xliff:g>."</string>
- <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Uxhumano olubethelwe ku-<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Manje usuxhumeke kunethiwekhi yeselula evikeleke kakhulu."</string>
- <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Uxhumano olungabethelwe ku-<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
- <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Uxhumeke kunethiwekhi yeselula engabethelwe. Amakholi akho, imilayezo, nedatha kusengozini yokuphazamiseka."</string>
- <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Amasethingi okuvikeleka kweselula"</string>
+ <!-- no translation found for scCellularNetworkSecurityTitle (7752521808690294384) -->
+ <skip />
+ <!-- no translation found for scCellularNetworkSecuritySummary (7042036754550545005) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueTitle (2898888825129970328) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummaryNotification (3699930821270580416) -->
+ <skip />
+ <!-- no translation found for scIdentifierDisclosureIssueSummary (7283387338827749276) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedTitle (234717016411824969) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueEncryptedSummary (8577510708842150475) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedTitle (3978071464929453915) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummaryNotification (7386936934128110388) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueNonEncryptedSummary (5093428974513703253) -->
+ <skip />
+ <!-- no translation found for scNullCipherIssueActionSettings (5888857706424639946) -->
+ <skip />
<string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"Funda kabanzi"</string>
+ <!-- no translation found for scNullCipherIssueActionGotIt (8747796640866585787) -->
+ <skip />
<string name="fcComplete" msgid="1080909484660507044">"Ikhodi yesici iqedile."</string>
<string name="fcError" msgid="5325116502080221346">"Inkinga yoxhumano noma ikhodi yesici engalungile."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"KULUNGILE"</string>
@@ -356,8 +371,7 @@
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Thatha isithombe-skrini"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ingathatha isithombe-skrini sesiboniso"</string>
<string name="dream_preview_title" msgid="5570751491996100804">"Hlola kuqala, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
- <skip />
+ <string name="dream_accessibility_action_click" msgid="7392398629967797805">"chitha"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"khubaza noma guqula ibha yomumo"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"yiba yibha yesimo"</string>
@@ -1898,8 +1912,7 @@
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Cela iphinikhodi ngaphambi kokuphina"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Cela iphethini yokuvula ngaphambi kokususa ukuphina"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
- <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
- <skip />
+ <string name="package_installed_device_owner" msgid="8684974629306529138">"Kufakwe ngumphathi wakho.\nIya kumasethingi ukuze ubuke izimvume ezinikeziwe"</string>
<string name="package_updated_device_owner" msgid="7560272363805506941">"Kubuyekezwe umlawuli wakho"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Kususwe umlawuli wakho"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"KULUNGILE"</string>
@@ -2217,6 +2230,10 @@
<string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Shintshela ku-app yasemsebenzini?"</string>
<string name="miniresolver_call_information" msgid="6739417525304184083">"Inhlangano yakho ikuvumela kuphela ukuthi wenze amakholi ngama-app asemsebenzini"</string>
<string name="miniresolver_sms_information" msgid="4311292661329483088">"Inhlangano yakho ikuvumela ukuthumela imilayezo kusuka kuma-app omsebenzi kuphela"</string>
+ <!-- no translation found for miniresolver_private_space_phone_information (4469511223312488570) -->
+ <skip />
+ <!-- no translation found for miniresolver_private_space_messages_information (111285656327622118) -->
+ <skip />
<string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Sebenzisa isiphequluli somuntu siqu"</string>
<string name="miniresolver_use_work_browser" msgid="543575306251952994">"Sebenzisa isiphequluli somsebenzi"</string>
<string name="miniresolver_call" msgid="6386870060423480765">"Fona"</string>
@@ -2396,8 +2413,7 @@
<string name="profile_label_work_3" msgid="4834572253956798917">"Umsebenzi 3"</string>
<string name="profile_label_test" msgid="9168641926186071947">"Hlola"</string>
<string name="profile_label_communal" msgid="8743921499944800427">"Okomphakathi"</string>
- <!-- no translation found for redacted_notification_message (1520587845842228816) -->
- <skip />
+ <string name="redacted_notification_message" msgid="1520587845842228816">"Okuqukethwe kwesaziso esizwelayo kufihliwe"</string>
<string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Okuqukethwe kwe-app kufihliwe kusuka ekwabelaneni kwesikrini ngokuvikelwa"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"Ixhumeke ngokuzenzakalelayo kusathelayithi"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b5256f8..877d11e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -764,6 +764,9 @@
<!-- Indicates whether to enable hinge angle sensor when using unfold animation -->
<bool name="config_unfoldTransitionHingeAngle">false</bool>
+ <!-- Indicates whether to enable haptics during unfold animation -->
+ <bool name="config_unfoldTransitionHapticsEnabled">false</bool>
+
<!-- Indicates the time needed to time out the fold animation if the device stops in half folded
mode. -->
<integer name="config_unfoldTransitionHalfFoldedTimeout">1000</integer>
@@ -3656,6 +3659,7 @@
"emergency" = Launch emergency dialer
"lockdown" = Lock down device until the user authenticates
"logout" = Logout the current user
+ "system_update" = Launch System Update screen
-->
<string-array translatable="false" name="config_globalActionsList">
<item>emergency</item>
@@ -6973,6 +6977,9 @@
<!-- Whether to enable left-right split in portrait on this device -->
<bool name="config_leftRightSplitInPortrait">false</bool>
+ <!-- Whether to allow split screen ratios to flexibly calculate based on available space -->
+ <bool name="config_flexibleSplitRatios">false</bool>
+
<!-- Whether scroll haptic feedback is enabled for rotary encoder scrolls on
{@link MotionEvent#AXIS_SCROLL} generated by {@link InputDevice#SOURCE_ROTARY_ENCODER}
devices. -->
@@ -7031,4 +7038,7 @@
If the gesture is completed faster than this, we assume it's not performed by human and the
event gets ignored. -->
<integer name="config_defaultMinEmergencyGestureTapDurationMillis">200</integer>
+
+ <!-- Whether the system uses auto-suspend mode. -->
+ <bool name="config_useAutoSuspend">true</bool>
</resources>
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index a248ede..cc02a7e 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -190,6 +190,13 @@
<integer name="config_satellite_nb_iot_inactivity_timeout_millis">180000</integer>
<java-symbol type="integer" name="config_satellite_nb_iot_inactivity_timeout_millis" />
+ <!-- The time duration in millis after which cellular scanning will be enabled and satellite
+ will move to IDLE state. This timeout duration is used for satellite with NB IOT radio
+ technologies in demo mode.
+ -->
+ <integer name="config_satellite_demo_mode_nb_iot_inactivity_timeout_millis">60000</integer>
+ <java-symbol type="integer" name="config_satellite_demo_mode_nb_iot_inactivity_timeout_millis" />
+
<!-- The time duration in millis needed to switch the modem image from TN to NTN. -->
<integer name="config_satellite_modem_image_switching_duration_millis">20000</integer>
<java-symbol type="integer" name="config_satellite_modem_image_switching_duration_millis" />
diff --git a/core/res/res/values/public-final.xml b/core/res/res/values/public-final.xml
index daa0f553..d421944 100644
--- a/core/res/res/values/public-final.xml
+++ b/core/res/res/values/public-final.xml
@@ -3741,4 +3741,185 @@
<!-- @hide @SystemApi -->
<public type="bool" name="config_enableDefaultNotesForWorkProfile" id="0x0111000b" />
+ <!-- ===============================================================
+ Resources added in version NEXT of the platform
+
+ NOTE: After this version of the platform is forked, changes cannot be made to the root
+ branch's groups for that release. Only merge changes to the forked platform branch.
+ =============================================================== -->
+ <eat-comment/>
+
+ <staging-public-group-final type="attr" first-id="0x01bd0000">
+ <!-- @FlaggedApi("android.content.res.default_locale") -->
+ <public name="defaultLocale"/>
+ <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")
+ @hide @SystemApi -->
+ <public name="isVirtualDeviceOnly"/>
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_optional" />
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_adServiceTypes" />
+ <!-- @hide @SystemApi @FlaggedApi("android.content.res.manifest_flagging") -->
+ <public name="featureFlag"/>
+ <!-- @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") -->
+ <public name="systemUserOnly"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="allow"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="query"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="queryPrefix"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="queryPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="queryAdvancedPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="querySuffix"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentPrefix"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentAdvancedPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentSuffix"/>
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public name="useBoundsForWidth"/>
+ <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
+ <public name="autoTransact"/>
+ <!-- @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") -->
+ <public name="windowOptOutEdgeToEdgeEnforcement"/>
+ <!-- @FlaggedApi("android.security.content_uri_permission_apis") -->
+ <public name="requireContentUriPermissionFromCaller" />
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_languageSettingsActivity" />
+ <!-- @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") -->
+ <public name="useLocalePreferredLineHeightForMinimum"/>
+ <!-- @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") -->
+ <public name="contentSensitivity" />
+ <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
+ <public name="supportsConnectionlessStylusHandwriting" />
+ <!-- @FlaggedApi("android.nfc.nfc_observe_mode") -->
+ <public name="shouldDefaultToObserveMode"/>
+ <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
+ <public name="allowCrossUidActivitySwitchFromBelow"/>
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public name="shiftDrawingOffsetForStartOverhang" />
+ <!-- @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") -->
+ <public name="windowIsFrameRatePowerSavingsBalanced"/>
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_dreamCategory" />
+ </staging-public-group-final>
+
+ <!-- @FlaggedApi("android.content.res.default_locale") -->
+ <public type="attr" name="defaultLocale" id="0x01010688" />
+ <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")
+ @hide @SystemApi -->
+ <public type="attr" name="isVirtualDeviceOnly" id="0x01010689" />
+ <!-- @hide @SystemApi @FlaggedApi("android.content.res.manifest_flagging") -->
+ <public type="attr" name="featureFlag" id="0x0101068c" />
+ <!-- @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") -->
+ <public type="attr" name="systemUserOnly" id="0x0101068d" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="allow" id="0x0101068e" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="query" id="0x0101068f" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="queryPrefix" id="0x01010690" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="queryPattern" id="0x01010691" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="queryAdvancedPattern" id="0x01010692" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="querySuffix" id="0x01010693" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentPrefix" id="0x01010694" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentPattern" id="0x01010695" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentAdvancedPattern" id="0x01010696" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentSuffix" id="0x01010697" />
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public type="attr" name="useBoundsForWidth" id="0x01010698" />
+ <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
+ <public type="attr" name="autoTransact" id="0x01010699" />
+ <!-- @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") -->
+ <public type="attr" name="windowOptOutEdgeToEdgeEnforcement" id="0x0101069a" />
+ <!-- @FlaggedApi("android.security.content_uri_permission_apis") -->
+ <public type="attr" name="requireContentUriPermissionFromCaller" id="0x0101069b" />
+ <!-- @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") -->
+ <public type="attr" name="useLocalePreferredLineHeightForMinimum" id="0x0101069d" />
+ <!-- @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") -->
+ <public type="attr" name="contentSensitivity" id="0x0101069e" />
+ <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
+ <public type="attr" name="supportsConnectionlessStylusHandwriting" id="0x0101069f" />
+ <!-- @FlaggedApi("android.nfc.nfc_observe_mode") -->
+ <public type="attr" name="shouldDefaultToObserveMode" id="0x010106a0" />
+ <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
+ <public type="attr" name="allowCrossUidActivitySwitchFromBelow" id="0x010106a1" />
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public type="attr" name="shiftDrawingOffsetForStartOverhang" id="0x010106a2" />
+ <!-- @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") -->
+ <public type="attr" name="windowIsFrameRatePowerSavingsBalanced" id="0x010106a3" />
+
+ <staging-public-group-final type="string" first-id="0x01ba0000">
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.retail_demo_role_enabled") -->
+ <public name="config_defaultRetailDemo" />
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.wallet_role_enabled") -->
+ <public name="config_defaultWallet" />
+ </staging-public-group-final>
+
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.retail_demo_role_enabled") -->
+ <public type="string" name="config_defaultRetailDemo" id="0x01040048" />
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.wallet_role_enabled") -->
+ <public type="string" name="config_defaultWallet" id="0x01040049" />
+
+ <staging-public-group-final type="dimen" first-id="0x01b90000">
+ <!-- System corner radius baseline sizes. Used by Material styling of rounded corner shapes-->
+ <public name="removed_system_corner_radius_xsmall" />
+ <public name="removed_system_corner_radius_small" />
+ <public name="removed_system_corner_radius_medium" />
+ <public name="removed_system_corner_radius_large" />
+ <public name="removed_system_corner_radius_xlarge" />
+ </staging-public-group-final>
+
+ <!-- System corner radius baseline sizes. Used by Material styling of rounded corner shapes-->
+
+ <staging-public-group-final type="color" first-id="0x01b80000">
+ <public name="system_surface_disabled"/>
+ <public name="system_on_surface_disabled"/>
+ <public name="system_outline_disabled"/>
+ <public name="system_error_0"/>
+ <public name="system_error_10"/>
+ <public name="system_error_50"/>
+ <public name="system_error_100"/>
+ <public name="system_error_200"/>
+ <public name="system_error_300"/>
+ <public name="system_error_400"/>
+ <public name="system_error_500"/>
+ <public name="system_error_600"/>
+ <public name="system_error_700"/>
+ <public name="system_error_800"/>
+ <public name="system_error_900"/>
+ <public name="system_error_1000"/>
+ </staging-public-group-final>
+
+ <public type="color" name="system_surface_disabled" id="0x010600c2" />
+ <public type="color" name="system_on_surface_disabled" id="0x010600c3" />
+ <public type="color" name="system_outline_disabled" id="0x010600c4" />
+ <public type="color" name="system_error_0" id="0x010600c5" />
+ <public type="color" name="system_error_10" id="0x010600c6" />
+ <public type="color" name="system_error_50" id="0x010600c7" />
+ <public type="color" name="system_error_100" id="0x010600c8" />
+ <public type="color" name="system_error_200" id="0x010600c9" />
+ <public type="color" name="system_error_300" id="0x010600ca" />
+ <public type="color" name="system_error_400" id="0x010600cb" />
+ <public type="color" name="system_error_500" id="0x010600cc" />
+ <public type="color" name="system_error_600" id="0x010600cd" />
+ <public type="color" name="system_error_700" id="0x010600ce" />
+ <public type="color" name="system_error_800" id="0x010600cf" />
+ <public type="color" name="system_error_900" id="0x010600d0" />
+ <public type="color" name="system_error_1000" id="0x010600d1" />
+
</resources>
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index c84f781..b64334f 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -109,143 +109,66 @@
=============================================================== -->
<eat-comment/>
- <staging-public-group type="attr" first-id="0x01bd0000">
- <!-- @FlaggedApi("android.content.res.default_locale") -->
- <public name="defaultLocale"/>
- <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")
- @hide @SystemApi -->
- <public name="isVirtualDeviceOnly"/>
- <!-- @FlaggedApi("android.content.pm.sdk_lib_independence") -->
+ <staging-public-group type="attr" first-id="0x01b70000">
+ <!-- @FlaggedApi("android.content.pm.sdk_lib_independence") -->
<public name="optional"/>
<!-- @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") -->
<public name="adServiceTypes" />
- <!-- @hide @SystemApi @FlaggedApi("android.content.res.manifest_flagging") -->
- <public name="featureFlag"/>
- <!-- @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") -->
- <public name="systemUserOnly"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="allow"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="query"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="queryPrefix"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="queryPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="queryAdvancedPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="querySuffix"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentPrefix"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentAdvancedPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentSuffix"/>
- <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
- <public name="useBoundsForWidth"/>
- <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
- <public name="autoTransact"/>
- <!-- @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") -->
- <public name="windowOptOutEdgeToEdgeEnforcement"/>
- <!-- @FlaggedApi("android.security.content_uri_permission_apis") -->
- <public name="requireContentUriPermissionFromCaller" />
<!-- @FlaggedApi("android.view.inputmethod.ime_switcher_revamp") -->
<public name="languageSettingsActivity"/>
- <!-- @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") -->
- <public name="useLocalePreferredLineHeightForMinimum"/>
- <!-- @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") -->
- <public name="contentSensitivity" />
- <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
- <public name="supportsConnectionlessStylusHandwriting" />
- <!-- @FlaggedApi("android.nfc.nfc_observe_mode") -->
- <public name="shouldDefaultToObserveMode"/>
- <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
- <public name="allowCrossUidActivitySwitchFromBelow"/>
- <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
- <public name="shiftDrawingOffsetForStartOverhang" />
- <!-- @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") -->
- <public name="windowIsFrameRatePowerSavingsBalanced"/>
<!-- @FlaggedApi("android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM") -->
<public name="dreamCategory"/>
</staging-public-group>
- <staging-public-group type="id" first-id="0x01bc0000">
+ <staging-public-group type="id" first-id="0x01b60000">
</staging-public-group>
- <staging-public-group type="style" first-id="0x01bb0000">
+ <staging-public-group type="style" first-id="0x01b50000">
</staging-public-group>
- <staging-public-group type="string" first-id="0x01ba0000">
- <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.retail_demo_role_enabled") -->
- <public name="config_defaultRetailDemo" />
- <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.wallet_role_enabled") -->
- <public name="config_defaultWallet" />
+ <staging-public-group type="string" first-id="0x01b40000">
</staging-public-group>
- <staging-public-group type="dimen" first-id="0x01b90000">
- <!-- System corner radius baseline sizes. Used by Material styling of rounded corner shapes-->
- <public name="removed_system_corner_radius_xsmall" />
- <public name="removed_system_corner_radius_small" />
- <public name="removed_system_corner_radius_medium" />
- <public name="removed_system_corner_radius_large" />
- <public name="removed_system_corner_radius_xlarge" />
+ <staging-public-group type="dimen" first-id="0x01b30000">
</staging-public-group>
- <staging-public-group type="color" first-id="0x01b80000">
- <public name="system_surface_disabled"/>
- <public name="system_on_surface_disabled"/>
- <public name="system_outline_disabled"/>
- <public name="system_error_0"/>
- <public name="system_error_10"/>
- <public name="system_error_50"/>
- <public name="system_error_100"/>
- <public name="system_error_200"/>
- <public name="system_error_300"/>
- <public name="system_error_400"/>
- <public name="system_error_500"/>
- <public name="system_error_600"/>
- <public name="system_error_700"/>
- <public name="system_error_800"/>
- <public name="system_error_900"/>
- <public name="system_error_1000"/>
+ <staging-public-group type="color" first-id="0x01b20000">
</staging-public-group>
- <staging-public-group type="array" first-id="0x01b70000">
+ <staging-public-group type="array" first-id="0x01b10000">
</staging-public-group>
- <staging-public-group type="drawable" first-id="0x01b60000">
+ <staging-public-group type="drawable" first-id="0x01b00000">
</staging-public-group>
- <staging-public-group type="layout" first-id="0x01b50000">
+ <staging-public-group type="layout" first-id="0x01af0000">
</staging-public-group>
- <staging-public-group type="anim" first-id="0x01b40000">
+ <staging-public-group type="anim" first-id="0x01ae0000">
</staging-public-group>
- <staging-public-group type="animator" first-id="0x01b30000">
+ <staging-public-group type="animator" first-id="0x01ad0000">
</staging-public-group>
- <staging-public-group type="interpolator" first-id="0x01b20000">
+ <staging-public-group type="interpolator" first-id="0x01ac0000">
</staging-public-group>
- <staging-public-group type="mipmap" first-id="0x01b10000">
+ <staging-public-group type="mipmap" first-id="0x01ab0000">
</staging-public-group>
- <staging-public-group type="integer" first-id="0x01b00000">
+ <staging-public-group type="integer" first-id="0x01aa0000">
</staging-public-group>
- <staging-public-group type="transition" first-id="0x01af0000">
+ <staging-public-group type="transition" first-id="0x01a90000">
</staging-public-group>
- <staging-public-group type="raw" first-id="0x01ae0000">
+ <staging-public-group type="raw" first-id="0x01a80000">
</staging-public-group>
- <staging-public-group type="bool" first-id="0x01ad0000">
+ <staging-public-group type="bool" first-id="0x01a70000">
</staging-public-group>
- <staging-public-group type="fraction" first-id="0x01ac0000">
+ <staging-public-group type="fraction" first-id="0x01a60000">
</staging-public-group>
</resources>
diff --git a/core/res/res/values/required_apps_managed_device.xml b/core/res/res/values/required_apps_managed_device.xml
index c455bd8..c80d66c 100644
--- a/core/res/res/values/required_apps_managed_device.xml
+++ b/core/res/res/values/required_apps_managed_device.xml
@@ -29,5 +29,6 @@
<item>com.android.providers.downloads.ui</item>
<item>com.android.documentsui</item>
<item>com.android.cellbroadcastreceiver</item>
+ <item>com.android.webview</item>
</string-array>
</resources>
diff --git a/core/res/res/values/required_apps_managed_profile.xml b/core/res/res/values/required_apps_managed_profile.xml
index 6ed385a..5f52e1e 100644
--- a/core/res/res/values/required_apps_managed_profile.xml
+++ b/core/res/res/values/required_apps_managed_profile.xml
@@ -26,5 +26,6 @@
<item>com.android.providers.downloads</item>
<item>com.android.providers.downloads.ui</item>
<item>com.android.documentsui</item>
+ <item>com.android.webview</item>
</string-array>
</resources>
diff --git a/core/res/res/values/required_apps_managed_user.xml b/core/res/res/values/required_apps_managed_user.xml
index a6fc573..3e75a4c 100644
--- a/core/res/res/values/required_apps_managed_user.xml
+++ b/core/res/res/values/required_apps_managed_user.xml
@@ -28,5 +28,6 @@
<item>com.android.providers.downloads</item>
<item>com.android.providers.downloads.ui</item>
<item>com.android.documentsui</item>
+ <item>com.android.webview</item>
</string-array>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2f9f4df..54c9479 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -6050,6 +6050,10 @@
<!-- Dialog text. Shown when the user is unable to send a text message from a personal app due to restrictions set
by their organization, and so must switch to a work app or cancel. [CHAR LIMIT=NONE] -->
<string name="miniresolver_sms_information">Your organization only allows you to send messages from work apps</string>
+ <!-- Dialog text. Shown as when redirecting Calls from Private Space to the main user. [CHAR LIMIT=NONE] -->
+ <string name="miniresolver_private_space_phone_information">"You can only make phone calls from your personal Phone app. Calls made with personal Phone will be added to your personal call history."</string>
+ <!-- Dialog text. Shown as when redirecting SMS and MMS messages from Private Space to the main user. [CHAR LIMIT=NONE] -->
+ <string name="miniresolver_private_space_messages_information">"You can only send SMS messages from your personal Messages app."</string>
<!-- Button option. Open the link in the personal browser. [CHAR LIMIT=NONE] -->
<string name="miniresolver_use_personal_browser">Use personal browser</string>
<!-- Button option. Open the link in the work browser. [CHAR LIMIT=NONE] -->
@@ -6448,6 +6452,15 @@
<!-- Communal profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] -->
<string name="profile_label_communal">Communal</string>
+ <!-- Accessibility label for managed profile user type [CHAR LIMIT=30] -->
+ <string name="accessibility_label_managed_profile">Work profile</string>
+ <!-- Accessibility label for private profile user type [CHAR LIMIT=30] -->
+ <string name="accessibility_label_private_profile">Private space</string>
+ <!-- Accessibility label for clone profile user type [CHAR LIMIT=30] -->
+ <string name="accessibility_label_clone_profile">Clone</string>
+ <!-- Accessibility label for clone profile user type [CHAR LIMIT=30] -->
+ <string name="accessibility_label_communal_profile">Communal</string>
+
<!-- Notification message used when a notification's normal message contains sensitive information [CHAR_LIMIT=NOTIF_BODY] -->
<string name="redacted_notification_message">Sensitive notification content hidden</string>
<!-- Notification action title used instead of a notification's normal title sensitive [CHAR_LIMIT=NOTIF_BODY] -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5945f81..a46dc04 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1685,4 +1685,9 @@
<item name="android:paddingStart">8dp</item>
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
+
+ <style name="AccessibilityButtonChooserDialog"
+ parent="@style/Theme.DeviceDefault.Resolver">
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+ </style>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 90132c3..972d8df 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -408,6 +408,7 @@
<java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" />
<java-symbol type="bool" name="config_supportsMultiDisplay" />
<java-symbol type="bool" name="config_leftRightSplitInPortrait" />
+ <java-symbol type="bool" name="config_flexibleSplitRatios" />
<java-symbol type="integer" name="config_supportsNonResizableMultiWindow" />
<java-symbol type="integer" name="config_respectsActivityMinWidthHeightMultiWindow" />
<java-symbol type="dimen" name="config_minPercentageMultiWindowSupportHeight" />
@@ -1110,6 +1111,10 @@
<java-symbol type="string" name="profile_label_work_3" />
<java-symbol type="string" name="profile_label_test" />
<java-symbol type="string" name="profile_label_communal" />
+ <java-symbol type="string" name="accessibility_label_managed_profile" />
+ <java-symbol type="string" name="accessibility_label_private_profile" />
+ <java-symbol type="string" name="accessibility_label_clone_profile" />
+ <java-symbol type="string" name="accessibility_label_communal_profile" />
<java-symbol type="string" name="mediasize_unknown_portrait" />
<java-symbol type="string" name="mediasize_unknown_landscape" />
<java-symbol type="string" name="mediasize_iso_a0" />
@@ -1628,6 +1633,8 @@
<java-symbol type="string" name="miniresolver_switch" />
<java-symbol type="string" name="miniresolver_call_information" />
<java-symbol type="string" name="miniresolver_sms_information" />
+ <java-symbol type="string" name="miniresolver_private_space_phone_information" />
+ <java-symbol type="string" name="miniresolver_private_space_messages_information" />
<java-symbol type="id" name="miniresolver_info_section" />
<java-symbol type="id" name="miniresolver_info_section_text" />
<java-symbol type="id" name="button_open" />
@@ -4212,6 +4219,7 @@
<java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" />
<java-symbol type="bool" name="config_unfoldTransitionEnabled" />
<java-symbol type="bool" name="config_unfoldTransitionHingeAngle" />
+ <java-symbol type="bool" name="config_unfoldTransitionHapticsEnabled" />
<java-symbol type="integer" name="config_unfoldTransitionHalfFoldedTimeout" />
<java-symbol type="array" name="config_perDeviceStateRotationLockDefaults" />
@@ -5416,4 +5424,7 @@
<!-- Back swipe thresholds -->
<java-symbol type="dimen" name="navigation_edge_action_progress_threshold" />
<java-symbol type="dimen" name="back_progress_non_linear_factor" />
+
+ <!-- For PowerManagerService to determine whether to use auto-suspend mode -->
+ <java-symbol type="bool" name="config_useAutoSuspend" />
</resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 9bb72d9..4d7c009 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -69,6 +69,9 @@
<!-- Brazil: 1-5 digits (standard system default, not country specific) -->
<shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963|4141|8000|2652" />
+ <!-- Botswana: 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="bw" pattern="\\d{1,5}" free="16641" />
+
<!-- Belarus: 4 digits -->
<shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
@@ -108,7 +111,7 @@
<shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}|4665" />
<!-- Dominican Republic: 1-6 digits (standard system default, not country specific) -->
- <shortcode country="do" pattern="\\d{1,6}" free="912892" />
+ <shortcode country="do" pattern="\\d{1,6}" free="912892|912" />
<!-- Ecuador: 1-6 digits (standard system default, not country specific) -->
<shortcode country="ec" pattern="\\d{1,6}" free="466453|18512" />
@@ -141,7 +144,7 @@
<shortcode country="ge" pattern="\\d{1,5}" premium="801[234]|888[239]" free="95201|95202|95203" />
<!-- Ghana: 4 digits, known premium codes listed -->
- <shortcode country="gh" pattern="\\d{4}" free="5041|3777" />
+ <shortcode country="gh" pattern="\\d{4}" free="5041|3777|2333" />
<!-- Greece: 5 digits (54xxx, 19yxx, x=0-9, y=0-5): http://www.cmtelecom.com/premium-sms/greece -->
<shortcode country="gr" pattern="\\d{5}" premium="54\\d{3}|19[0-5]\\d{2}" free="116\\d{3}|12115" />
@@ -195,7 +198,7 @@
<shortcode country="kz" pattern="\\d{4}" premium="335[02]|4161|444[469]|77[2359]0|8444|919[3-5]|968[2-5]" />
<!-- Kuwait: 1-5 digits (standard system default, not country specific) -->
- <shortcode country="kw" pattern="\\d{1,5}" free="1378|50420|94006|55991|50976" />
+ <shortcode country="kw" pattern="\\d{1,5}" free="1378|50420|94006|55991|50976|7112" />
<!-- Lithuania: 3-5 digits, known premium codes listed, plus EU -->
<shortcode country="lt" pattern="\\d{3,5}" premium="13[89]1|1394|16[34]5" free="116\\d{3}|1399|1324" />
@@ -223,7 +226,7 @@
<shortcode country="mz" pattern="\\d{1,5}" free="1714" />
<!-- Mexico: 4-7 digits (not confirmed), known premium codes listed -->
- <shortcode country="mx" pattern="\\d{4,7}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346|3030303" />
+ <shortcode country="mx" pattern="\\d{4,7}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346|3030303|81811" />
<!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
<shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668|66966" />
@@ -253,7 +256,7 @@
<shortcode country="ph" pattern="\\d{1,5}" free="2147|5495|5496" />
<!-- Pakistan -->
- <shortcode country="pk" pattern="\\d{1,6}" free="2057|9092|909203" />
+ <shortcode country="pk" pattern="\\d{1,6}" free="2057|9092|909203|909201" />
<!-- Palestine: 5 digits, known premium codes listed -->
<shortcode country="ps" pattern="\\d{1,5}" free="37477|6681" />
@@ -339,8 +342,8 @@
<!-- Venezuela: 1-6 digits (standard system default, not country specific) -->
<shortcode country="ve" pattern="\\d{1,6}" free="538352" />
- <!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
- <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055|8079" />
+ <!-- Vietnam: 1-6 digits (standard system default, not country specific) -->
+ <shortcode country="vn" pattern="\\d{1,6}" free="5001|9055|8079|90002|118989" />
<!-- Mayotte (French Territory): 1-5 digits (not confirmed) -->
<shortcode country="yt" pattern="\\d{1,5}" free="38600,36300,36303,959" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 04e90ba..436ba15 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -116,6 +116,7 @@
],
jni_libs: [
"libpowermanagertest_jni",
+ "libviewRootImplTest_jni",
"libworksourceparceltest_jni",
],
diff --git a/core/tests/coretests/jni/Android.bp b/core/tests/coretests/jni/Android.bp
index 7cc844a..538e7f3 100644
--- a/core/tests/coretests/jni/Android.bp
+++ b/core/tests/coretests/jni/Android.bp
@@ -67,3 +67,27 @@
],
gtest: false,
}
+
+cc_test_library {
+ name: "libviewRootImplTest_jni",
+ srcs: [
+ "ViewRootImplTestJni.cpp",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libandroid_runtime_lazy",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libnativehelper",
+ "libpowermanager",
+ "libutils",
+ ],
+ header_libs: ["jni_headers"],
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ gtest: false,
+}
diff --git a/core/tests/coretests/jni/ViewRootImplTestJni.cpp b/core/tests/coretests/jni/ViewRootImplTestJni.cpp
new file mode 100644
index 0000000..06a0f23
--- /dev/null
+++ b/core/tests/coretests/jni/ViewRootImplTestJni.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ViewRootImplTest"
+
+#include "jni.h"
+
+#include <android_util_Binder.h>
+#include <binder/IServiceManager.h>
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+#include <android/native_window_jni.h>
+#include <android/surface_control.h>
+#include <android/surface_control_jni.h>
+
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
+namespace android {
+
+static bool nativeCreateASurfaceControlFromSurface(JNIEnv* env, jclass /* obj */,
+ jobject jSurface) {
+ if (!jSurface) {
+ ALOGE("Surface object is null\n");
+ return false;
+ }
+
+ ANativeWindow* window = ANativeWindow_fromSurface(env, jSurface);
+ if (!window) {
+ ALOGE("Could not create ANW from jSurface\n");
+ return false;
+ }
+
+ ASurfaceControl* surfaceControl =
+ ASurfaceControl_createFromWindow(window, "ViewRootImplTestLayer");
+ if (!surfaceControl) {
+ ALOGE("Could not create SC from ANW\n");
+ return false;
+ }
+
+ ANativeWindow_release(window);
+ ASurfaceControl_release(surfaceControl);
+ return true;
+}
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
+{
+ JNIEnv* env;
+ const JNINativeMethod methodTable[] = {
+ /* name, signature, funcPtr */
+ { "nativeCreateASurfaceControlFromSurface", "(Landroid/view/Surface;)Z",
+ (void*) nativeCreateASurfaceControlFromSurface },
+ };
+
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ return JNI_ERR;
+ }
+
+ jniRegisterNativeMethods(env, "android/view/ViewRootImplTest", methodTable,
+ sizeof(methodTable) / sizeof(JNINativeMethod));
+
+ return JNI_VERSION_1_6;
+}
+
+} /* namespace android */
diff --git a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
index 9bb064c..62d89f6 100644
--- a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
@@ -19,10 +19,20 @@
import static android.os.storage.VolumeInfo.STATE_MOUNTED;
import static android.os.storage.VolumeInfo.STATE_UNMOUNTED;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Bundle;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.platform.test.annotations.Presubmit;
@@ -35,9 +45,11 @@
import junit.framework.TestCase;
import org.mockito.Mockito;
+import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
@Presubmit
@@ -93,9 +105,11 @@
private static final class MockedApplicationPackageManager extends ApplicationPackageManager {
private boolean mForceAllowOnExternal = false;
private boolean mAllow3rdPartyOnInternal = true;
+ private HashMap<ApplicationInfo, Resources> mResourcesMap;
public MockedApplicationPackageManager() {
super(null, null);
+ mResourcesMap = new HashMap<ApplicationInfo, Resources>();
}
public void setForceAllowOnExternal(boolean forceAllowOnExternal) {
@@ -106,6 +120,10 @@
mAllow3rdPartyOnInternal = allow3rdPartyOnInternal;
}
+ public void setResourcesForApplication(ApplicationInfo info, Resources resources) {
+ mResourcesMap.put(info, resources);
+ }
+
@Override
public boolean isForceAllowOnExternal(Context context) {
return mForceAllowOnExternal;
@@ -122,6 +140,16 @@
StorageManager storageManager, IPackageManager pm) {
return super.getPackageCandidateVolumes(app, storageManager, pm);
}
+
+ @Override
+ public Resources getResourcesForApplication(ApplicationInfo app)
+ throws NameNotFoundException {
+ if (mResourcesMap.containsKey(app)) {
+ return mResourcesMap.get(app);
+ }
+
+ return super.getResourcesForApplication(app);
+ }
}
private StorageManager getMockedStorageManager() {
@@ -254,4 +282,73 @@
verifyReturnedVolumes(candidates, sAdoptedVol);
}
}
+
+ public void testExtractPackageItemInfoAttributes_noServiceInfo() {
+ final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+ assertThat(appPkgMgr.extractPackageItemInfoAttributes(null, null, null,
+ new int[]{})).isNull();
+ }
+
+ public void testExtractPackageItemInfoAttributes_noMetaData() {
+ final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+ final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+ assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, null,
+ new int[]{})).isNull();
+ }
+
+ public void testExtractPackageItemInfoAttributes_noParser() {
+ final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+ final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+ final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+ when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+ assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, null,
+ new int[]{})).isNull();
+ }
+
+ public void testExtractPackageItemInfoAttributes_noMetaDataXml() {
+ final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+ final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+ final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+ when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+ when(packageItemInfo.loadXmlMetaData(any(), any())).thenReturn(null);
+ assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, null,
+ new int[]{})).isNull();
+ }
+
+ public void testExtractPackageItemInfoAttributes_nonMatchingRootTag() throws Exception {
+ final String rootTag = "rootTag";
+ final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+ final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+ final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+ final XmlResourceParser parser = Mockito.mock(XmlResourceParser.class);
+
+ when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+ packageItemInfo.metaData = new Bundle();
+ when(packageItemInfo.loadXmlMetaData(any(), any())).thenReturn(parser);
+ when(parser.next()).thenReturn(XmlPullParser.END_DOCUMENT);
+ when(parser.getName()).thenReturn(rootTag + "0");
+ assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, rootTag,
+ new int[]{})).isNull();
+ }
+
+ public void testExtractPackageItemInfoAttributes_successfulExtraction() throws Exception {
+ final String rootTag = "rootTag";
+ final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+ final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+ final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+ final XmlResourceParser parser = Mockito.mock(XmlResourceParser.class);
+ final Resources resources = Mockito.mock(Resources.class);
+ final TypedArray attributes = Mockito.mock(TypedArray.class);
+
+ when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+ packageItemInfo.metaData = new Bundle();
+ when(packageItemInfo.loadXmlMetaData(any(), any())).thenReturn(parser);
+ when(parser.next()).thenReturn(XmlPullParser.END_DOCUMENT);
+ when(parser.getName()).thenReturn(rootTag);
+ when(resources.obtainAttributes(any(), any())).thenReturn(attributes);
+ appPkgMgr.setResourcesForApplication(applicationInfo, resources);
+
+ assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, rootTag,
+ new int[]{})).isEqualTo(attributes);
+ }
}
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 5cc1ee4..7fb894a 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -86,6 +86,7 @@
import android.os.Parcelable;
import android.os.SystemProperties;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@@ -126,6 +127,7 @@
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
public void setUp() {
@@ -1835,6 +1837,36 @@
Assert.assertEquals(bitmap, resultBitmap);
}
+ @Test
+ public void testGetWhen_zero() {
+ Notification n = new Notification.Builder(mContext, "test")
+ .setWhen(0)
+ .build();
+
+ mSetFlagsRule.disableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+ assertThat(n.getWhen()).isEqualTo(0);
+
+ mSetFlagsRule.enableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+ assertThat(n.getWhen()).isEqualTo(n.creationTime);
+ }
+
+ @Test
+ public void testGetWhen_devProvidedNonZero() {
+ Notification n = new Notification.Builder(mContext, "test")
+ .setWhen(9)
+ .build();
+
+ mSetFlagsRule.disableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+ assertThat(n.getWhen()).isEqualTo(9);
+
+ mSetFlagsRule.enableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+ assertThat(n.getWhen()).isEqualTo(9);
+ }
+
private void assertValid(Notification.Colors c) {
// Assert that all colors are populated
assertThat(c.getBackgroundColor()).isNotEqualTo(Notification.COLOR_INVALID);
diff --git a/core/tests/coretests/src/android/text/LayoutTest.java b/core/tests/coretests/src/android/text/LayoutTest.java
index f60eff6..1c12362 100644
--- a/core/tests/coretests/src/android/text/LayoutTest.java
+++ b/core/tests/coretests/src/android/text/LayoutTest.java
@@ -18,9 +18,6 @@
import static com.android.graphics.hwui.flags.Flags.FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -47,6 +44,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.google.common.truth.Expect;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -63,7 +62,13 @@
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+ @Rule
+ public final Expect expect = Expect.create();
+
+ // Line count when using MockLayout
private static final int LINE_COUNT = 5;
+ // Actual line count when using StaticLayout
+ private static final int STATIC_LINE_COUNT = 9;
private static final int LINE_HEIGHT = 12;
private static final int LINE_DESCENT = 4;
private static final CharSequence LAYOUT_TEXT = "alwei\t;sdfs\ndf @";
@@ -655,8 +660,8 @@
@Test
@RequiresFlagsEnabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT)
public void highContrastTextEnabled_testDrawSelectionAndHighlight_drawsHighContrastSelectionAndHighlight() {
- Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
- mAlign, mSpacingMult, mSpacingAdd);
+ Layout layout = new StaticLayout(LAYOUT_TEXT, mTextPaint, mWidth,
+ mAlign, mSpacingMult, mSpacingAdd, /* includePad= */ false);
List<Path> highlightPaths = new ArrayList<>();
List<Paint> highlightPaints = new ArrayList<>();
@@ -677,9 +682,12 @@
layout.draw(c, highlightPaths, highlightPaints, selectionPath, selectionPaint,
/* cursorOffsetVertical= */ 0);
List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands();
- var textsDrawn = LINE_COUNT;
+ var textsDrawn = STATIC_LINE_COUNT;
var highlightsDrawn = 2;
- assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn);
+ var backgroundRectsDrawn = STATIC_LINE_COUNT;
+ expect.withMessage("wrong number of drawCommands: " + drawCommands)
+ .that(drawCommands.size())
+ .isEqualTo(textsDrawn + backgroundRectsDrawn + highlightsDrawn);
var highlightsFound = 0;
var curLineIndex = 0;
@@ -687,29 +695,26 @@
MockCanvas.DrawCommand drawCommand = drawCommands.get(i);
if (drawCommand.path != null) {
- assertThat(drawCommand.path).isEqualTo(selectionPath);
- assertThat(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW);
- assertThat(drawCommand.paint.getBlendMode()).isNotNull();
+ expect.that(drawCommand.path).isEqualTo(selectionPath);
+ expect.that(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW);
+ expect.that(drawCommand.paint.getBlendMode()).isNotNull();
highlightsFound++;
} else if (drawCommand.text != null) {
- int start = layout.getLineStart(curLineIndex);
- int end = layout.getLineEnd(curLineIndex);
- assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text);
curLineIndex++;
- assertWithMessage("highlight is drawn on top of text")
+ expect.withMessage("highlight is drawn on top of text")
.that(highlightsFound).isEqualTo(0);
}
}
- assertThat(highlightsFound).isEqualTo(2);
+ expect.that(highlightsFound).isEqualTo(2);
}
@Test
@RequiresFlagsEnabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT)
public void highContrastTextEnabled_testDrawHighlight_drawsHighContrastHighlight() {
- Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
- mAlign, mSpacingMult, mSpacingAdd);
+ Layout layout = new StaticLayout(LAYOUT_TEXT, mTextPaint, mWidth,
+ mAlign, mSpacingMult, mSpacingAdd, /* includePad= */ false);
List<Path> highlightPaths = new ArrayList<>();
List<Paint> highlightPaints = new ArrayList<>();
@@ -730,9 +735,12 @@
layout.draw(c, highlightPaths, highlightPaints, /* selectionPath= */ null,
/* selectionPaint= */ null, /* cursorOffsetVertical= */ 0);
List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands();
- var textsDrawn = LINE_COUNT;
+ var textsDrawn = STATIC_LINE_COUNT;
var highlightsDrawn = 1;
- assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn);
+ var backgroundRectsDrawn = STATIC_LINE_COUNT;
+ expect.withMessage("wrong number of drawCommands: " + drawCommands)
+ .that(drawCommands.size())
+ .isEqualTo(textsDrawn + backgroundRectsDrawn + highlightsDrawn);
var highlightsFound = 0;
var curLineIndex = 0;
@@ -740,29 +748,26 @@
MockCanvas.DrawCommand drawCommand = drawCommands.get(i);
if (drawCommand.path != null) {
- assertThat(drawCommand.path).isEqualTo(selectionPath);
- assertThat(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW);
- assertThat(drawCommand.paint.getBlendMode()).isNotNull();
+ expect.that(drawCommand.path).isEqualTo(selectionPath);
+ expect.that(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW);
+ expect.that(drawCommand.paint.getBlendMode()).isNotNull();
highlightsFound++;
} else if (drawCommand.text != null) {
- int start = layout.getLineStart(curLineIndex);
- int end = layout.getLineEnd(curLineIndex);
- assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text);
curLineIndex++;
- assertWithMessage("highlight is drawn on top of text")
+ expect.withMessage("highlight is drawn on top of text")
.that(highlightsFound).isEqualTo(0);
}
}
- assertThat(highlightsFound).isEqualTo(1);
+ expect.that(highlightsFound).isEqualTo(1);
}
@Test
@RequiresFlagsEnabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT)
public void highContrastTextDisabledByDefault_testDrawHighlight_drawsNormalHighlightBehind() {
- Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
- mAlign, mSpacingMult, mSpacingAdd);
+ Layout layout = new StaticLayout(LAYOUT_TEXT, mTextPaint, mWidth,
+ mAlign, mSpacingMult, mSpacingAdd, /* includePad= */ false);
List<Path> highlightPaths = new ArrayList<>();
List<Paint> highlightPaints = new ArrayList<>();
@@ -782,9 +787,12 @@
layout.draw(c, highlightPaths, highlightPaints, /* selectionPath= */ null,
/* selectionPaint= */ null, /* cursorOffsetVertical= */ 0);
List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands();
- var textsDrawn = LINE_COUNT;
+ var textsDrawn = STATIC_LINE_COUNT;
var highlightsDrawn = 1;
- assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn);
+ var backgroundRectsDrawn = 0;
+ expect.withMessage("wrong number of drawCommands: " + drawCommands)
+ .that(drawCommands.size())
+ .isEqualTo(textsDrawn + backgroundRectsDrawn + highlightsDrawn);
var highlightsFound = 0;
var curLineIndex = 0;
@@ -792,29 +800,26 @@
MockCanvas.DrawCommand drawCommand = drawCommands.get(i);
if (drawCommand.path != null) {
- assertThat(drawCommand.path).isEqualTo(selectionPath);
- assertThat(drawCommand.paint.getColor()).isEqualTo(Color.CYAN);
- assertThat(drawCommand.paint.getBlendMode()).isNull();
+ expect.that(drawCommand.path).isEqualTo(selectionPath);
+ expect.that(drawCommand.paint.getColor()).isEqualTo(Color.CYAN);
+ expect.that(drawCommand.paint.getBlendMode()).isNull();
highlightsFound++;
} else if (drawCommand.text != null) {
- int start = layout.getLineStart(curLineIndex);
- int end = layout.getLineEnd(curLineIndex);
- assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text);
curLineIndex++;
- assertWithMessage("highlight is drawn behind text")
+ expect.withMessage("highlight is drawn behind text")
.that(highlightsFound).isGreaterThan(0);
}
}
- assertThat(highlightsFound).isEqualTo(1);
+ expect.that(highlightsFound).isEqualTo(1);
}
@Test
@RequiresFlagsDisabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT)
public void highContrastTextEnabledButFlagOff_testDrawHighlight_drawsNormalHighlightBehind() {
- Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth,
- mAlign, mSpacingMult, mSpacingAdd);
+ Layout layout = new StaticLayout(LAYOUT_TEXT, mTextPaint, mWidth,
+ mAlign, mSpacingMult, mSpacingAdd, /* includePad= */ false);
List<Path> highlightPaths = new ArrayList<>();
List<Paint> highlightPaints = new ArrayList<>();
@@ -835,9 +840,12 @@
layout.draw(c, highlightPaths, highlightPaints, /* selectionPath= */ null,
/* selectionPaint= */ null, /* cursorOffsetVertical= */ 0);
List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands();
- var textsDrawn = LINE_COUNT;
+ var textsDrawn = STATIC_LINE_COUNT;
var highlightsDrawn = 1;
- assertThat(drawCommands.size()).isEqualTo(textsDrawn + highlightsDrawn);
+ var backgroundRectsDrawn = 0;
+ expect.withMessage("wrong number of drawCommands: " + drawCommands)
+ .that(drawCommands.size())
+ .isEqualTo(textsDrawn + backgroundRectsDrawn + highlightsDrawn);
var highlightsFound = 0;
var curLineIndex = 0;
@@ -845,33 +853,84 @@
MockCanvas.DrawCommand drawCommand = drawCommands.get(i);
if (drawCommand.path != null) {
- assertThat(drawCommand.path).isEqualTo(selectionPath);
- assertThat(drawCommand.paint.getColor()).isEqualTo(Color.CYAN);
- assertThat(drawCommand.paint.getBlendMode()).isNull();
+ expect.that(drawCommand.path).isEqualTo(selectionPath);
+ expect.that(drawCommand.paint.getColor()).isEqualTo(Color.CYAN);
+ expect.that(drawCommand.paint.getBlendMode()).isNull();
highlightsFound++;
} else if (drawCommand.text != null) {
- int start = layout.getLineStart(curLineIndex);
- int end = layout.getLineEnd(curLineIndex);
- assertEquals(LAYOUT_TEXT.toString().substring(start, end), drawCommand.text);
curLineIndex++;
- assertWithMessage("highlight is drawn behind text")
+ expect.withMessage("highlight is drawn behind text")
.that(highlightsFound).isGreaterThan(0);
}
}
- assertThat(highlightsFound).isEqualTo(1);
+ expect.that(highlightsFound).isEqualTo(1);
}
@Test
public void mockCanvasHighContrastOverridesCorrectly() {
var canvas = new MockCanvas(100, 100);
- assertThat(canvas.isHighContrastTextEnabled()).isFalse();
+ expect.that(canvas.isHighContrastTextEnabled()).isFalse();
canvas.setHighContrastTextEnabled(true);
- assertThat(canvas.isHighContrastTextEnabled()).isTrue();
+ expect.that(canvas.isHighContrastTextEnabled()).isTrue();
canvas.setHighContrastTextEnabled(false);
- assertThat(canvas.isHighContrastTextEnabled()).isFalse();
+ expect.that(canvas.isHighContrastTextEnabled()).isFalse();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT)
+ public void highContrastTextEnabled_testDrawLightText_drawsBlackBackgroundRects() {
+ mTextPaint.setColor(Color.parseColor("#CCAA33"));
+ Layout layout = new StaticLayout(LAYOUT_TEXT, mTextPaint, mWidth,
+ mAlign, mSpacingMult, mSpacingAdd, /* includePad= */ false);
+
+ final int width = 256;
+ final int height = 256;
+ MockCanvas c = new MockCanvas(width, height);
+ c.setHighContrastTextEnabled(true);
+ layout.draw(
+ c,
+ /* highlightPaths= */ null,
+ /* highlightPaints= */ null,
+ /* selectionPath= */ null,
+ /* selectionPaint= */ null,
+ /* cursorOffsetVertical= */ 0
+ );
+ List<MockCanvas.DrawCommand> drawCommands = c.getDrawCommands();
+ var textsDrawn = STATIC_LINE_COUNT;
+ var highlightsDrawn = 0;
+ var backgroundRectsDrawn = STATIC_LINE_COUNT;
+ expect.withMessage("wrong number of drawCommands: " + drawCommands)
+ .that(drawCommands.size())
+ .isEqualTo(textsDrawn + backgroundRectsDrawn + highlightsDrawn);
+
+ int numBackgroundsFound = 0;
+ var curLineIndex = 0;
+ for (int i = 0; i < drawCommands.size(); i++) {
+ MockCanvas.DrawCommand drawCommand = drawCommands.get(i);
+
+ if (drawCommand.rect != null) {
+ numBackgroundsFound++;
+ expect.that(drawCommand.paint.getColor()).isEqualTo(Color.BLACK);
+ expect.that(drawCommand.rect.height()).isAtLeast(LINE_HEIGHT);
+ expect.that(drawCommand.rect.width()).isGreaterThan(0);
+ float expectedY = (numBackgroundsFound) * (LINE_HEIGHT + LINE_DESCENT);
+ expect.that(drawCommand.rect.bottom).isAtLeast(expectedY);
+ } else if (drawCommand.text != null) {
+ // draw text
+ curLineIndex++;
+
+ expect.withMessage("background is drawn on top of text")
+ .that(numBackgroundsFound).isEqualTo(backgroundRectsDrawn);
+ } else {
+ fail("unexpected path drawn");
+ }
+ }
+
+ // One for each line
+ expect.that(numBackgroundsFound).isEqualTo(backgroundRectsDrawn);
}
private static final class MockCanvas extends Canvas {
@@ -881,22 +940,46 @@
public final float x;
public final float y;
public final Path path;
+ public final RectF rect;
public final Paint paint;
DrawCommand(String text, float x, float y, Paint paint) {
this.text = text;
this.x = x;
this.y = y;
- this.paint = paint;
+ this.paint = new Paint(paint);
path = null;
+ rect = null;
}
DrawCommand(Path path, Paint paint) {
this.path = path;
- this.paint = paint;
+ this.paint = new Paint(paint);
y = 0;
x = 0;
text = null;
+ rect = null;
+ }
+
+ DrawCommand(RectF rect, Paint paint) {
+ this.rect = new RectF(rect);
+ this.paint = new Paint(paint);
+ path = null;
+ y = 0;
+ x = 0;
+ text = null;
+ }
+
+ @Override
+ public String toString() {
+ return "DrawCommand{"
+ + "text='" + text + '\''
+ + ", x=" + x
+ + ", y=" + y
+ + ", path=" + path
+ + ", rect=" + rect
+ + ", paint=" + paint
+ + '}';
}
}
@@ -956,6 +1039,11 @@
mDrawCommands.add(new DrawCommand(path, p));
}
+ @Override
+ public void drawRect(RectF rect, Paint p) {
+ mDrawCommands.add(new DrawCommand(rect, p));
+ }
+
List<DrawCommand> getDrawCommands() {
return mDrawCommands;
}
diff --git a/core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java b/core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java
new file mode 100644
index 0000000..c00ebe4
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java
@@ -0,0 +1,257 @@
+/*
+ * 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;
+
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.window.BackEvent.EDGE_LEFT;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+import android.content.Context;
+import android.graphics.Insets;
+import android.platform.test.annotations.Presubmit;
+import android.view.animation.BackGestureInterpolator;
+import android.view.animation.Interpolator;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+import android.window.BackEvent;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link ImeBackAnimationController}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:ImeBackAnimationControllerTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ImeBackAnimationControllerTest {
+
+ private static final float PEEK_FRACTION = 0.1f;
+ private static final Interpolator BACK_GESTURE = new BackGestureInterpolator();
+ private static final int IME_HEIGHT = 200;
+ private static final Insets IME_INSETS = Insets.of(0, 0, 0, IME_HEIGHT);
+
+ @Mock
+ private InsetsController mInsetsController;
+ @Mock
+ private WindowInsetsAnimationController mWindowInsetsAnimationController;
+ @Mock
+ private ViewRootInsetsControllerHost mViewRootInsetsControllerHost;
+
+ private ViewRootImpl mViewRoot;
+ private ImeBackAnimationController mBackAnimationController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ InputMethodManager inputMethodManager = context.getSystemService(
+ InputMethodManager.class);
+ // cannot mock ViewRootImpl since it's final.
+ mViewRoot = new ViewRootImpl(context, context.getDisplayNoVerify());
+ try {
+ mViewRoot.setView(new TextView(context), new WindowManager.LayoutParams(), null);
+ } catch (WindowManager.BadTokenException e) {
+ // activity isn't running, we will ignore BadTokenException.
+ }
+ mBackAnimationController = new ImeBackAnimationController(mViewRoot, mInsetsController);
+
+ when(mWindowInsetsAnimationController.getHiddenStateInsets()).thenReturn(Insets.NONE);
+ when(mWindowInsetsAnimationController.getShownStateInsets()).thenReturn(IME_INSETS);
+ when(mWindowInsetsAnimationController.getCurrentInsets()).thenReturn(IME_INSETS);
+ when(mInsetsController.getHost()).thenReturn(mViewRootInsetsControllerHost);
+ when(mViewRootInsetsControllerHost.getInputMethodManager()).thenReturn(
+ inputMethodManager);
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ @Test
+ public void testAdjustResizeWithAppWindowInsetsListenerPlaysAnim() {
+ // setup ViewRoot with InsetsAnimationCallback and softInputMode=adjustResize
+ mViewRoot.getView()
+ .setWindowInsetsAnimationCallback(mock(WindowInsetsAnimation.Callback.class));
+ mViewRoot.mWindowAttributes.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
+ // start back gesture
+ mBackAnimationController.onBackStarted(new BackEvent(0f, 0f, 0f, EDGE_LEFT));
+ // verify that ImeBackAnimationController takes control over IME insets
+ verify(mInsetsController, times(1)).controlWindowInsetsAnimation(anyInt(), any(), any(),
+ anyBoolean(), anyLong(), any(), anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testAdjustResizeWithoutAppWindowInsetsListenerNotPlayingAnim() {
+ // setup ViewRoot with softInputMode=adjustResize
+ mViewRoot.mWindowAttributes.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
+ // start back gesture
+ mBackAnimationController.onBackStarted(new BackEvent(0f, 0f, 0f, EDGE_LEFT));
+ // progress back gesture
+ mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, 0.5f, EDGE_LEFT));
+ // commit back gesture
+ mBackAnimationController.onBackInvoked();
+ // verify that InsetsController#hide is called
+ verify(mInsetsController, times(1)).hide(ime());
+ // verify that ImeBackAnimationController does not take control over IME insets
+ verify(mInsetsController, never()).controlWindowInsetsAnimation(anyInt(), any(), any(),
+ anyBoolean(), anyLong(), any(), anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testAdjustPanScrollsViewRoot() {
+ // simulate view root being panned upwards by 50px
+ int appPan = -50;
+ mViewRoot.setScrollY(appPan);
+ // setup ViewRoot with softInputMode=adjustPan
+ mViewRoot.mWindowAttributes.softInputMode = SOFT_INPUT_ADJUST_PAN;
+
+ // start back gesture
+ WindowInsetsAnimationControlListener animationControlListener = startBackGesture();
+ // simulate ImeBackAnimationController receiving control
+ animationControlListener.onReady(mWindowInsetsAnimationController, ime());
+
+ // progress back gesture
+ float progress = 0.5f;
+ mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, progress, EDGE_LEFT));
+
+ // verify that view root is scrolled by expected amount
+ float interpolatedProgress = BACK_GESTURE.getInterpolation(progress);
+ int expectedViewRootScroll =
+ (int) (appPan * (1 - interpolatedProgress * PEEK_FRACTION));
+ assertEquals(mViewRoot.getScrollY(), expectedViewRootScroll);
+ }
+
+ @Test
+ public void testNewGestureAfterCancelSeamlessTakeover() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // start back gesture
+ WindowInsetsAnimationControlListener animationControlListener = startBackGesture();
+ // simulate ImeBackAnimationController receiving control
+ animationControlListener.onReady(mWindowInsetsAnimationController, ime());
+ // verify initial animation insets are set
+ verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha(
+ eq(Insets.of(0, 0, 0, IME_HEIGHT)), eq(1f), anyFloat());
+
+ // progress back gesture
+ mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, 0.5f, EDGE_LEFT));
+
+ // cancel back gesture
+ mBackAnimationController.onBackCancelled();
+ // verify that InsetsController does not notified of a hide-anim (because the gesture
+ // was cancelled)
+ verify(mInsetsController, never()).setPredictiveBackImeHideAnimInProgress(eq(true));
+
+ Mockito.clearInvocations(mWindowInsetsAnimationController);
+ // restart back gesture
+ mBackAnimationController.onBackStarted(new BackEvent(0f, 0f, 0f, EDGE_LEFT));
+ // verify that animation controller is reused and initial insets are set immediately
+ verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha(
+ eq(Insets.of(0, 0, 0, IME_HEIGHT)), eq(1f), anyFloat());
+ });
+ }
+
+ @Test
+ public void testImeInsetsManipulationCurve() {
+ // start back gesture
+ WindowInsetsAnimationControlListener animationControlListener = startBackGesture();
+ // simulate ImeBackAnimationController receiving control
+ animationControlListener.onReady(mWindowInsetsAnimationController, ime());
+ // verify initial animation insets are set
+ verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha(
+ eq(Insets.of(0, 0, 0, IME_HEIGHT)), eq(1f), anyFloat());
+
+ Mockito.clearInvocations(mWindowInsetsAnimationController);
+ // progress back gesture
+ float progress = 0.5f;
+ mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, progress, EDGE_LEFT));
+ // verify correct ime insets manipulation
+ float interpolatedProgress = BACK_GESTURE.getInterpolation(progress);
+ int expectedInset =
+ (int) (IME_HEIGHT - interpolatedProgress * PEEK_FRACTION * IME_HEIGHT);
+ verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha(
+ eq(Insets.of(0, 0, 0, expectedInset)), eq(1f), anyFloat());
+ }
+
+ @Test
+ public void testOnReadyAfterGestureFinished() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // start back gesture
+ WindowInsetsAnimationControlListener animationControlListener = startBackGesture();
+
+ // progress back gesture
+ mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, 0.5f, EDGE_LEFT));
+
+ // commit back gesture
+ mBackAnimationController.onBackInvoked();
+
+ // verify setInsetsAndAlpha never called due onReady delayed
+ verify(mWindowInsetsAnimationController, never()).setInsetsAndAlpha(any(), anyInt(),
+ anyFloat());
+ verify(mInsetsController, never()).setPredictiveBackImeHideAnimInProgress(eq(true));
+
+ // simulate ImeBackAnimationController receiving control
+ animationControlListener.onReady(mWindowInsetsAnimationController, ime());
+
+ // verify setInsetsAndAlpha immediately called
+ verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha(
+ eq(Insets.of(0, 0, 0, IME_HEIGHT)), eq(1f), anyFloat());
+ // verify post-commit hide anim has started
+ verify(mInsetsController, times(1)).setPredictiveBackImeHideAnimInProgress(eq(true));
+ });
+ }
+
+ private WindowInsetsAnimationControlListener startBackGesture() {
+ // start back gesture
+ mBackAnimationController.onBackStarted(new BackEvent(0f, 0f, 0f, EDGE_LEFT));
+
+ // verify controlWindowInsetsAnimation is called and capture animationControlListener
+ ArgumentCaptor<WindowInsetsAnimationControlListener> animationControlListener =
+ ArgumentCaptor.forClass(WindowInsetsAnimationControlListener.class);
+ verify(mInsetsController, times(1)).controlWindowInsetsAnimation(anyInt(), any(),
+ animationControlListener.capture(), anyBoolean(), anyLong(), any(), anyInt(),
+ anyBoolean());
+
+ return animationControlListener.getValue();
+ }
+}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 4fb85c1f..f05390d 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -21,6 +21,7 @@
import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_RESIZE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
+import static android.view.InsetsController.ANIMATION_TYPE_USER;
import static android.view.InsetsSource.FLAG_ANIMATE_RESIZING;
import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
@@ -925,6 +926,95 @@
});
}
+ @Test
+ public void testImeRequestedVisibleDuringPredictiveBackAnim() {
+ prepareControls();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // show ime as initial state
+ mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
+ mController.cancelExistingAnimations(); // fast forward show animation
+ assertTrue(mController.getState().peekSource(ID_IME).isVisible());
+
+ // start control request (for predictive back animation)
+ WindowInsetsAnimationControlListener listener =
+ mock(WindowInsetsAnimationControlListener.class);
+ mController.controlWindowInsetsAnimation(ime(), /*cancellationSignal*/ null,
+ listener, /*fromIme*/ false, /*duration*/ -1, /*interpolator*/ null,
+ ANIMATION_TYPE_USER, /*fromPredictiveBack*/ true);
+
+ // Verify that onReady is called (after next predraw)
+ mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+ verify(listener).onReady(notNull(), eq(ime()));
+
+ // verify that insets are requested visible during animation
+ assertTrue(isRequestedVisible(mController, ime()));
+ });
+ }
+
+ @Test
+ public void testImeShowRequestCancelsPredictiveBackPostCommitAnim() {
+ prepareControls();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // show ime as initial state
+ mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
+ mController.cancelExistingAnimations(); // fast forward show animation
+ mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+ assertTrue(mController.getState().peekSource(ID_IME).isVisible());
+
+ // start control request (for predictive back animation)
+ WindowInsetsAnimationControlListener listener =
+ mock(WindowInsetsAnimationControlListener.class);
+ mController.controlWindowInsetsAnimation(ime(), /*cancellationSignal*/ null,
+ listener, /*fromIme*/ false, /*duration*/ -1, /*interpolator*/ null,
+ ANIMATION_TYPE_USER, /*fromPredictiveBack*/ true);
+
+ // verify that controller
+ // has ANIMATION_TYPE_USER set for ime()
+ assertEquals(ANIMATION_TYPE_USER, mController.getAnimationType(ime()));
+
+ // verify show request is ignored during pre commit phase of predictive back anim
+ mController.show(ime(), true /* fromIme */, null /* statsToken */);
+ assertEquals(ANIMATION_TYPE_USER, mController.getAnimationType(ime()));
+
+ // verify show request is applied during post commit phase of predictive back anim
+ mController.setPredictiveBackImeHideAnimInProgress(true);
+ mController.show(ime(), true /* fromIme */, null /* statsToken */);
+ assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ime()));
+
+ // additionally verify that IME ends up visible
+ mController.cancelExistingAnimations();
+ assertTrue(mController.getState().peekSource(ID_IME).isVisible());
+ });
+ }
+
+ @Test
+ public void testImeHideRequestIgnoredDuringPredictiveBackPostCommitAnim() {
+ prepareControls();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // show ime as initial state
+ mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty());
+ mController.cancelExistingAnimations(); // fast forward show animation
+ mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+ assertTrue(mController.getState().peekSource(ID_IME).isVisible());
+
+ // start control request (for predictive back animation)
+ WindowInsetsAnimationControlListener listener =
+ mock(WindowInsetsAnimationControlListener.class);
+ mController.controlWindowInsetsAnimation(ime(), /*cancellationSignal*/ null,
+ listener, /*fromIme*/ false, /*duration*/ -1, /*interpolator*/ null,
+ ANIMATION_TYPE_USER, /*fromPredictiveBack*/ true);
+
+ // verify that controller has ANIMATION_TYPE_USER set for ime()
+ assertEquals(ANIMATION_TYPE_USER, mController.getAnimationType(ime()));
+
+ // verify hide request is ignored during post commit phase of predictive back anim
+ // since IME is already animating away
+ mController.setPredictiveBackImeHideAnimInProgress(true);
+ mController.hide(ime(), true /* fromIme */, null /* statsToken */);
+ assertEquals(ANIMATION_TYPE_USER, mController.getAnimationType(ime()));
+ });
+ }
+
private void waitUntilNextFrame() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
index 4cdc993..32aec1a 100644
--- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -19,6 +19,7 @@
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
+import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
@@ -35,6 +36,7 @@
import android.annotation.NonNull;
import android.app.Activity;
+import android.app.Instrumentation;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
@@ -46,6 +48,7 @@
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -435,6 +438,129 @@
waitForAfterDraw();
}
+ @Test
+ @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+ FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY
+ })
+ public void willNotDrawUsesCategory() throws Throwable {
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.setWillNotDraw(true);
+ mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_LOW);
+ });
+ waitForFrameRateCategoryToSettle();
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_LOW,
+ mViewRoot.getLastPreferredFrameRateCategory()));
+ });
+ waitForAfterDraw();
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL);
+ mMovingView.setAlpha(0.9f);
+ runAfterDraw(() -> {
+ assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+ mViewRoot.getLastPreferredFrameRateCategory());
+ });
+ });
+ waitForAfterDraw();
+ }
+
+ /**
+ * A common behavior is for two different views to be invalidated in succession, but
+ * intermittently. We want to treat this as an intermittent invalidation.
+ *
+ * This test will only succeed on non-cuttlefish devices, so it is commented out
+ * for potential manual testing.
+ */
+// @Test
+ @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+ FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
+ public void intermittentDoubleInvalidate() throws Throwable {
+ View parent = (View) mMovingView.getParent();
+ mActivityRule.runOnUiThread(() -> {
+ parent.setWillNotDraw(false);
+ // Make sure the View is large
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.width = parent.getWidth();
+ layoutParams.height = parent.getHeight();
+ mMovingView.setLayoutParams(layoutParams);
+ });
+ waitForFrameRateCategoryToSettle();
+ for (int i = 0; i < 5; i++) {
+ int expectedCategory;
+ if (i < 4) {
+ // not intermittent yet.
+ // It takes 2 frames of intermittency before Views vote as intermittent.
+ // It takes 4 more frames for the category to drop to the next category.
+ expectedCategory =
+ toolkitFrameRateDefaultNormalReadOnly() ? FRAME_RATE_CATEGORY_NORMAL
+ : FRAME_RATE_CATEGORY_HIGH;
+ } else {
+ // intermittent
+ expectedCategory = FRAME_RATE_CATEGORY_NORMAL;
+ }
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ runAfterDraw(() -> assertEquals(expectedCategory,
+ mViewRoot.getLastPreferredFrameRateCategory()));
+ });
+ waitForAfterDraw();
+ mActivityRule.runOnUiThread(() -> {
+ parent.invalidate();
+ runAfterDraw(() -> assertEquals(expectedCategory,
+ mViewRoot.getLastPreferredFrameRateCategory()));
+ });
+ waitForAfterDraw();
+ Thread.sleep(90);
+ }
+ }
+
+ // When a view has two motions that offset each other, the overall motion
+ // should be canceled and be considered unmoved.
+ @Test
+ @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+ FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY
+ })
+ public void sameFrameMotion() throws Throwable {
+ mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+ waitForFrameRateCategoryToSettle();
+
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.offsetLeftAndRight(10);
+ mMovingView.offsetLeftAndRight(-10);
+ mMovingView.offsetTopAndBottom(100);
+ mMovingView.offsetTopAndBottom(-100);
+ mMovingView.invalidate();
+ runAfterDraw(() -> {
+ assertEquals(0f, mViewRoot.getLastPreferredFrameRate(), 0f);
+ assertEquals(FRAME_RATE_CATEGORY_NO_PREFERENCE,
+ mViewRoot.getLastPreferredFrameRateCategory());
+ });
+ });
+ waitForAfterDraw();
+ }
+
+ @Test
+ @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+ FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY
+ })
+ public void frameRateReset() throws Throwable {
+ mMovingView.setRequestedFrameRate(120f);
+ waitForFrameRateCategoryToSettle();
+ mActivityRule.runOnUiThread(() -> mMovingView.setVisibility(View.INVISIBLE));
+
+ final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+ for (int i = 0; i < 120; i++) {
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.getParent().onDescendantInvalidated(mMovingView, mMovingView);
+ });
+ instrumentation.waitForIdleSync();
+ }
+
+ assertEquals(0f, mViewRoot.getLastPreferredFrameRate(), 0f);
+ }
+
private void runAfterDraw(@NonNull Runnable runnable) {
Handler handler = new Handler(Looper.getMainLooper());
mAfterDrawLatch = new CountDownLatch(1);
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 20fb6e3..7c098f2 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -17,6 +17,7 @@
package android.view;
import static android.view.accessibility.Flags.FLAG_FORCE_INVERT_COLOR;
+import static android.view.flags.Flags.FLAG_ADD_SCHANDLE_TO_VRI_SURFACE;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_BY_SIZE_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY;
@@ -27,7 +28,6 @@
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
-import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
@@ -124,6 +124,10 @@
private CountDownLatch mAfterDrawLatch;
private Throwable mAfterDrawThrowable;
+ private native boolean nativeCreateASurfaceControlFromSurface(Surface surface);
+ static {
+ System.loadLibrary("viewRootImplTest_jni");
+ }
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@@ -1134,6 +1138,8 @@
mView = new View(sContext);
WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
+ int expected = toolkitFrameRateDefaultNormalReadOnly()
+ ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
sInstrumentation.runOnMainSync(() -> {
WindowManager wm = sContext.getSystemService(WindowManager.class);
@@ -1153,51 +1159,42 @@
Thread.sleep(delay);
sInstrumentation.runOnMainSync(() -> {
mView.invalidate();
- int expected = toolkitFrameRateDefaultNormalReadOnly()
- ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
runAfterDraw(() -> assertEquals(expected,
mViewRootImpl.getLastPreferredFrameRateCategory()));
});
waitForAfterDraw();
- // reset the frame rate category counts
- for (int i = 0; i < 5; i++) {
- sInstrumentation.runOnMainSync(() -> {
- mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
- mView.invalidate();
- });
- sInstrumentation.waitForIdleSync();
- }
-
// In transition from frequent update to infrequent update
Thread.sleep(delay);
sInstrumentation.runOnMainSync(() -> {
- mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
mView.invalidate();
- runAfterDraw(() -> {
- assertEquals(FRAME_RATE_CATEGORY_NO_PREFERENCE,
- mViewRootImpl.getLastPreferredFrameRateCategory());
- });
- });
- waitForAfterDraw();
- Thread.sleep(delay);
- sInstrumentation.runOnMainSync(() -> {
- mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
- mView.invalidate();
- runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NO_PREFERENCE,
+ runAfterDraw(() -> assertEquals(expected,
mViewRootImpl.getLastPreferredFrameRateCategory()));
});
- waitForAfterDraw();
// Infrequent update
Thread.sleep(delay);
sInstrumentation.runOnMainSync(() -> {
- mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
mView.invalidate();
runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
mViewRootImpl.getLastPreferredFrameRateCategory()));
});
waitForAfterDraw();
+
+ // When the View vote, it's still considered as intermittent update state
+ sInstrumentation.runOnMainSync(() -> {
+ mView.invalidate();
+ runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+ mViewRootImpl.getLastPreferredFrameRateCategory()));
+ });
+ waitForAfterDraw();
+
+ // Becomes frequent update state
+ sInstrumentation.runOnMainSync(() -> {
+ mView.invalidate();
+ runAfterDraw(() -> assertEquals(expected,
+ mViewRootImpl.getLastPreferredFrameRateCategory()));
+ });
}
/**
@@ -1364,6 +1361,23 @@
assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.FORCE_DARK);
}
+ @Test
+ @RequiresFlagsEnabled({FLAG_ADD_SCHANDLE_TO_VRI_SURFACE})
+ public void testASurfaceControl_createFromWindow() throws Throwable {
+ mView = new View(sContext);
+ attachViewToWindow(mView);
+ sInstrumentation.runOnMainSync(() -> {
+ mView.setVisibility(View.VISIBLE);
+ mView.invalidate();
+ runAfterDraw(()->{});
+ });
+ waitForAfterDraw();
+ mViewRootImpl = mView.getViewRootImpl();
+ Log.d(TAG, "mViewRootImpl.mSurface=" + mViewRootImpl.mSurface);
+ assertTrue("Could not create ASurfaceControl from VRI surface",
+ nativeCreateASurfaceControlFromSurface(mViewRootImpl.mSurface));
+ }
+
private boolean setForceDarkSysProp(boolean isForceDarkEnabled) {
try {
SystemProperties.set(
diff --git a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
index 0361546..6c8dcd3 100644
--- a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
+++ b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
@@ -77,7 +77,7 @@
Color.RED, Color.BLUE);
mSnapshotSurface = new SnapshotDrawerUtils.SnapshotSurface(
- new SurfaceControl(), snapshot, "Test", taskBounds);
+ new SurfaceControl(), snapshot, "Test");
mSnapshotSurface.initiateSystemBarPainter(windowFlags, 0, 0,
taskDescription, WindowInsets.Type.defaultVisible());
}
@@ -167,14 +167,16 @@
@Test
public void testCalculateSnapshotCrop_taskNotOnTop() {
final Rect contentInsets = new Rect(0, 10, 0, 10);
- setupSurface(100, 100, contentInsets, 0, new Rect(0, 50, 100, 150));
+ final Rect bounds = new Rect(0, 50, 100, 150);
+ setupSurface(100, 100, contentInsets, 0, bounds);
+ mSnapshotSurface.setFrames(bounds, contentInsets);
assertEquals(new Rect(0, 10, 100, 90),
mSnapshotSurface.calculateSnapshotCrop(contentInsets));
}
@Test
public void testCalculateSnapshotCrop_navBarLeft() {
- final Rect contentInsets = new Rect(0, 10, 0, 0);
+ final Rect contentInsets = new Rect(10, 0, 0, 0);
setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
assertEquals(new Rect(10, 0, 100, 100),
mSnapshotSurface.calculateSnapshotCrop(contentInsets));
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index 36bede9..1a8e75a 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -34,11 +34,13 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.IWindow;
import android.view.IWindowSession;
+import android.view.ImeBackAnimationController;
import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
@@ -76,6 +78,12 @@
@Mock
private OnBackAnimationCallback mCallback2;
@Mock
+ private ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback mImeCallback;
+ @Mock
+ private ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback mDefaultImeCallback;
+ @Mock
+ private ImeBackAnimationController mImeBackAnimationController;
+ @Mock
private Context mContext;
@Mock
private ApplicationInfo mApplicationInfo;
@@ -102,7 +110,7 @@
doReturn(mApplicationInfo).when(mContext).getApplicationInfo();
mDispatcher = new WindowOnBackInvokedDispatcher(mContext, Looper.getMainLooper());
- mDispatcher.attachToWindow(mWindowSession, mWindow, null);
+ mDispatcher.attachToWindow(mWindowSession, mWindow, mImeBackAnimationController);
}
private void waitForIdle() {
@@ -403,7 +411,9 @@
mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1);
OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo();
- mDispatcher.onMotionEvent(mMotionEvent);
+ // Send motion event in View's main thread.
+ final Handler main = Handler.getMain();
+ main.runWithScissors(() -> mDispatcher.onMotionEvent(mMotionEvent), 100);
assertFalse(mDispatcher.mTouchTracker.isActive());
callbackInfo.getCallback().onBackStarted(mBackEvent);
@@ -411,8 +421,33 @@
assertTrue(mDispatcher.isDispatching());
assertTrue(mDispatcher.mTouchTracker.isActive());
- mDispatcher.onMotionEvent(mMotionEvent);
+ main.runWithScissors(() -> mDispatcher.onMotionEvent(mMotionEvent), 100);
waitForIdle();
- verify(mCallback1).onBackProgressed(any());
+ // onBackPressed is called from animator, so it can happen more than once.
+ verify(mCallback1, atLeast(1)).onBackProgressed(any());
+ }
+
+ @Test
+ public void registerImeCallbacks_onBackInvokedCallbackEnabled() throws RemoteException {
+ mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback);
+ assertCallbacksSize(/* default */ 1, /* overlay */ 0);
+ assertSetCallbackInfo();
+ assertTopCallback(mImeBackAnimationController);
+
+ mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback);
+ assertCallbacksSize(/* default */ 2, /* overlay */ 0);
+ assertSetCallbackInfo();
+ assertTopCallback(mImeCallback);
+ }
+
+ @Test
+ public void registerImeCallbacks_legacyBack() throws RemoteException {
+ doReturn(false).when(mApplicationInfo).isOnBackInvokedCallbackEnabled();
+
+ mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback);
+ assertNoSetCallbackInfo();
+
+ mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback);
+ assertNoSetCallbackInfo();
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java b/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
index 6402206..baab3b2 100644
--- a/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
@@ -168,6 +168,20 @@
assertThat(end).isEqualTo("END");
}
+ @Test
+ public void parceling_corruptParcel() {
+ PowerStats stats = new PowerStats(mDescriptor);
+ Parcel parcel = Parcel.obtain();
+ stats.writeToParcel(parcel);
+
+ Parcel newParcel = marshallAndUnmarshall(parcel);
+ newParcel.writeInt(-42); // Negative section length
+ newParcel.setDataPosition(0);
+
+ PowerStats newStats = PowerStats.readFromParcel(newParcel, mRegistry);
+ assertThat(newStats).isNull();
+ }
+
private static Parcel marshallAndUnmarshall(Parcel parcel) {
byte[] bytes = parcel.marshall();
parcel.recycle();
diff --git a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
index 9cb9122..03cb17e 100644
--- a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
+++ b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -95,6 +96,16 @@
}
@Test
+ public void testPackageMonitorNotRegisterWithoutSupportPackageRestartQuery() throws Exception {
+ PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor(false));
+
+ spyPackageMonitor.register(mMockContext, UserHandle.ALL, mMockHandler);
+
+ verify(mMockContext, never()).registerReceiverAsUser(any(), eq(UserHandle.ALL), any(),
+ eq(null), eq(mMockHandler));
+ }
+
+ @Test
public void testPackageMonitorDoHandlePackageEventUidRemoved() throws Exception {
PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor());
@@ -471,5 +482,12 @@
}
public static class TestPackageMonitor extends PackageMonitor {
+ public TestPackageMonitor(boolean b) {
+ super(b);
+ }
+
+ public TestPackageMonitor() {
+ super();
+ }
}
}
diff --git a/data/etc/core.protolog.pb b/data/etc/core.protolog.pb
index 97147a0..000f6ef 100644
--- a/data/etc/core.protolog.pb
+++ b/data/etc/core.protolog.pb
Binary files differ
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 483b693..01deb49 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1117,6 +1117,24 @@
"group": "WM_SHOW_SURFACE_ALLOC",
"at": "com\/android\/server\/wm\/BlackFrame.java"
},
+ "5256889109971284149": {
+ "message": "CameraManager cannot be found.",
+ "level": "ERROR",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/CameraStateMonitor.java"
+ },
+ "8116030277393789125": {
+ "message": "Display id=%d is notified that Camera %s is open for package %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/CameraStateMonitor.java"
+ },
+ "-3774458166471278611": {
+ "message": "Display id=%d is notified that Camera %s is closed.",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/CameraStateMonitor.java"
+ },
"-74949168947384056": {
"message": "Sending to proc %s new compat %s",
"level": "VERBOSE",
@@ -1771,32 +1789,20 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
},
- "-8302211458579221117": {
- "message": "Display id=%d is notified that Camera %s is open for package %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
- },
"-1534784331886673955": {
"message": "DisplayRotationCompatPolicy: Multi-window toast not shown as package '%s' cannot be found.",
"level": "ERROR",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
},
- "1797195804376906831": {
- "message": "Display id=%d is notified that Camera %s is closed, scheduling rotation update.",
+ "-5121743609317543819": {
+ "message": "Display id=%d is notified that camera is closed but activity is still refreshing. Rescheduling an update.",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
},
- "-8746776274432739264": {
- "message": "Display id=%d is notified that Camera %s is closed but activity is still refreshing. Rescheduling an update.",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
- },
- "3622181214422515679": {
- "message": "Display id=%d is notified that Camera %s is closed, updating rotation.",
+ "1769752961776628557": {
+ "message": "Display id=%d is notified that Camera is closed, updating rotation.",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 46a3e7f..e38038e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -67,7 +67,6 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
-import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -113,8 +112,7 @@
public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback,
ActivityEmbeddingComponent, DividerPresenter.DragEventCallback {
static final String TAG = "SplitController";
- static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+ static final boolean ENABLE_SHELL_TRANSITIONS = true;
// TODO(b/243518738): Move to WM Extensions if we have requirement of overlay without
// association. It's not set in WM Extensions nor Wm Jetpack library currently.
@@ -1522,12 +1520,16 @@
@GuardedBy("mLock")
TaskFragmentContainer resolveStartActivityIntent(@NonNull WindowContainerTransaction wct,
int taskId, @NonNull Intent intent, @Nullable Activity launchingActivity) {
- // Skip resolving if started from an isolated navigated TaskFragmentContainer.
if (launchingActivity != null) {
final TaskFragmentContainer taskFragmentContainer = getContainerWithActivity(
launchingActivity);
if (taskFragmentContainer != null
&& taskFragmentContainer.isIsolatedNavigationEnabled()) {
+ // Skip resolving if started from an isolated navigated TaskFragmentContainer.
+ return null;
+ }
+ if (isAssociatedWithOverlay(launchingActivity)) {
+ // Skip resolving if the launching activity associated with an overlay.
return null;
}
}
@@ -1661,9 +1663,8 @@
// is the first embedded TF in the task.
final TaskContainer taskContainer = container.getTaskContainer();
// TODO(b/265271880): remove redundant logic after all TF operations take fragmentToken.
- final Rect taskBounds = taskContainer.getBounds();
final Rect sanitizedBounds = sanitizeBounds(activityStackAttributes.getRelativeBounds(),
- getMinDimensions(intent), taskBounds);
+ getMinDimensions(intent), container);
final int windowingMode = taskContainer
.getWindowingModeForTaskFragment(sanitizedBounds);
mPresenter.createTaskFragment(wct, taskFragmentToken, activityInTask.getActivityToken(),
@@ -1724,17 +1725,14 @@
@GuardedBy("mLock")
@Nullable
TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) {
- // Check pending appeared activity first because there can be a delay for the server
- // update.
- TaskFragmentContainer taskFragmentContainer =
- getContainer(container -> container.hasPendingAppearedActivity(activityToken));
- if (taskFragmentContainer != null) {
- return taskFragmentContainer;
+ for (int i = mTaskContainers.size() - 1; i >= 0; --i) {
+ final TaskFragmentContainer container = mTaskContainers.valueAt(i)
+ .getContainerWithActivity(activityToken);
+ if (container != null) {
+ return container;
+ }
}
-
-
- // Check appeared activity if there is no such pending appeared activity.
- return getContainer(container -> container.hasAppearedActivity(activityToken));
+ return null;
}
@GuardedBy("mLock")
@@ -2098,19 +2096,7 @@
if (container == null) {
return null;
}
- final List<SplitContainer> splitContainers =
- container.getTaskContainer().getSplitContainers();
- if (splitContainers.isEmpty()) {
- return null;
- }
- for (int i = splitContainers.size() - 1; i >= 0; i--) {
- final SplitContainer splitContainer = splitContainers.get(i);
- if (container.equals(splitContainer.getSecondaryContainer())
- || container.equals(splitContainer.getPrimaryContainer())) {
- return splitContainer;
- }
- }
- return null;
+ return container.getTaskContainer().getActiveSplitForContainer(container);
}
/**
@@ -2160,6 +2146,11 @@
return false;
}
+ if (isAssociatedWithOverlay(activity)) {
+ // Can't launch the placeholder if the activity associates an overlay.
+ return false;
+ }
+
final TaskFragmentContainer container = getContainerWithActivity(activity);
if (container != null && !allowLaunchPlaceholder(container)) {
// We don't allow activity in this TaskFragment to launch placeholder.
@@ -2199,6 +2190,11 @@
*/
@GuardedBy("mLock")
private boolean allowLaunchPlaceholder(@NonNull TaskFragmentContainer container) {
+ if (container.isOverlay()) {
+ // Don't launch placeholder if the container is an overlay.
+ return false;
+ }
+
final TaskFragmentContainer topContainer = container.getTaskContainer()
.getTopNonFinishingTaskFragmentContainer();
if (container != topContainer) {
@@ -2472,13 +2468,10 @@
@GuardedBy("mLock")
TaskFragmentContainer getContainer(@NonNull Predicate<TaskFragmentContainer> predicate) {
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
- final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
- .getTaskFragmentContainers();
- for (int j = containers.size() - 1; j >= 0; j--) {
- final TaskFragmentContainer container = containers.get(j);
- if (predicate.test(container)) {
- return container;
- }
+ final TaskFragmentContainer container = mTaskContainers.valueAt(i)
+ .getContainer(predicate);
+ if (container != null) {
+ return container;
}
}
return null;
@@ -2643,6 +2636,16 @@
return overlayContainers;
}
+ @GuardedBy("mLock")
+ private boolean isAssociatedWithOverlay(@NonNull Activity activity) {
+ final TaskContainer taskContainer = getTaskContainer(getTaskId(activity));
+ if (taskContainer == null) {
+ return false;
+ }
+ return taskContainer.getContainer(c -> c.isOverlay() && !c.isFinished()
+ && c.getAssociatedActivityToken() == activity.getActivityToken()) != null;
+ }
+
/**
* Creates an overlay container or updates a visible overlay container if its
* {@link TaskFragmentContainer#getTaskId()}, {@link TaskFragmentContainer#getOverlayTag()}
@@ -2736,7 +2739,7 @@
}
// Requesting an always-on-top overlay.
if (!associateLaunchingActivity) {
- if (overlayContainer.isAssociatedWithActivity()) {
+ if (overlayContainer.isOverlayWithActivityAssociation()) {
// Dismiss the overlay container since it has associated with an activity.
Log.w(TAG, "The overlay container with tag:"
+ overlayContainer.getOverlayTag() + " is dismissed because"
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 6231ea0..0e4fb30 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -591,16 +591,14 @@
@NonNull TaskFragmentContainer container,
@NonNull ActivityStackAttributes attributes,
@Nullable Size minDimensions) {
- final Rect taskBounds = container.getTaskContainer().getBounds();
final Rect relativeBounds = sanitizeBounds(attributes.getRelativeBounds(), minDimensions,
- taskBounds);
+ container);
final boolean isFillParent = relativeBounds.isEmpty();
// Note that we only set isolated navigation for overlay container without activity
// association. Activity will be launched to an expanded container on top of the overlay
// if the overlay is associated with an activity. Thus, an overlay with activity association
// will never be isolated navigated.
- final boolean isIsolatedNavigated = container.isOverlay()
- && !container.isAssociatedWithActivity() && !isFillParent;
+ final boolean isIsolatedNavigated = container.isAlwaysOnTopOverlay() && !isFillParent;
final boolean dimOnTask = !isFillParent
&& attributes.getWindowAttributes().getDimAreaBehavior() == DIM_AREA_ON_TASK
&& Flags.fullscreenDimFlag();
@@ -624,7 +622,7 @@
*/
@NonNull
static Rect sanitizeBounds(@NonNull Rect bounds, @Nullable Size minDimension,
- @NonNull Rect taskBounds) {
+ @NonNull TaskFragmentContainer container) {
if (bounds.isEmpty()) {
// Don't need to check if the bounds follows the task bounds.
return bounds;
@@ -633,10 +631,33 @@
// Expand the bounds if the bounds are smaller than minimum dimensions.
return new Rect();
}
+ final TaskContainer taskContainer = container.getTaskContainer();
+ final Rect taskBounds = taskContainer.getBounds();
if (!taskBounds.contains(bounds)) {
// Expand the bounds if the bounds exceed the task bounds.
return new Rect();
}
+
+ if (!container.isOverlay()) {
+ // Stop here if the container is not an overlay.
+ return bounds;
+ }
+
+ final IBinder associatedActivityToken = container.getAssociatedActivityToken();
+
+ if (associatedActivityToken == null) {
+ // Stop here if the container is an always-on-top overlay.
+ return bounds;
+ }
+
+ // Expand the overlay with activity association if the associated activity is part of a
+ // split, or we may need to handle three change transition together.
+ final TaskFragmentContainer associatedContainer = taskContainer
+ .getContainerWithActivity(associatedActivityToken);
+ if (taskContainer.getActiveSplitForContainer(associatedContainer) != null) {
+ return new Rect();
+ }
+
return bounds;
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index fdf0910..67d34c7 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -43,6 +43,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.window.extensions.core.util.function.Predicate;
import androidx.window.extensions.embedding.SplitAttributes.SplitType;
import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
@@ -318,6 +319,38 @@
return null;
}
+ @Nullable
+ TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) {
+ return getContainer(container -> container.hasAppearedActivity(activityToken)
+ || container.hasPendingAppearedActivity(activityToken));
+ }
+
+ @Nullable
+ TaskFragmentContainer getContainer(@NonNull Predicate<TaskFragmentContainer> predicate) {
+ for (int i = mContainers.size() - 1; i >= 0; i--) {
+ final TaskFragmentContainer container = mContainers.get(i);
+ if (predicate.test(container)) {
+ return container;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ SplitContainer getActiveSplitForContainer(@Nullable TaskFragmentContainer container) {
+ if (container == null) {
+ return null;
+ }
+ for (int i = mSplitContainers.size() - 1; i >= 0; i--) {
+ final SplitContainer splitContainer = mSplitContainers.get(i);
+ if (container.equals(splitContainer.getSecondaryContainer())
+ || container.equals(splitContainer.getPrimaryContainer())) {
+ return splitContainer;
+ }
+ }
+ return null;
+ }
+
/**
* Returns the always-on-top overlay container in the task, or {@code null} if it doesn't exist.
*/
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 094ebcb..c952dfe 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -465,7 +465,7 @@
return;
}
// Early return if this container is not an overlay with activity association.
- if (!isOverlay() || !isAssociatedWithActivity()) {
+ if (!isOverlayWithActivityAssociation()) {
return;
}
if (mAssociatedActivityToken == activityToken) {
@@ -500,7 +500,7 @@
// sure the controller considers this container as the one containing the activity.
// This is needed when the activity is added as pending appeared activity to one
// TaskFragment while it is also an appeared activity in another.
- return mController.getContainerWithActivity(activityToken) == this;
+ return mTaskContainer.getContainerWithActivity(activityToken) == this;
}
/** Whether this activity has appeared in the TaskFragment on the server side. */
@@ -1019,16 +1019,16 @@
return mAssociatedActivityToken;
}
- boolean isAssociatedWithActivity() {
- return mAssociatedActivityToken != null;
- }
-
/**
* Returns {@code true} if the overlay container should be always on top, which should be
* a non-fill-parent overlay without activity association.
*/
boolean isAlwaysOnTopOverlay() {
- return isOverlay() && !isAssociatedWithActivity();
+ return isOverlay() && mAssociatedActivityToken == null;
+ }
+
+ boolean isOverlayWithActivityAssociation() {
+ return isOverlay() && mAssociatedActivityToken != null;
}
@Override
@@ -1050,7 +1050,7 @@
+ " runningActivityCount=" + getRunningActivityCount()
+ " isFinished=" + mIsFinished
+ " overlayTag=" + mOverlayTag
- + " associatedActivity" + mAssociatedActivityToken
+ + " associatedActivityToken=" + mAssociatedActivityToken
+ " lastRequestedBounds=" + mLastRequestedBounds
+ " pendingAppearedActivities=" + mPendingAppearedActivities
+ (includeContainersToFinishOnExit ? " containersToFinishOnExit="
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index 50abdfd..fab298d 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -21,11 +21,15 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.window.extensions.embedding.ActivityEmbeddingOptionsProperties.KEY_OVERLAY_TAG;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.SPLIT_ATTRIBUTES;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TEST_TAG;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPairRuleBuilder;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPlaceholderRuleBuilder;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
+import static androidx.window.extensions.embedding.SplitPresenter.sanitizeBounds;
import static androidx.window.extensions.embedding.WindowAttributes.DIM_AREA_ON_TASK;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -85,6 +89,7 @@
import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -102,6 +107,9 @@
@Rule
public MockitoRule rule = MockitoJUnit.rule();
+ private static final Intent PLACEHOLDER_INTENT = new Intent().setComponent(
+ new ComponentName("test", "placeholder"));
+
@Rule
public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
@@ -259,8 +267,7 @@
mSplitController.setActivityStackAttributesCalculator(params ->
new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
- mOverlayContainer1.getOverlayTag(),
- mOverlayContainer1.getTopNonFinishingActivity());
+ mOverlayContainer1.getOverlayTag());
assertWithMessage("overlayContainer1 must be updated since the new overlay container"
+ " is launched with the same tag and task")
@@ -280,12 +287,13 @@
mSplitController.setActivityStackAttributesCalculator(params ->
new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
- mOverlayContainer1.getOverlayTag(), mActivity);
+ mOverlayContainer1.getOverlayTag(), createMockActivity());
assertWithMessage("overlayContainer1 must be dismissed since the new overlay container"
+ " is associated with different launching activity")
.that(mSplitController.getAllNonFinishingOverlayContainers())
.containsExactly(mOverlayContainer2, overlayContainer);
+ assertThat(overlayContainer).isNotEqualTo(mOverlayContainer1);
}
@Test
@@ -323,7 +331,8 @@
}
private void createExistingOverlayContainers(boolean visible) {
- mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", visible);
+ mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", visible,
+ true /* associatedLaunchingActivity */, mActivity);
mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2", visible);
List<TaskFragmentContainer> overlayContainers = mSplitController
.getAllNonFinishingOverlayContainers();
@@ -335,17 +344,49 @@
mIntent.setComponent(new ComponentName(ApplicationProvider.getApplicationContext(),
MinimumDimensionActivity.class));
final Rect bounds = new Rect(0, 0, 100, 100);
+ final TaskFragmentContainer overlayContainer =
+ createTestOverlayContainer(TASK_ID, "test1");
- SplitPresenter.sanitizeBounds(bounds, SplitPresenter.getMinDimensions(mIntent),
- TASK_BOUNDS);
+ assertThat(sanitizeBounds(bounds, SplitPresenter.getMinDimensions(mIntent),
+ overlayContainer).isEmpty()).isTrue();
}
@Test
public void testSanitizeBounds_notInTaskBounds_expandOverlay() {
final Rect bounds = new Rect(TASK_BOUNDS);
bounds.offset(10, 10);
+ final TaskFragmentContainer overlayContainer =
+ createTestOverlayContainer(TASK_ID, "test1");
- SplitPresenter.sanitizeBounds(bounds, null, TASK_BOUNDS);
+ assertThat(sanitizeBounds(bounds, null, overlayContainer)
+ .isEmpty()).isTrue();
+ }
+
+ @Test
+ public void testSanitizeBounds_visibleSplit_expandOverlay() {
+ // Launch a visible split
+ final Activity primaryActivity = createMockActivity();
+ final Activity secondaryActivity = createMockActivity();
+ final TaskFragmentContainer primaryContainer =
+ createMockTaskFragmentContainer(primaryActivity, true /* isVisible */);
+ final TaskFragmentContainer secondaryContainer =
+ createMockTaskFragmentContainer(secondaryActivity, true /* isVisible */);
+
+ final SplitPairRule splitPairRule = createSplitPairRuleBuilder(
+ activityActivityPair -> true /* activityPairPredicate */,
+ activityIntentPair -> true /* activityIntentPairPredicate */,
+ parentWindowMetrics -> true /* parentWindowMetricsPredicate */)
+ .build();
+ mSplitController.registerSplit(mTransaction, primaryContainer, primaryActivity,
+ secondaryContainer, splitPairRule, splitPairRule.getDefaultSplitAttributes());
+
+ final Rect bounds = new Rect(0, 0, 100, 100);
+ final TaskFragmentContainer overlayContainer =
+ createTestOverlayContainer(TASK_ID, "test1", true /* isVisible */,
+ true /* associatedLaunchingActivity */, secondaryActivity);
+
+ assertThat(sanitizeBounds(bounds, null, overlayContainer)
+ .isEmpty()).isTrue();
}
@Test
@@ -701,6 +742,70 @@
.doesNotContain(overlayWithAssociation);
}
+ @Test
+ public void testLaunchPlaceholderIfNecessary_skipIfActivityAssociateOverlay() {
+ setupPlaceholderRule(mActivity);
+ createTestOverlayContainer(TASK_ID, "test", true /* isVisible */,
+ true /* associateLaunchingActivity */, mActivity);
+
+
+ mSplitController.mTransactionManager.startNewTransaction();
+ assertThat(mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
+ false /* isOnCreated */)).isFalse();
+
+ verify(mTransaction, never()).startActivityInTaskFragment(any(), any(), any(), any());
+ }
+
+ @Test
+ public void testLaunchPlaceholderIfNecessary_skipIfActivityInOverlay() {
+ setupPlaceholderRule(mActivity);
+ createOrUpdateOverlayTaskFragmentIfNeeded("test1", mActivity);
+
+ mSplitController.mTransactionManager.startNewTransaction();
+ assertThat(mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
+ false /* isOnCreated */)).isFalse();
+
+ verify(mTransaction, never()).startActivityInTaskFragment(any(), any(), any(), any());
+ }
+
+ /** Setups a rule to launch placeholder for the given activity. */
+ private void setupPlaceholderRule(@NonNull Activity primaryActivity) {
+ final SplitRule placeholderRule = createSplitPlaceholderRuleBuilder(PLACEHOLDER_INTENT,
+ primaryActivity::equals, i -> false, w -> true)
+ .setDefaultSplitAttributes(SPLIT_ATTRIBUTES)
+ .build();
+ mSplitController.setEmbeddingRules(Collections.singleton(placeholderRule));
+ }
+
+ @Test
+ public void testResolveStartActivityIntent_skipIfAssociateOverlay() {
+ final Intent intent = new Intent();
+ mSplitController.setEmbeddingRules(Collections.singleton(
+ createSplitRule(mActivity, intent)));
+ createTestOverlayContainer(TASK_ID, "test", true /* isVisible */,
+ true /* associateLaunchingActivity */, mActivity);
+ final TaskFragmentContainer container = mSplitController.resolveStartActivityIntent(
+ mTransaction, TASK_ID, intent, mActivity);
+
+ assertThat(container).isNull();
+ verify(mSplitController, never()).resolveStartActivityIntentByRule(any(), anyInt(), any(),
+ any());
+ }
+
+ @Test
+ public void testResolveStartActivityIntent_skipIfLaunchingActivityInOverlay() {
+ final Intent intent = new Intent();
+ mSplitController.setEmbeddingRules(Collections.singleton(
+ createSplitRule(mActivity, intent)));
+ createOrUpdateOverlayTaskFragmentIfNeeded("test1", mActivity);
+ final TaskFragmentContainer container = mSplitController.resolveStartActivityIntent(
+ mTransaction, TASK_ID, intent, mActivity);
+
+ assertThat(container).isNull();
+ verify(mSplitController, never()).resolveStartActivityIntentByRule(any(), anyInt(), any(),
+ any());
+ }
+
/**
* A simplified version of {@link SplitController#createOrUpdateOverlayTaskFragmentIfNeeded}
*/
@@ -726,9 +831,16 @@
/** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
@NonNull
private TaskFragmentContainer createMockTaskFragmentContainer(@NonNull Activity activity) {
+ return createMockTaskFragmentContainer(activity, false /* isVisible */);
+ }
+
+ /** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
+ @NonNull
+ private TaskFragmentContainer createMockTaskFragmentContainer(
+ @NonNull Activity activity, boolean isVisible) {
final TaskFragmentContainer container = mSplitController.newContainer(activity,
activity.getTaskId());
- setupTaskFragmentInfo(container, activity, false /* isVisible */);
+ setupTaskFragmentInfo(container, activity, isVisible);
return container;
}
@@ -745,17 +857,26 @@
true /* associateLaunchingActivity */);
}
+ @NonNull
+ private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
+ boolean isVisible, boolean associateLaunchingActivity) {
+ return createTestOverlayContainer(taskId, tag, isVisible, associateLaunchingActivity,
+ null /* launchingActivity */);
+ }
+
// TODO(b/243518738): add more test coverage on overlay container without activity association
// once we have use cases.
@NonNull
private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
- boolean isVisible, boolean associateLaunchingActivity) {
- Activity activity = createMockActivity();
+ boolean isVisible, boolean associateLaunchingActivity,
+ @Nullable Activity launchingActivity) {
+ final Activity activity = launchingActivity != null
+ ? launchingActivity : createMockActivity();
TaskFragmentContainer overlayContainer = mSplitController.newContainer(
null /* pendingAppearedActivity */, mIntent, activity, taskId,
null /* pairedPrimaryContainer */, tag, Bundle.EMPTY,
associateLaunchingActivity);
- setupTaskFragmentInfo(overlayContainer, activity, isVisible);
+ setupTaskFragmentInfo(overlayContainer, createMockActivity(), isVisible);
return overlayContainer;
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index abfc9c8..44ab2c4 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -538,9 +538,7 @@
// container1.
container2.setInfo(mTransaction, mInfo);
- assertTrue(container1.hasActivity(mActivity.getActivityToken()));
- assertFalse(container2.hasActivity(mActivity.getActivityToken()));
-
+ assertTrue(container2.hasActivity(mActivity.getActivityToken()));
// When the pending appeared record is removed from container1, we respect the appeared
// record in container2.
container1.removePendingAppearedActivity(mActivity.getActivityToken());
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinControllerTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinControllerTest.kt
index e1bf40c..6110133 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinControllerTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinControllerTest.kt
@@ -105,18 +105,21 @@
}
@Test
- fun onDragUpdate_stayOnSameSide() {
+ fun drag_stayOnSameSide() {
runOnMainSync {
controller.onDragStart(initialLocationOnLeft = false)
controller.onDragUpdate(pointOnRight.x, pointOnRight.y)
+ controller.onDragEnd()
}
waitForAnimateIn()
assertThat(dropTargetView).isNull()
assertThat(testListener.locationChanges).isEmpty()
+ assertThat(testListener.locationReleases).containsExactly(BubbleBarLocation.RIGHT)
}
@Test
- fun onDragUpdate_toLeft() {
+ fun drag_toLeft() {
+ // Drag to left, but don't finish
runOnMainSync {
controller.onDragStart(initialLocationOnLeft = false)
controller.onDragUpdate(pointOnLeft.x, pointOnLeft.y)
@@ -132,10 +135,16 @@
.isEqualTo(expectedDropTargetBounds.height())
assertThat(testListener.locationChanges).containsExactly(BubbleBarLocation.LEFT)
+ assertThat(testListener.locationReleases).isEmpty()
+
+ // Finish the drag
+ runOnMainSync { controller.onDragEnd() }
+ assertThat(testListener.locationReleases).containsExactly(BubbleBarLocation.LEFT)
}
@Test
- fun onDragUpdate_toLeftAndBackToRight() {
+ fun drag_toLeftAndBackToRight() {
+ // Drag to left
runOnMainSync {
controller.onDragStart(initialLocationOnLeft = false)
controller.onDragUpdate(pointOnLeft.x, pointOnLeft.y)
@@ -143,6 +152,7 @@
waitForAnimateIn()
assertThat(dropTargetView).isNotNull()
+ // Drag to right
runOnMainSync { controller.onDragUpdate(pointOnRight.x, pointOnRight.y) }
// We have to wait for existing drop target to animate out and new to animate in
waitForAnimateOut()
@@ -158,10 +168,15 @@
assertThat(testListener.locationChanges)
.containsExactly(BubbleBarLocation.LEFT, BubbleBarLocation.RIGHT)
+ assertThat(testListener.locationReleases).isEmpty()
+
+ // Release the view
+ runOnMainSync { controller.onDragEnd() }
+ assertThat(testListener.locationReleases).containsExactly(BubbleBarLocation.RIGHT)
}
@Test
- fun onDragUpdate_toLeftInExclusionRect() {
+ fun drag_toLeftInExclusionRect() {
runOnMainSync {
controller.onDragStart(initialLocationOnLeft = false)
// Exclusion rect is around the bottom center area of the screen
@@ -170,6 +185,10 @@
waitForAnimateIn()
assertThat(dropTargetView).isNull()
assertThat(testListener.locationChanges).isEmpty()
+ assertThat(testListener.locationReleases).isEmpty()
+
+ runOnMainSync { controller.onDragEnd() }
+ assertThat(testListener.locationReleases).containsExactly(BubbleBarLocation.RIGHT)
}
@Test
@@ -256,8 +275,13 @@
internal class TestLocationChangeListener : BaseBubblePinController.LocationChangeListener {
val locationChanges = mutableListOf<BubbleBarLocation>()
+ val locationReleases = mutableListOf<BubbleBarLocation>()
override fun onChange(location: BubbleBarLocation) {
locationChanges.add(location)
}
+
+ override fun onRelease(location: BubbleBarLocation) {
+ locationReleases.add(location)
+ }
}
}
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 0297901..f9a1d94 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
@@ -82,8 +82,8 @@
private BubbleViewProvider mBubble;
private BubblePositioner mPositioner;
- private boolean mOnLeft;
-
+ private boolean mBadgeOnLeft;
+ private boolean mDotOnLeft;
private DotRenderer mDotRenderer;
private DotRenderer.DrawParams mDrawParams;
private int mDotColor;
@@ -153,7 +153,8 @@
public void hideDotAndBadge(boolean onLeft) {
addDotSuppressionFlag(BadgedImageView.SuppressionFlag.BEHIND_STACK);
- mOnLeft = onLeft;
+ mBadgeOnLeft = onLeft;
+ mDotOnLeft = onLeft;
hideBadge();
}
@@ -185,7 +186,7 @@
mDrawParams.dotColor = mDotColor;
mDrawParams.iconBounds = mTempBounds;
- mDrawParams.leftAlign = mOnLeft;
+ mDrawParams.leftAlign = mDotOnLeft;
mDrawParams.scale = mDotScale;
mDotRenderer.draw(canvas, mDrawParams);
@@ -255,7 +256,7 @@
* Whether decorations (badges or dots) are on the left.
*/
boolean getDotOnLeft() {
- return mOnLeft;
+ return mDotOnLeft;
}
/**
@@ -263,7 +264,7 @@
*/
float[] getDotCenter() {
float[] dotPosition;
- if (mOnLeft) {
+ if (mDotOnLeft) {
dotPosition = mDotRenderer.getLeftDotPosition();
} else {
dotPosition = mDotRenderer.getRightDotPosition();
@@ -291,22 +292,23 @@
if (onLeft != getDotOnLeft()) {
if (shouldDrawDot()) {
animateDotScale(0f /* showDot */, () -> {
- mOnLeft = onLeft;
+ mDotOnLeft = onLeft;
invalidate();
animateDotScale(1.0f, null /* after */);
});
} else {
- mOnLeft = onLeft;
+ mDotOnLeft = onLeft;
}
}
+ mBadgeOnLeft = onLeft;
// TODO animate badge
showBadge();
-
}
/** Sets the position of the dot and badge. */
void setDotBadgeOnLeft(boolean onLeft) {
- mOnLeft = onLeft;
+ mBadgeOnLeft = onLeft;
+ mDotOnLeft = onLeft;
invalidate();
showBadge();
}
@@ -361,7 +363,7 @@
}
int translationX;
- if (mOnLeft) {
+ if (mBadgeOnLeft) {
translationX = -(mBubble.getBubbleIcon().getWidth() - appBadgeBitmap.getWidth());
} else {
translationX = 0;
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 d295877..edd5935 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
@@ -474,11 +474,16 @@
mDisplayController.addDisplayChangingController(
(displayId, fromRotation, toRotation, newDisplayAreaInfo, t) -> {
- // This is triggered right before the rotation is applied
- if (fromRotation != toRotation) {
+ Rect newScreenBounds = new Rect();
+ if (newDisplayAreaInfo != null) {
+ newScreenBounds =
+ newDisplayAreaInfo.configuration.windowConfiguration.getBounds();
+ }
+ // This is triggered right before the rotation or new screen size is applied
+ if (fromRotation != toRotation || !newScreenBounds.equals(mScreenBounds)) {
if (mStackView != null) {
// Layout listener set on stackView will update the positioner
- // once the rotation is applied
+ // once the rotation or screen change is applied
mStackView.onOrientationChanged();
}
}
@@ -725,6 +730,17 @@
}
}
+ /**
+ * Animate bubble bar to the given location. The location change is transient. It does not
+ * update the state of the bubble bar.
+ * To update bubble bar pinned location, use {@link #setBubbleBarLocation(BubbleBarLocation)}.
+ */
+ public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+ if (canShowAsBubbleBar()) {
+ mBubbleStateListener.animateBubbleBarLocation(bubbleBarLocation);
+ }
+ }
+
/** Whether this userId belongs to the current user. */
private boolean isCurrentProfile(int userId) {
return userId == UserHandle.USER_ALL
@@ -2250,15 +2266,19 @@
private final SingleInstanceRemoteListener<BubbleController, IBubblesListener> mListener;
private final Bubbles.BubbleStateListener mBubbleListener =
new Bubbles.BubbleStateListener() {
+ @Override
+ public void onBubbleStateChange(BubbleBarUpdate update) {
+ Bundle b = new Bundle();
+ b.setClassLoader(BubbleBarUpdate.class.getClassLoader());
+ b.putParcelable(BubbleBarUpdate.BUNDLE_KEY, update);
+ mListener.call(l -> l.onBubbleStateChange(b));
+ }
- @Override
- public void onBubbleStateChange(BubbleBarUpdate update) {
- Bundle b = new Bundle();
- b.setClassLoader(BubbleBarUpdate.class.getClassLoader());
- b.putParcelable(BubbleBarUpdate.BUNDLE_KEY, update);
- mListener.call(l -> l.onBubbleStateChange(b));
- }
- };
+ @Override
+ public void animateBubbleBarLocation(BubbleBarLocation location) {
+ mListener.call(l -> l.animateBubbleBarLocation(location));
+ }
+ };
IBubblesImpl(BubbleController controller) {
mController = controller;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index 127a49f..322088b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -37,6 +37,7 @@
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.android.wm.shell.shared.annotations.ExternalThread;
@@ -304,6 +305,12 @@
* Called when the bubbles state changes.
*/
void onBubbleStateChange(BubbleBarUpdate update);
+
+ /**
+ * Called when bubble bar should temporarily be animated to a new location.
+ * Does not result in a state change.
+ */
+ void animateBubbleBarLocation(BubbleBarLocation location);
}
/** Listener to find out about stack expansion / collapse events. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl
index e48f8d5..14d29cd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl
@@ -15,8 +15,9 @@
*/
package com.android.wm.shell.bubbles;
-import android.os.Bundle;
+import android.os.Bundle;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
/**
* Listener interface that Launcher attaches to SystemUI to get bubbles callbacks.
*/
@@ -26,4 +27,10 @@
* Called when the bubbles state changes.
*/
void onBubbleStateChange(in Bundle update);
+
+ /**
+ * Called when bubble bar should temporarily be animated to a new location.
+ * Does not result in a state change.
+ */
+ void animateBubbleBarLocation(in BubbleBarLocation location);
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index 1fb966f..9440e98 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -468,9 +468,9 @@
final int index = mLayout.indexOfChild(bubbleView);
final PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleStackView.getState());
animationForChildAtIndex(index)
- .position(p.x, p.y)
+ .position(p.x, p.y, /* translationZ= */ 0f)
.withPositionStartVelocities(velX, velY)
- .start(() -> bubbleView.setTranslationZ(0f) /* after */);
+ .start();
mMagnetizedBubbleDraggingOut = null;
@@ -509,6 +509,7 @@
return Sets.newHashSet(
DynamicAnimation.TRANSLATION_X,
DynamicAnimation.TRANSLATION_Y,
+ DynamicAnimation.TRANSLATION_Z,
DynamicAnimation.SCALE_X,
DynamicAnimation.SCALE_Y,
DynamicAnimation.ALPHA);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
index bfddff0..06305f0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
@@ -419,7 +419,8 @@
// be animating in this case, even if the physics animations haven't been started yet.
final boolean isTranslation =
property.equals(DynamicAnimation.TRANSLATION_X)
- || property.equals(DynamicAnimation.TRANSLATION_Y);
+ || property.equals(DynamicAnimation.TRANSLATION_Y)
+ || property.equals(DynamicAnimation.TRANSLATION_Z);
if (isTranslation && targetAnimator != null && targetAnimator.isRunning()) {
return true;
}
@@ -495,6 +496,8 @@
return "TRANSLATION_X";
} else if (property.equals(DynamicAnimation.TRANSLATION_Y)) {
return "TRANSLATION_Y";
+ } else if (property.equals(DynamicAnimation.TRANSLATION_Z)) {
+ return "TRANSLATION_Z";
} else if (property.equals(DynamicAnimation.SCALE_X)) {
return "SCALE_X";
} else if (property.equals(DynamicAnimation.SCALE_Y)) {
@@ -598,6 +601,8 @@
return R.id.translation_x_dynamicanimation_tag;
} else if (property.equals(DynamicAnimation.TRANSLATION_Y)) {
return R.id.translation_y_dynamicanimation_tag;
+ } else if (property.equals(DynamicAnimation.TRANSLATION_Z)) {
+ return R.id.translation_z_dynamicanimation_tag;
} else if (property.equals(DynamicAnimation.SCALE_X)) {
return R.id.scale_x_dynamicanimation_tag;
} else if (property.equals(DynamicAnimation.SCALE_Y)) {
@@ -763,6 +768,12 @@
return property(DynamicAnimation.TRANSLATION_X, translationX, endActions);
}
+ /** Animate the view's translationZ value to the provided value. */
+ public PhysicsPropertyAnimator translationZ(float translationZ, Runnable... endActions) {
+ mPathAnimator = null; // We aren't using the path anymore if we're translating.
+ return property(DynamicAnimation.TRANSLATION_Z, translationZ, endActions);
+ }
+
/** Set the view's translationX value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator translationX(
float from, float to, Runnable... endActions) {
@@ -785,13 +796,14 @@
/**
* Animate the view's translationX and translationY values, and call the end actions only
- * once both TRANSLATION_X and TRANSLATION_Y animations have completed.
+ * once both TRANSLATION_X, TRANSLATION_Y and TRANSLATION_Z animations have completed.
*/
- public PhysicsPropertyAnimator position(
- float translationX, float translationY, Runnable... endActions) {
+ public PhysicsPropertyAnimator position(float translationX, float translationY,
+ float translationZ, Runnable... endActions) {
mPositionEndActions = endActions;
translationX(translationX);
- return translationY(translationY);
+ translationY(translationY);
+ return translationZ(translationZ);
}
/**
@@ -845,10 +857,13 @@
private void clearTranslationValues() {
mAnimatedProperties.remove(DynamicAnimation.TRANSLATION_X);
mAnimatedProperties.remove(DynamicAnimation.TRANSLATION_Y);
+ mAnimatedProperties.remove(DynamicAnimation.TRANSLATION_Z);
mInitialPropertyValues.remove(DynamicAnimation.TRANSLATION_X);
mInitialPropertyValues.remove(DynamicAnimation.TRANSLATION_Y);
+ mInitialPropertyValues.remove(DynamicAnimation.TRANSLATION_Z);
mEndActionForProperty.remove(DynamicAnimation.TRANSLATION_X);
mEndActionForProperty.remove(DynamicAnimation.TRANSLATION_Y);
+ mEndActionForProperty.remove(DynamicAnimation.TRANSLATION_Z);
}
/** Animate the view's scaleX value to the provided value. */
@@ -939,15 +954,19 @@
}, propertiesArray);
}
- // If we used position-specific end actions, we'll need to listen for both TRANSLATION_X
- // and TRANSLATION_Y animations ending, and call them once both have finished.
+ // If we used position-specific end actions, we'll need to listen for TRANSLATION_X
+ // TRANSLATION_Y and TRANSLATION_Z animations ending, and call them once both have
+ // finished.
if (mPositionEndActions != null) {
final SpringAnimation translationXAnim =
getSpringAnimationFromView(DynamicAnimation.TRANSLATION_X, mView);
final SpringAnimation translationYAnim =
getSpringAnimationFromView(DynamicAnimation.TRANSLATION_Y, mView);
- final Runnable waitForBothXAndY = () -> {
- if (!translationXAnim.isRunning() && !translationYAnim.isRunning()) {
+ final SpringAnimation translationZAnim =
+ getSpringAnimationFromView(DynamicAnimation.TRANSLATION_Z, mView);
+ final Runnable waitForXYZ = () -> {
+ if (!translationXAnim.isRunning() && !translationYAnim.isRunning()
+ && !translationZAnim.isRunning()) {
if (mPositionEndActions != null) {
for (Runnable callback : mPositionEndActions) {
callback.run();
@@ -959,9 +978,11 @@
};
mEndActionsForProperty.put(DynamicAnimation.TRANSLATION_X,
- new Runnable[]{waitForBothXAndY});
+ new Runnable[]{waitForXYZ});
mEndActionsForProperty.put(DynamicAnimation.TRANSLATION_Y,
- new Runnable[]{waitForBothXAndY});
+ new Runnable[]{waitForXYZ});
+ mEndActionsForProperty.put(DynamicAnimation.TRANSLATION_Z,
+ new Runnable[]{waitForXYZ});
}
if (mPathAnimator != null) {
@@ -972,9 +993,10 @@
for (DynamicAnimation.ViewProperty property : properties) {
// Don't start translation animations if we're using a path animator, the update
// listeners added to that animator will take care of that.
- if (mPathAnimator != null
- && (property.equals(DynamicAnimation.TRANSLATION_X)
- || property.equals(DynamicAnimation.TRANSLATION_Y))) {
+ boolean isTranslationProperty = property.equals(DynamicAnimation.TRANSLATION_X)
+ || property.equals(DynamicAnimation.TRANSLATION_Y)
+ || property.equals(DynamicAnimation.TRANSLATION_Z);
+ if (mPathAnimator != null && isTranslationProperty) {
return;
}
@@ -1006,6 +1028,7 @@
if (mPathAnimator != null) {
animatedProperties.add(DynamicAnimation.TRANSLATION_X);
animatedProperties.add(DynamicAnimation.TRANSLATION_Y);
+ animatedProperties.add(DynamicAnimation.TRANSLATION_Z);
}
return animatedProperties;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
index fe9c4d4..a51ac63 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
@@ -135,9 +135,9 @@
private fun finishDrag() {
if (!isStuckToDismiss) {
- animationHelper.animateToRestPosition()
pinController.onDragEnd()
dragListener.onReleased(inDismiss = false)
+ animationHelper.animateToRestPosition()
dismissView.hide()
}
isMoving = false
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 62cc4da..a351cef 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
@@ -33,6 +33,8 @@
import android.view.WindowManager;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+
import com.android.wm.shell.bubbles.Bubble;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.bubbles.BubbleData;
@@ -42,6 +44,8 @@
import com.android.wm.shell.bubbles.DeviceConfig;
import com.android.wm.shell.bubbles.DismissViewUtils;
import com.android.wm.shell.bubbles.bar.BubbleBarExpandedViewDragController.DragListener;
+import com.android.wm.shell.common.bubbles.BaseBubblePinController;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import com.android.wm.shell.common.bubbles.DismissView;
import kotlin.Unit;
@@ -115,7 +119,18 @@
mBubbleExpandedViewPinController = new BubbleExpandedViewPinController(
context, this, mPositioner);
- mBubbleExpandedViewPinController.setListener(mBubbleController::setBubbleBarLocation);
+ mBubbleExpandedViewPinController.setListener(
+ new BaseBubblePinController.LocationChangeListener() {
+ @Override
+ public void onChange(@NonNull BubbleBarLocation bubbleBarLocation) {
+ mBubbleController.animateBubbleBarLocation(bubbleBarLocation);
+ }
+
+ @Override
+ public void onRelease(@NonNull BubbleBarLocation location) {
+ mBubbleController.setBubbleBarLocation(location);
+ }
+ });
setOnClickListener(view -> hideMenuOrCollapse());
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinController.kt
index 5d391ec..3b3974d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleExpandedViewPinController.kt
@@ -17,8 +17,8 @@
package com.android.wm.shell.bubbles.bar
import android.content.Context
+import android.graphics.Point
import android.graphics.Rect
-import android.graphics.RectF
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
@@ -37,31 +37,25 @@
private val context: Context,
private val container: FrameLayout,
private val positioner: BubblePositioner
-) : BaseBubblePinController() {
+) : BaseBubblePinController({ positioner.availableRect.let { Point(it.width(), it.height()) } }) {
private var dropTargetView: View? = null
private val tempRect: Rect by lazy(LazyThreadSafetyMode.NONE) { Rect() }
- override fun getScreenCenterX(): Int {
- return positioner.screenRect.centerX()
+ private val exclRectWidth: Float by lazy {
+ context.resources.getDimension(R.dimen.bubble_bar_dismiss_zone_width)
}
- override fun getExclusionRect(): RectF {
- val rect =
- RectF(
- 0f,
- 0f,
- context.resources.getDimension(R.dimen.bubble_bar_dismiss_zone_width),
- context.resources.getDimension(R.dimen.bubble_bar_dismiss_zone_height)
- )
+ private val exclRectHeight: Float by lazy {
+ context.resources.getDimension(R.dimen.bubble_bar_dismiss_zone_height)
+ }
- val screenRect = positioner.screenRect
- // Center it around the bottom center of the screen
- rect.offsetTo(
- screenRect.exactCenterX() - rect.width() / 2f,
- screenRect.bottom - rect.height()
- )
- return rect
+ override fun getExclusionRectWidth(): Float {
+ return exclRectWidth
+ }
+
+ override fun getExclusionRectHeight(): Float {
+ return exclRectHeight
}
override fun createDropTargetView(): View {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BaseBubblePinController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BaseBubblePinController.kt
index 630ad6e..e514f9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BaseBubblePinController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BaseBubblePinController.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.common.bubbles
+import android.graphics.Point
import android.graphics.RectF
import android.view.View
import androidx.annotation.VisibleForTesting
@@ -35,7 +36,7 @@
*
* Shows a drop target when releasing a view would update the [BubbleBarLocation].
*/
-abstract class BaseBubblePinController {
+abstract class BaseBubblePinController(private val screenSizeProvider: () -> Point) {
private var onLeft = false
private var dismissZone: RectF? = null
@@ -50,8 +51,8 @@
*/
fun onDragStart(initialLocationOnLeft: Boolean) {
onLeft = initialLocationOnLeft
+ screenCenterX = screenSizeProvider.invoke().x / 2
dismissZone = getExclusionRect()
- screenCenterX = getScreenCenterX()
}
/** View has moved to [x] and [y] screen coordinates */
@@ -81,6 +82,7 @@
fun onDragEnd() {
getDropTargetView()?.let { view -> view.animateOut { removeDropTargetView(view) } }
dismissZone = null
+ listener?.onRelease(if (onLeft) LEFT else RIGHT)
}
/**
@@ -91,11 +93,10 @@
this.listener = listener
}
- /** Get screen center coordinate on the x axis. */
- protected abstract fun getScreenCenterX(): Int
-
- /** Optional exclusion rect where drag interactions are not processed */
- protected abstract fun getExclusionRect(): RectF?
+ /** Get width for exclusion rect where dismiss takes over drag */
+ protected abstract fun getExclusionRectWidth(): Float
+ /** Get height for exclusion rect where dismiss takes over drag */
+ protected abstract fun getExclusionRectHeight(): Float
/** Create the drop target view and attach it to the parent */
protected abstract fun createDropTargetView(): View
@@ -114,6 +115,14 @@
listener?.onChange(location)
}
+ private fun getExclusionRect(): RectF {
+ val rect = RectF(0f, 0f, getExclusionRectWidth(), getExclusionRectHeight())
+ // Center it around the bottom center of the screen
+ val screenBottom = screenSizeProvider.invoke().y
+ rect.offsetTo(screenCenterX - rect.width() / 2, screenBottom - rect.height())
+ return rect
+ }
+
private fun showDropTarget(location: BubbleBarLocation) {
val targetView = getDropTargetView() ?: createDropTargetView().apply { alpha = 0f }
if (targetView.alpha > 0) {
@@ -162,14 +171,22 @@
/** Receive updates on location changes */
interface LocationChangeListener {
/**
- * Bubble bar [BubbleBarLocation] has changed as a result of dragging
+ * Bubble bar has been dragged to a new [BubbleBarLocation]. And the drag is still in
+ * progress.
*
* Triggered when drag gesture passes the middle of the screen and before touch up. Can be
* triggered multiple times per gesture.
*
* @param location new location as a result of the ongoing drag operation
*/
- fun onChange(location: BubbleBarLocation)
+ fun onChange(location: BubbleBarLocation) {}
+
+ /**
+ * Bubble bar has been released in the [BubbleBarLocation].
+ *
+ * @param location final location of the bubble bar once drag is released
+ */
+ fun onRelease(location: BubbleBarLocation)
}
companion object {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java
index f9a286e..bc6ed1f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java
@@ -84,6 +84,8 @@
private final int mMinimalSizeResizableTask;
private final int mTaskHeightInMinimizedMode;
private final float mFixedRatio;
+ /** Allows split ratios to calculated dynamically instead of using {@link #mFixedRatio}. */
+ private final boolean mAllowFlexibleSplitRatios;
private boolean mIsHorizontalDivision;
/** The first target which is still splitting the screen */
@@ -144,6 +146,8 @@
com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1);
mMinimalSizeResizableTask = res.getDimensionPixelSize(
com.android.internal.R.dimen.default_minimal_size_resizable_task);
+ mAllowFlexibleSplitRatios = res.getBoolean(
+ com.android.internal.R.bool.config_flexibleSplitRatios);
mTaskHeightInMinimizedMode = isHomeResizable ? res.getDimensionPixelSize(
com.android.internal.R.dimen.task_height_of_minimized_mode) : 0;
calculateTargets(isHorizontalDivision, dockSide);
@@ -349,6 +353,9 @@
? mDisplayHeight - mInsets.bottom
: mDisplayWidth - mInsets.right;
int size = (int) (mFixedRatio * (end - start)) - mDividerSize / 2;
+ if (mAllowFlexibleSplitRatios) {
+ size = Math.max(size, mMinimalSizeResizableTask);
+ }
int topPosition = start + size;
int bottomPosition = end - size - mDividerSize;
addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 6834e6d..17121c8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -702,10 +702,12 @@
ShellInit shellInit,
ShellController shellController,
Transitions transitions,
+ TaskStackListenerImpl taskStackListener,
@ShellMainThread Handler mainHandler,
@ShellMainThread ShellExecutor mainExecutor) {
return new KeyguardTransitionHandler(
- shellInit, shellController, transitions, mainHandler, mainExecutor);
+ shellInit, shellController, transitions, taskStackListener, mainHandler,
+ mainExecutor);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
index 4eff3f0..6e61f22 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
@@ -26,6 +26,7 @@
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SystemWindows;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipDisplayLayoutState;
@@ -43,6 +44,7 @@
import com.android.wm.shell.pip2.phone.PipScheduler;
import com.android.wm.shell.pip2.phone.PipTouchHandler;
import com.android.wm.shell.pip2.phone.PipTransition;
+import com.android.wm.shell.pip2.phone.PipTransitionState;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -69,9 +71,11 @@
PipBoundsAlgorithm pipBoundsAlgorithm,
Optional<PipController> pipController,
PipTouchHandler pipTouchHandler,
- @NonNull PipScheduler pipScheduler) {
+ @NonNull PipScheduler pipScheduler,
+ @NonNull PipTransitionState pipStackListenerController) {
return new PipTransition(context, shellInit, shellTaskOrganizer, transitions,
- pipBoundsState, null, pipBoundsAlgorithm, pipScheduler);
+ pipBoundsState, null, pipBoundsAlgorithm, pipScheduler,
+ pipStackListenerController);
}
@WMSingleton
@@ -85,6 +89,9 @@
PipBoundsAlgorithm pipBoundsAlgorithm,
PipDisplayLayoutState pipDisplayLayoutState,
PipScheduler pipScheduler,
+ TaskStackListenerImpl taskStackListener,
+ ShellTaskOrganizer shellTaskOrganizer,
+ PipTransitionState pipTransitionState,
@ShellMainThread ShellExecutor mainExecutor) {
if (!PipUtils.isPip2ExperimentEnabled()) {
return Optional.empty();
@@ -92,7 +99,7 @@
return Optional.ofNullable(PipController.create(
context, shellInit, shellController, displayController, displayInsetsController,
pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler,
- mainExecutor));
+ taskStackListener, shellTaskOrganizer, pipTransitionState, mainExecutor));
}
}
@@ -101,8 +108,8 @@
static PipScheduler providePipScheduler(Context context,
PipBoundsState pipBoundsState,
@ShellMainThread ShellExecutor mainExecutor,
- ShellTaskOrganizer shellTaskOrganizer) {
- return new PipScheduler(context, pipBoundsState, mainExecutor, shellTaskOrganizer);
+ PipTransitionState pipTransitionState) {
+ return new PipScheduler(context, pipBoundsState, mainExecutor, pipTransitionState);
}
@WMSingleton
@@ -146,4 +153,10 @@
return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm,
floatingContentCoordinator, pipPerfHintControllerOptional);
}
+
+ @WMSingleton
+ @Provides
+ static PipTransitionState providePipStackListenerController() {
+ return new PipTransitionState();
+ }
}
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 63a8158..ecfb134 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
@@ -158,6 +158,10 @@
com.android.wm.shell.R.dimen.desktop_mode_transition_area_width
)
+ /** Task id of the task currently being dragged from fullscreen/split. */
+ val draggingTaskId
+ get() = dragToDesktopTransitionHandler.draggingTaskId
+
private var recentsAnimationRunning = false
private lateinit var splitScreenController: SplitScreenController
@@ -406,6 +410,7 @@
fun onDesktopSplitSelectAnimComplete(taskInfo: RunningTaskInfo) {
val wct = WindowContainerTransaction()
wct.setBounds(taskInfo.token, Rect())
+ wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED)
shellTaskOrganizer.applyTransaction(wct)
}
@@ -447,7 +452,9 @@
)
val wct = WindowContainerTransaction()
wct.setBounds(task.token, Rect())
- addMoveToSplitChanges(wct, task)
+ // Rather than set windowing mode to multi-window at task level, set it to
+ // undefined and inherit from split stage.
+ wct.setWindowingMode(task.token, WINDOWING_MODE_UNDEFINED)
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */)
} else {
@@ -458,10 +465,12 @@
private fun exitSplitIfApplicable(wct: WindowContainerTransaction, taskInfo: RunningTaskInfo) {
if (splitScreenController.isTaskInSplitScreen(taskInfo.taskId)) {
splitScreenController.prepareExitSplitScreen(
- wct,
- splitScreenController.getStageOfTask(taskInfo.taskId),
- EXIT_REASON_DESKTOP_MODE
+ wct,
+ splitScreenController.getStageOfTask(taskInfo.taskId),
+ EXIT_REASON_DESKTOP_MODE
)
+ splitScreenController.transitionHandler
+ ?.onSplitToDesktop()
}
}
@@ -1044,9 +1053,11 @@
wct: WindowContainerTransaction,
taskInfo: RunningTaskInfo
) {
- // Explicitly setting multi-window at task level interferes with animations.
- // Let task inherit windowing mode once transition is complete instead.
- wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED)
+ // This windowing mode is to get the transition animation started; once we complete
+ // split select, we will change windowing mode to undefined and inherit from split stage.
+ // Going to undefined here causes task to flicker to the top left.
+ // Cancelling the split select flow will revert it to fullscreen.
+ wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_MULTI_WINDOW)
// The task's density may have been overridden in freeform; revert it here as we don't
// want it overridden in multi-window.
wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi())
@@ -1237,7 +1248,7 @@
finalizeDragToDesktop(taskInfo, getDefaultDesktopTaskBounds(displayLayout))
}
DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR,
- DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR -> {
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR -> {
cancelDragToDesktop(taskInfo)
}
DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR -> {
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 e341f2d..e5e435d 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
@@ -6,6 +6,7 @@
import android.animation.ValueAnimator
import android.app.ActivityOptions
import android.app.ActivityOptions.SourceInfo
+import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
import android.app.PendingIntent.FLAG_MUTABLE
@@ -26,6 +27,9 @@
import android.window.WindowContainerToken
import android.window.WindowContainerTransaction
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
+import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
+import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
+import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED
import com.android.wm.shell.protolog.ShellProtoLogGroup
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.splitscreen.SplitScreenController
@@ -68,7 +72,7 @@
.addCategory(Intent.CATEGORY_HOME)
private var dragToDesktopStateListener: DragToDesktopStateListener? = null
- private var splitScreenController: SplitScreenController? = null
+ private lateinit var splitScreenController: SplitScreenController
private var transitionState: TransitionState? = null
private lateinit var onTaskResizeAnimationListener: OnTaskResizeAnimationListener
@@ -76,6 +80,9 @@
val inProgress: Boolean
get() = transitionState != null
+ /** The task id of the task currently being dragged from fullscreen/split. */
+ val draggingTaskId: Int
+ get() = transitionState?.draggedTaskId ?: INVALID_TASK_ID
/** Sets a listener to receive callback about events during the transition animation. */
fun setDragToDesktopStateListener(listener: DragToDesktopStateListener) {
dragToDesktopStateListener = listener
@@ -130,10 +137,14 @@
.startTransition(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP, wct, this)
transitionState = if (isSplitTask(taskId)) {
+ val otherTask = getOtherSplitTask(taskId) ?: throw IllegalStateException(
+ "Expected split task to have a counterpart."
+ )
TransitionState.FromSplit(
draggedTaskId = taskId,
dragAnimator = dragToDesktopAnimator,
- startTransitionToken = startTransitionToken
+ startTransitionToken = startTransitionToken,
+ otherSplitTask = otherTask
)
} else {
TransitionState.FromFullscreen(
@@ -347,6 +358,12 @@
?: error("Start transition expected to be waiting for merge but wasn't")
if (isEndTransition) {
info.changes.withIndex().forEach { (i, change) ->
+ // If we're exiting split, hide the remaining split task.
+ if (state is TransitionState.FromSplit &&
+ change.taskInfo?.taskId == state.otherSplitTask) {
+ t.hide(change.leash)
+ startTransactionFinishT.hide(change.leash)
+ }
if (change.mode == TRANSIT_CLOSE) {
t.hide(change.leash)
startTransactionFinishT.hide(change.leash)
@@ -392,7 +409,6 @@
onTaskResizeAnimationListener.onAnimationStart(state.draggedTaskId, t,
unscaledStartBounds)
finishCallback.onTransitionFinished(null /* wct */)
-
val tx: SurfaceControl.Transaction = transactionSupplier.get()
ValueAnimator.ofObject(rectEvaluator, unscaledStartBounds, endBounds)
.setDuration(DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS)
@@ -549,7 +565,18 @@
}
private fun isSplitTask(taskId: Int): Boolean {
- return splitScreenController?.isTaskInSplitScreen(taskId) ?: false
+ return splitScreenController.isTaskInSplitScreen(taskId)
+ }
+
+ private fun getOtherSplitTask(taskId: Int): Int? {
+ val splitPos = splitScreenController.getSplitPosition(taskId)
+ if (splitPos == SPLIT_POSITION_UNDEFINED) return null
+ val otherTaskPos = if (splitPos == SPLIT_POSITION_BOTTOM_OR_RIGHT) {
+ SPLIT_POSITION_TOP_OR_LEFT
+ } else {
+ SPLIT_POSITION_BOTTOM_OR_RIGHT
+ }
+ return splitScreenController.getTaskInfo(otherTaskPos)?.taskId
}
private fun requireTransitionState(): TransitionState {
@@ -598,6 +625,7 @@
override var cancelled: Boolean = false,
override var startAborted: Boolean = false,
var splitRootChange: Change? = null,
+ var otherSplitTask: Int
) : TransitionState()
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index 863a51a..9eaf7e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -44,10 +45,13 @@
import android.window.IRemoteTransitionFinishedCallback;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TaskStackListenerCallback;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.annotations.ExternalThread;
import com.android.wm.shell.sysui.KeyguardChangeListener;
@@ -62,7 +66,8 @@
* <p>This takes the highest priority.
*/
public class KeyguardTransitionHandler
- implements Transitions.TransitionHandler, KeyguardChangeListener {
+ implements Transitions.TransitionHandler, KeyguardChangeListener,
+ TaskStackListenerCallback {
private static final String TAG = "KeyguardTransition";
private final Transitions mTransitions;
@@ -71,6 +76,7 @@
private final ShellExecutor mMainExecutor;
private final ArrayMap<IBinder, StartedTransition> mStartedTransitions = new ArrayMap<>();
+ private final TaskStackListenerImpl mTaskStackListener;
/**
* Local IRemoteTransition implementations registered by the keyguard service.
@@ -87,6 +93,8 @@
// Last value reported by {@link KeyguardChangeListener}.
private boolean mKeyguardShowing = true;
+ @Nullable
+ private WindowContainerToken mDreamToken;
private final class StartedTransition {
final TransitionInfo mInfo;
@@ -105,18 +113,23 @@
@NonNull ShellInit shellInit,
@NonNull ShellController shellController,
@NonNull Transitions transitions,
+ @NonNull TaskStackListenerImpl taskStackListener,
@NonNull Handler mainHandler,
@NonNull ShellExecutor mainExecutor) {
mTransitions = transitions;
mShellController = shellController;
mMainHandler = mainHandler;
mMainExecutor = mainExecutor;
+ mTaskStackListener = taskStackListener;
shellInit.addInitCallback(this::onInit, this);
}
private void onInit() {
mTransitions.addHandler(this);
mShellController.addKeyguardChangeListener(this);
+ if (dismissDreamOnKeyguardDismiss()) {
+ mTaskStackListener.addListener(this);
+ }
}
/**
@@ -142,6 +155,11 @@
}
@Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+ mDreamToken = taskInfo.getActivityType() == ACTIVITY_TYPE_DREAM ? taskInfo.token : null;
+ }
+
+ @Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@@ -271,6 +289,13 @@
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
+ if (dismissDreamOnKeyguardDismiss()
+ && (request.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0
+ && mDreamToken != null) {
+ // Dismiss the dream in the same transaction, so that it isn't visible once the device
+ // is unlocked.
+ return new WindowContainerTransaction().removeTask(mDreamToken);
+ }
return null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 4f71a02..7730285 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -54,7 +54,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import java.util.function.Consumer;
/**
* Responsible supplying PiP Transitions.
@@ -125,12 +124,8 @@
/**
* Called when the Shell wants to start resizing Pip transition/animation.
- *
- * @param onFinishResizeCallback callback guaranteed to execute when animation ends and
- * client completes any potential draws upon WM state updates.
*/
- public void startResizeTransition(WindowContainerTransaction wct,
- Consumer<Rect> onFinishResizeCallback) {
+ public void startResizeTransition(WindowContainerTransaction wct) {
// Default implementation does nothing.
}
@@ -266,9 +261,9 @@
}
/** Whether a particular package is same as current pip package. */
- public boolean isInPipPackage(String packageName) {
+ public boolean isPackageActiveInPip(String packageName) {
final TaskInfo inPipTask = mPipOrganizer.getTaskInfo();
- return packageName != null && inPipTask != null
+ return packageName != null && inPipTask != null && mPipOrganizer.isInPip()
&& packageName.equals(SplitScreenUtils.getPackageName(inPipTask.baseIntent));
}
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 1e18b8c..a12882f 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
@@ -16,25 +16,31 @@
package com.android.wm.shell.pip2.phone;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_PIP;
+import android.app.ActivityManager;
import android.app.PictureInPictureParams;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Bundle;
import android.view.InsetsState;
import android.view.SurfaceControl;
import androidx.annotation.BinderThread;
+import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.Preconditions;
import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayLayout;
@@ -42,6 +48,8 @@
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SingleInstanceRemoteListener;
+import com.android.wm.shell.common.TaskStackListenerCallback;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.pip.IPip;
import com.android.wm.shell.common.pip.IPipAnimationListener;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
@@ -57,8 +65,11 @@
* Manages the picture-in-picture (PIP) UI and states for Phones.
*/
public class PipController implements ConfigurationChangeListener,
+ PipTransitionState.PipTransitionStateChangedListener,
DisplayController.OnDisplaysChangedListener, RemoteCallable<PipController> {
private static final String TAG = PipController.class.getSimpleName();
+ private static final String SWIPE_TO_PIP_APP_BOUNDS = "pip_app_bounds";
+ private static final String SWIPE_TO_PIP_OVERLAY = "swipe_to_pip_overlay";
private final Context mContext;
private final ShellController mShellController;
@@ -68,6 +79,9 @@
private final PipBoundsAlgorithm mPipBoundsAlgorithm;
private final PipDisplayLayoutState mPipDisplayLayoutState;
private final PipScheduler mPipScheduler;
+ private final TaskStackListenerImpl mTaskStackListener;
+ private final ShellTaskOrganizer mShellTaskOrganizer;
+ private final PipTransitionState mPipTransitionState;
private final ShellExecutor mMainExecutor;
// Wrapper for making Binder calls into PiP animation listener hosted in launcher's Recents.
@@ -104,6 +118,9 @@
PipBoundsAlgorithm pipBoundsAlgorithm,
PipDisplayLayoutState pipDisplayLayoutState,
PipScheduler pipScheduler,
+ TaskStackListenerImpl taskStackListener,
+ ShellTaskOrganizer shellTaskOrganizer,
+ PipTransitionState pipTransitionState,
ShellExecutor mainExecutor) {
mContext = context;
mShellController = shellController;
@@ -113,6 +130,10 @@
mPipBoundsAlgorithm = pipBoundsAlgorithm;
mPipDisplayLayoutState = pipDisplayLayoutState;
mPipScheduler = pipScheduler;
+ mTaskStackListener = taskStackListener;
+ mShellTaskOrganizer = shellTaskOrganizer;
+ mPipTransitionState = pipTransitionState;
+ mPipTransitionState.addPipTransitionStateChangedListener(this);
mMainExecutor = mainExecutor;
if (PipUtils.isPip2ExperimentEnabled()) {
@@ -132,6 +153,9 @@
PipBoundsAlgorithm pipBoundsAlgorithm,
PipDisplayLayoutState pipDisplayLayoutState,
PipScheduler pipScheduler,
+ TaskStackListenerImpl taskStackListener,
+ ShellTaskOrganizer shellTaskOrganizer,
+ PipTransitionState pipTransitionState,
ShellExecutor mainExecutor) {
if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
@@ -140,7 +164,8 @@
}
return new PipController(context, shellInit, shellController, displayController,
displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState,
- pipScheduler, mainExecutor);
+ pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState,
+ mainExecutor);
}
private void onInit() {
@@ -164,6 +189,17 @@
mShellController.addExternalInterface(KEY_EXTRA_SHELL_PIP,
this::createExternalInterface, this);
mShellController.addConfigurationChangeListener(this);
+
+ mTaskStackListener.addListener(new TaskStackListenerCallback() {
+ @Override
+ public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
+ boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
+ if (task.getWindowingMode() != WINDOWING_MODE_PINNED) {
+ return;
+ }
+ mPipScheduler.scheduleExitPipViaExpand();
+ }
+ });
}
private ExternalInterfaceBinder createExternalInterface() {
@@ -245,11 +281,46 @@
Rect destinationBounds, SurfaceControl overlay, Rect appBounds) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"onSwipePipToHomeAnimationStart: %s", componentName);
- mPipScheduler.onSwipePipToHomeAnimationStart(taskId, componentName, destinationBounds,
- overlay, appBounds);
+ Bundle extra = new Bundle();
+ extra.putParcelable(SWIPE_TO_PIP_OVERLAY, overlay);
+ extra.putParcelable(SWIPE_TO_PIP_APP_BOUNDS, appBounds);
+ mPipTransitionState.setState(PipTransitionState.SWIPING_TO_PIP, extra);
+ if (overlay != null) {
+ // Shell transitions might use a root animation leash, which will be removed when
+ // the Recents transition is finished. Launcher attaches the overlay leash to this
+ // animation target leash; thus, we need to reparent it to the actual Task surface now.
+ // PipTransition is responsible to fade it out and cleanup when finishing the enter PIP
+ // transition.
+ SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
+ mShellTaskOrganizer.reparentChildSurfaceToTask(taskId, overlay, tx);
+ tx.setLayer(overlay, Integer.MAX_VALUE);
+ tx.apply();
+ }
mPipRecentsAnimationListener.onPipAnimationStarted();
}
+ @Override
+ public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState,
+ @PipTransitionState.TransitionState int newState, @Nullable Bundle extra) {
+ if (newState == PipTransitionState.SWIPING_TO_PIP) {
+ Preconditions.checkState(extra != null,
+ "No extra bundle for " + mPipTransitionState);
+
+ SurfaceControl overlay = extra.getParcelable(
+ SWIPE_TO_PIP_OVERLAY, SurfaceControl.class);
+ Rect appBounds = extra.getParcelable(
+ SWIPE_TO_PIP_APP_BOUNDS, Rect.class);
+
+ Preconditions.checkState(appBounds != null,
+ "App bounds can't be null for " + mPipTransitionState);
+ mPipTransitionState.setSwipePipToHomeState(overlay, appBounds);
+ } else if (newState == PipTransitionState.ENTERED_PIP) {
+ if (mPipTransitionState.isInSwipePipToHomeTransition()) {
+ mPipTransitionState.resetSwipePipToHomeState();
+ }
+ }
+ }
+
//
// IPipAnimationListener Binder proxy helpers
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
index b4ca7df..72fa3ba 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
@@ -21,21 +21,16 @@
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
-import android.view.SurfaceControl;
-import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
-import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipUtils;
@@ -43,7 +38,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.function.Consumer;
/**
* Scheduler for Shell initiated PiP transitions and animations.
@@ -55,31 +49,10 @@
private final Context mContext;
private final PipBoundsState mPipBoundsState;
private final ShellExecutor mMainExecutor;
- private final ShellTaskOrganizer mShellTaskOrganizer;
+ private final PipTransitionState mPipTransitionState;
private PipSchedulerReceiver mSchedulerReceiver;
private PipTransitionController mPipTransitionController;
- // pinned PiP task's WC token
- @Nullable
- private WindowContainerToken mPipTaskToken;
-
- // pinned PiP task's leash
- @Nullable
- private SurfaceControl mPinnedTaskLeash;
-
- // true if Launcher has started swipe PiP to home animation
- private boolean mInSwipePipToHomeTransition;
-
- // Overlay leash potentially used during swipe PiP to home transition;
- // if null while mInSwipePipToHomeTransition is true, then srcRectHint was invalid.
- @Nullable
- SurfaceControl mSwipePipToHomeOverlay;
-
- // App bounds used when as a starting point to swipe PiP to home animation in Launcher;
- // these are also used to calculate the app icon overlay buffer size.
- @NonNull
- final Rect mSwipePipToHomeAppBounds = new Rect();
-
/**
* Temporary PiP CUJ codes to schedule PiP related transitions directly from Shell.
* This is used for a broadcast receiver to resolve intents. This should be removed once
@@ -118,11 +91,11 @@
public PipScheduler(Context context,
PipBoundsState pipBoundsState,
ShellExecutor mainExecutor,
- ShellTaskOrganizer shellTaskOrganizer) {
+ PipTransitionState pipTransitionState) {
mContext = context;
mPipBoundsState = pipBoundsState;
mMainExecutor = mainExecutor;
- mShellTaskOrganizer = shellTaskOrganizer;
+ mPipTransitionState = pipTransitionState;
if (PipUtils.isPip2ExperimentEnabled()) {
// temporary broadcast receiver to initiate exit PiP via expand
@@ -140,25 +113,17 @@
mPipTransitionController = pipTransitionController;
}
- void setPinnedTaskLeash(SurfaceControl pinnedTaskLeash) {
- mPinnedTaskLeash = pinnedTaskLeash;
- }
-
- void setPipTaskToken(@Nullable WindowContainerToken pipTaskToken) {
- mPipTaskToken = pipTaskToken;
- }
-
@Nullable
private WindowContainerTransaction getExitPipViaExpandTransaction() {
- if (mPipTaskToken == null) {
+ if (mPipTransitionState.mPipTaskToken == null) {
return null;
}
WindowContainerTransaction wct = new WindowContainerTransaction();
// final expanded bounds to be inherited from the parent
- wct.setBounds(mPipTaskToken, null);
+ wct.setBounds(mPipTransitionState.mPipTaskToken, null);
// if we are hitting a multi-activity case
// windowing mode change will reparent to original host task
- wct.setWindowingMode(mPipTaskToken, WINDOWING_MODE_UNDEFINED);
+ wct.setWindowingMode(mPipTransitionState.mPipTaskToken, WINDOWING_MODE_UNDEFINED);
return wct;
}
@@ -183,43 +148,12 @@
/**
* Animates resizing of the pinned stack given the duration.
*/
- public void scheduleAnimateResizePip(Rect toBounds, Consumer<Rect> onFinishResizeCallback) {
- if (mPipTaskToken == null) {
+ public void scheduleAnimateResizePip(Rect toBounds) {
+ if (mPipTransitionState.mPipTaskToken == null || !mPipTransitionState.isInPip()) {
return;
}
WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.setBounds(mPipTaskToken, toBounds);
- mPipTransitionController.startResizeTransition(wct, onFinishResizeCallback);
- }
-
- void onSwipePipToHomeAnimationStart(int taskId, ComponentName componentName,
- Rect destinationBounds, SurfaceControl overlay, Rect appBounds) {
- mInSwipePipToHomeTransition = true;
- mSwipePipToHomeOverlay = overlay;
- mSwipePipToHomeAppBounds.set(appBounds);
- if (overlay != null) {
- // Shell transitions might use a root animation leash, which will be removed when
- // the Recents transition is finished. Launcher attaches the overlay leash to this
- // animation target leash; thus, we need to reparent it to the actual Task surface now.
- // PipTransition is responsible to fade it out and cleanup when finishing the enter PIP
- // transition.
- SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
- mShellTaskOrganizer.reparentChildSurfaceToTask(taskId, overlay, tx);
- tx.setLayer(overlay, Integer.MAX_VALUE);
- tx.apply();
- }
- }
-
- void setInSwipePipToHomeTransition(boolean inSwipePipToHome) {
- mInSwipePipToHomeTransition = inSwipePipToHome;
- }
-
- boolean isInSwipePipToHomeTransition() {
- return mInSwipePipToHomeTransition;
- }
-
- void onExitPip() {
- mPipTaskToken = null;
- mPinnedTaskLeash = null;
+ wct.setBounds(mPipTransitionState.mPipTaskToken, toBounds);
+ mPipTransitionController.startResizeTransition(wct);
}
}
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 e829d4e..12dce5b 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
@@ -34,6 +34,7 @@
import android.app.PictureInPictureParams;
import android.content.Context;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.IBinder;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -43,6 +44,7 @@
import androidx.annotation.Nullable;
+import com.android.internal.util.Preconditions;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
@@ -54,23 +56,33 @@
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
-import java.util.function.Consumer;
-
/**
* Implementation of transitions for PiP on phone.
*/
-public class PipTransition extends PipTransitionController {
+public class PipTransition extends PipTransitionController implements
+ PipTransitionState.PipTransitionStateChangedListener {
private static final String TAG = PipTransition.class.getSimpleName();
+ private static final String PIP_TASK_TOKEN = "pip_task_token";
+ private static final String PIP_TASK_LEASH = "pip_task_leash";
+
/**
* The fixed start delay in ms when fading out the content overlay from bounds animation.
* The fadeout animation is guaranteed to start after the client has drawn under the new config.
*/
private static final int CONTENT_OVERLAY_FADE_OUT_DELAY_MS = 400;
+ //
+ // Dependencies
+ //
+
private final Context mContext;
private final PipScheduler mPipScheduler;
- @Nullable
- private WindowContainerToken mPipTaskToken;
+ private final PipTransitionState mPipTransitionState;
+
+ //
+ // Transition tokens
+ //
+
@Nullable
private IBinder mEnterTransition;
@Nullable
@@ -78,7 +90,14 @@
@Nullable
private IBinder mResizeTransition;
- private Consumer<Rect> mFinishResizeCallback;
+ //
+ // Internal state and relevant cached info
+ //
+
+ @Nullable
+ private WindowContainerToken mPipTaskToken;
+ @Nullable
+ private SurfaceControl mPipLeash;
public PipTransition(
Context context,
@@ -88,13 +107,16 @@
PipBoundsState pipBoundsState,
PipMenuController pipMenuController,
PipBoundsAlgorithm pipBoundsAlgorithm,
- PipScheduler pipScheduler) {
+ PipScheduler pipScheduler,
+ PipTransitionState pipTransitionState) {
super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController,
pipBoundsAlgorithm);
mContext = context;
mPipScheduler = pipScheduler;
mPipScheduler.setPipTransitionController(this);
+ mPipTransitionState = pipTransitionState;
+ mPipTransitionState.addPipTransitionStateChangedListener(this);
}
@Override
@@ -104,6 +126,10 @@
}
}
+ //
+ // Transition collection stage lifecycle hooks
+ //
+
@Override
public void startExitTransition(int type, WindowContainerTransaction out,
@Nullable Rect destinationBounds) {
@@ -117,13 +143,11 @@
}
@Override
- public void startResizeTransition(WindowContainerTransaction wct,
- Consumer<Rect> onFinishResizeCallback) {
+ public void startResizeTransition(WindowContainerTransaction wct) {
if (wct == null) {
return;
}
mResizeTransition = mTransitions.startTransition(TRANSIT_RESIZE_PIP, wct, this);
- mFinishResizeCallback = onFinishResizeCallback;
}
@Nullable
@@ -146,6 +170,10 @@
}
}
+ //
+ // Transition playing stage lifecycle hooks
+ //
+
@Override
public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@@ -163,7 +191,19 @@
@NonNull Transitions.TransitionFinishCallback finishCallback) {
if (transition == mEnterTransition || info.getType() == TRANSIT_PIP) {
mEnterTransition = null;
- if (mPipScheduler.isInSwipePipToHomeTransition()) {
+ // If we are in swipe PiP to Home transition we are ENTERING_PIP as a jumpcut transition
+ // is being carried out.
+ TransitionInfo.Change pipChange = getPipChange(info);
+
+ // If there is no PiP change, exit this transition handler and potentially try others.
+ if (pipChange == null) return false;
+
+ Bundle extra = new Bundle();
+ extra.putParcelable(PIP_TASK_TOKEN, pipChange.getContainer());
+ extra.putParcelable(PIP_TASK_LEASH, pipChange.getLeash());
+ mPipTransitionState.setState(PipTransitionState.ENTERING_PIP, extra);
+
+ if (mPipTransitionState.isInSwipePipToHomeTransition()) {
// If this is the second transition as a part of swipe PiP to home cuj,
// handle this transition as a special case with no-op animation.
return handleSwipePipToHomeTransition(info, startTransaction, finishTransaction,
@@ -179,9 +219,11 @@
finishCallback);
} else if (transition == mExitViaExpandTransition) {
mExitViaExpandTransition = null;
+ mPipTransitionState.setState(PipTransitionState.EXITING_PIP);
return startExpandAnimation(info, startTransaction, finishTransaction, finishCallback);
} else if (transition == mResizeTransition) {
mResizeTransition = null;
+ mPipTransitionState.setState(PipTransitionState.CHANGING_PIP_BOUNDS);
return startResizeAnimation(info, startTransaction, finishTransaction, finishCallback);
}
@@ -191,6 +233,10 @@
return false;
}
+ //
+ // Animation schedulers and entry points
+ //
+
private boolean startResizeAnimation(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@@ -236,11 +282,7 @@
if (pipChange == null) {
return false;
}
- mPipScheduler.setInSwipePipToHomeTransition(false);
- mPipTaskToken = pipChange.getContainer();
-
- // cache the PiP task token and leash
- mPipScheduler.setPipTaskToken(mPipTaskToken);
+ WindowContainerToken pipTaskToken = pipChange.getContainer();
SurfaceControl pipLeash = pipChange.getLeash();
PictureInPictureParams params = pipChange.getTaskInfo().pictureInPictureParams;
@@ -264,9 +306,9 @@
} else {
final float scaleX = (float) destinationBounds.width() / startBounds.width();
final float scaleY = (float) destinationBounds.height() / startBounds.height();
- final int overlaySize = PipContentOverlay.PipAppIconOverlay
- .getOverlaySize(mPipScheduler.mSwipePipToHomeAppBounds, destinationBounds);
- SurfaceControl overlayLeash = mPipScheduler.mSwipePipToHomeOverlay;
+ final int overlaySize = PipContentOverlay.PipAppIconOverlay.getOverlaySize(
+ mPipTransitionState.getSwipePipToHomeAppBounds(), destinationBounds);
+ SurfaceControl overlayLeash = mPipTransitionState.getSwipePipToHomeOverlay();
startTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top)
.setScale(pipLeash, scaleX, scaleY)
@@ -274,7 +316,7 @@
.reparent(overlayLeash, pipLeash)
.setLayer(overlayLeash, Integer.MAX_VALUE);
- if (mPipTaskToken != null) {
+ if (pipTaskToken != null) {
SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
tx.addTransactionCommittedListener(mPipScheduler.getMainExecutor(),
this::onClientDrawAtTransitionEnd)
@@ -282,7 +324,7 @@
.setPosition(overlayLeash,
(destinationBounds.width() - overlaySize) / 2f,
(destinationBounds.height() - overlaySize) / 2f);
- finishWct.setBoundsChangeTransaction(mPipTaskToken, tx);
+ finishWct.setBoundsChangeTransaction(pipTaskToken, tx);
}
}
startTransaction.apply();
@@ -293,14 +335,6 @@
return true;
}
- private void onClientDrawAtTransitionEnd() {
- startOverlayFadeoutAnimation();
- }
-
- //
- // Subroutines setting up and starting transitions' animations.
- //
-
private void startOverlayFadeoutAnimation() {
ValueAnimator animator = ValueAnimator.ofFloat(1f, 0f);
animator.setDuration(CONTENT_OVERLAY_FADE_OUT_DELAY_MS);
@@ -309,15 +343,17 @@
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
- tx.remove(mPipScheduler.mSwipePipToHomeOverlay);
+ tx.remove(mPipTransitionState.getSwipePipToHomeOverlay());
tx.apply();
- mPipScheduler.mSwipePipToHomeOverlay = null;
+
+ // We have fully completed enter-PiP animation after the overlay is gone.
+ mPipTransitionState.setState(PipTransitionState.ENTERED_PIP);
}
});
animator.addUpdateListener(animation -> {
float alpha = (float) animation.getAnimatedValue();
SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
- tx.setAlpha(mPipScheduler.mSwipePipToHomeOverlay, alpha).apply();
+ tx.setAlpha(mPipTransitionState.getSwipePipToHomeOverlay(), alpha).apply();
});
animator.start();
}
@@ -330,10 +366,8 @@
if (pipChange == null) {
return false;
}
- mPipTaskToken = pipChange.getContainer();
-
// cache the PiP task token and leash
- mPipScheduler.setPipTaskToken(mPipTaskToken);
+ WindowContainerToken pipTaskToken = pipChange.getContainer();
startTransaction.apply();
// TODO: b/275910498 Use a new implementation of the PiP animator here.
@@ -349,10 +383,8 @@
if (pipChange == null) {
return false;
}
- mPipTaskToken = pipChange.getContainer();
-
// cache the PiP task token and leash
- mPipScheduler.setPipTaskToken(mPipTaskToken);
+ WindowContainerToken pipTaskToken = pipChange.getContainer();
startTransaction.apply();
finishCallback.onTransitionFinished(null);
@@ -366,7 +398,7 @@
startTransaction.apply();
// TODO: b/275910498 Use a new implementation of the PiP animator here.
finishCallback.onTransitionFinished(null);
- onExitPip();
+ mPipTransitionState.setState(PipTransitionState.EXITED_PIP);
return true;
}
@@ -376,12 +408,20 @@
@NonNull Transitions.TransitionFinishCallback finishCallback) {
startTransaction.apply();
finishCallback.onTransitionFinished(null);
- onExitPip();
+ mPipTransitionState.setState(PipTransitionState.EXITED_PIP);
return true;
}
+ /**
+ * TODO: b/275910498 Use a new implementation of the PiP animator here.
+ */
+ private void startResizeAnimation(SurfaceControl leash, Rect startBounds,
+ Rect endBounds, int duration) {
+ mPipTransitionState.setState(PipTransitionState.CHANGED_PIP_BOUNDS);
+ }
+
//
- // Utility methods for checking PiP-related transition info and requests.
+ // Various helpers to resolve transition requests and infos
//
@Nullable
@@ -442,11 +482,11 @@
}
private boolean isRemovePipTransition(@NonNull TransitionInfo info) {
- if (mPipTaskToken == null) {
+ if (mPipTransitionState.mPipTaskToken == null) {
// PiP removal makes sense if enter-PiP has cached a valid pinned task token.
return false;
}
- TransitionInfo.Change pipChange = info.getChange(mPipTaskToken);
+ TransitionInfo.Change pipChange = info.getChange(mPipTransitionState.mPipTaskToken);
if (pipChange == null) {
// Search for the PiP change by token since the windowing mode might be FULLSCREEN now.
return false;
@@ -460,14 +500,43 @@
return isPipMovedToBack || isPipClosed;
}
- /**
- * TODO: b/275910498 Use a new implementation of the PiP animator here.
- */
- private void startResizeAnimation(SurfaceControl leash, Rect startBounds,
- Rect endBounds, int duration) {}
+ //
+ // Miscellaneous callbacks and listeners
+ //
- private void onExitPip() {
- mPipTaskToken = null;
- mPipScheduler.onExitPip();
+ private void onClientDrawAtTransitionEnd() {
+ if (mPipTransitionState.getSwipePipToHomeOverlay() != null) {
+ startOverlayFadeoutAnimation();
+ } else if (mPipTransitionState.getState() == PipTransitionState.ENTERING_PIP) {
+ // If we were entering PiP (i.e. playing the animation) with a valid srcRectHint,
+ // and then we get a signal on client finishing its draw after the transition
+ // has ended, then we have fully entered PiP.
+ mPipTransitionState.setState(PipTransitionState.ENTERED_PIP);
+ }
+ }
+
+ @Override
+ public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState,
+ @PipTransitionState.TransitionState int newState, @Nullable Bundle extra) {
+ switch (newState) {
+ case PipTransitionState.ENTERING_PIP:
+ Preconditions.checkState(extra != null,
+ "No extra bundle for " + mPipTransitionState);
+
+ mPipTransitionState.mPipTaskToken = extra.getParcelable(
+ PIP_TASK_TOKEN, WindowContainerToken.class);
+ mPipTransitionState.mPinnedTaskLeash = extra.getParcelable(
+ PIP_TASK_LEASH, SurfaceControl.class);
+ boolean hasValidTokenAndLeash = mPipTransitionState.mPipTaskToken != null
+ && mPipTransitionState.mPinnedTaskLeash != null;
+
+ Preconditions.checkState(hasValidTokenAndLeash,
+ "Unexpected bundle for " + mPipTransitionState);
+ break;
+ case PipTransitionState.EXITED_PIP:
+ mPipTransitionState.mPipTaskToken = null;
+ mPipTransitionState.mPinnedTaskLeash = null;
+ break;
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java
new file mode 100644
index 0000000..f7bc622
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip2.phone;
+
+import android.annotation.IntDef;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.SurfaceControl;
+import android.window.WindowContainerToken;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains the state relevant to carry out or probe the status of PiP transitions.
+ *
+ * <p>Existing and new PiP components can subscribe to PiP transition related state changes
+ * via <code>PipTransitionStateChangedListener</code>.</p>
+ *
+ * <p><code>PipTransitionState</code> users shouldn't rely on listener execution ordering.
+ * For example, if a class <code>Foo</code> wants to change some arbitrary state A that belongs
+ * to some other class <code>Bar</code>, a special care must be given when manipulating state A in
+ * <code>Foo#onPipTransitionStateChanged()</code>, since that's the responsibility of
+ * the class <code>Bar</code>.</p>
+ *
+ * <p>Hence, the recommended usage for classes who want to subscribe to
+ * <code>PipTransitionState</code> changes is to manipulate only their own internal state or
+ * <code>PipTransitionState</code> state.</p>
+ *
+ * <p>If there is some state that must be manipulated in another class <code>Bar</code>, it should
+ * just be moved to <code>PipTransitionState</code> and become a shared state
+ * between Foo and Bar.</p>
+ *
+ * <p>Moreover, <code>onPipTransitionStateChanged(oldState, newState, extra)</code>
+ * receives a <code>Bundle</code> extra object that can be optionally set via
+ * <code>setState(state, extra)</code>. This can be used to resolve extra information to update
+ * relevant internal or <code>PipTransitionState</code> state. However, each listener
+ * needs to check for whether the extra passed is correct for a particular state,
+ * and throw an <code>IllegalStateException</code> otherwise.</p>
+ */
+public class PipTransitionState {
+ public static final int UNDEFINED = 0;
+
+ // State for Launcher animating the swipe PiP to home animation.
+ public static final int SWIPING_TO_PIP = 1;
+
+ // State for Shell animating enter PiP or jump-cutting to PiP mode after Launcher animation.
+ public static final int ENTERING_PIP = 2;
+
+ // State for app finishing drawing in PiP mode as a final step in enter PiP flow.
+ public static final int ENTERED_PIP = 3;
+
+ // State for scheduling a transition to change PiP bounds.
+ public static final int CHANGING_PIP_BOUNDS = 4;
+
+ // State for app potentially finishing drawing in new PiP bounds after resize is complete.
+ public static final int CHANGED_PIP_BOUNDS = 5;
+
+ // State for starting exiting PiP.
+ public static final int EXITING_PIP = 6;
+
+ // State for finishing exit PiP flow.
+ public static final int EXITED_PIP = 7;
+
+ private static final int FIRST_CUSTOM_STATE = 1000;
+
+ private int mPrevCustomState = FIRST_CUSTOM_STATE;
+
+ @IntDef(prefix = { "TRANSITION_STATE_" }, value = {
+ UNDEFINED,
+ SWIPING_TO_PIP,
+ ENTERING_PIP,
+ ENTERED_PIP,
+ CHANGING_PIP_BOUNDS,
+ CHANGED_PIP_BOUNDS,
+ EXITING_PIP,
+ EXITED_PIP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TransitionState {}
+
+ @TransitionState
+ private int mState;
+
+ //
+ // Swipe up to enter PiP related state
+ //
+
+ // true if Launcher has started swipe PiP to home animation
+ private boolean mInSwipePipToHomeTransition;
+
+ // App bounds used when as a starting point to swipe PiP to home animation in Launcher;
+ // these are also used to calculate the app icon overlay buffer size.
+ @NonNull
+ private final Rect mSwipePipToHomeAppBounds = new Rect();
+
+ //
+ // Tokens and leashes
+ //
+
+ // pinned PiP task's WC token
+ @Nullable
+ WindowContainerToken mPipTaskToken;
+
+ // pinned PiP task's leash
+ @Nullable
+ SurfaceControl mPinnedTaskLeash;
+
+ // Overlay leash potentially used during swipe PiP to home transition;
+ // if null while mInSwipePipToHomeTransition is true, then srcRectHint was invalid.
+ @Nullable
+ private SurfaceControl mSwipePipToHomeOverlay;
+
+ /**
+ * An interface to track state updates as we progress through PiP transitions.
+ */
+ public interface PipTransitionStateChangedListener {
+
+ /** Reports changes in PiP transition state. */
+ void onPipTransitionStateChanged(@TransitionState int oldState,
+ @TransitionState int newState, @Nullable Bundle extra);
+ }
+
+ private final List<PipTransitionStateChangedListener> mCallbacks = new ArrayList<>();
+
+ /**
+ * @return the state of PiP in the context of transitions.
+ */
+ @TransitionState
+ public int getState() {
+ return mState;
+ }
+
+ /**
+ * Sets the state of PiP in the context of transitions.
+ */
+ public void setState(@TransitionState int state) {
+ setState(state, null /* extra */);
+ }
+
+ /**
+ * Sets the state of PiP in the context of transitions
+ *
+ * @param extra a bundle passed to the subscribed listeners to resolve/cache extra info.
+ */
+ public void setState(@TransitionState int state, @Nullable Bundle extra) {
+ if (state == ENTERING_PIP || state == SWIPING_TO_PIP) {
+ // Whenever we are entering PiP caller must provide extra state to set as well.
+ Preconditions.checkArgument(extra != null && !extra.isEmpty(),
+ "No extra bundle for either ENTERING_PIP or SWIPING_TO_PIP state.");
+ }
+ if (mState != state) {
+ dispatchPipTransitionStateChanged(mState, state, extra);
+ mState = state;
+ }
+ }
+
+ private void dispatchPipTransitionStateChanged(@TransitionState int oldState,
+ @TransitionState int newState, @Nullable Bundle extra) {
+ mCallbacks.forEach(l -> l.onPipTransitionStateChanged(oldState, newState, extra));
+ }
+
+ /**
+ * Adds a {@link PipTransitionStateChangedListener} for future PiP transition state updates.
+ */
+ public void addPipTransitionStateChangedListener(PipTransitionStateChangedListener listener) {
+ if (mCallbacks.contains(listener)) {
+ return;
+ }
+ mCallbacks.add(listener);
+ }
+
+ /**
+ * @return true if provided {@link PipTransitionStateChangedListener}
+ * is registered before removing it.
+ */
+ public boolean removePipTransitionStateChangedListener(
+ PipTransitionStateChangedListener listener) {
+ return mCallbacks.remove(listener);
+ }
+
+ /**
+ * @return true if we have fully entered PiP.
+ */
+ public boolean isInPip() {
+ return mState > ENTERING_PIP && mState < EXITING_PIP;
+ }
+
+ void setSwipePipToHomeState(@Nullable SurfaceControl overlayLeash,
+ @NonNull Rect appBounds) {
+ mInSwipePipToHomeTransition = true;
+ if (overlayLeash != null && !appBounds.isEmpty()) {
+ mSwipePipToHomeOverlay = overlayLeash;
+ mSwipePipToHomeAppBounds.set(appBounds);
+ }
+ }
+
+ void resetSwipePipToHomeState() {
+ mInSwipePipToHomeTransition = false;
+ mSwipePipToHomeOverlay = null;
+ mSwipePipToHomeAppBounds.setEmpty();
+ }
+
+ /**
+ * @return true if in swipe PiP to home. Note that this is true until overlay fades if used too.
+ */
+ public boolean isInSwipePipToHomeTransition() {
+ return mInSwipePipToHomeTransition;
+ }
+
+ /**
+ * @return the overlay used during swipe PiP to home for invalid srcRectHints in auto-enter PiP;
+ * null if srcRectHint provided is valid.
+ */
+ @Nullable
+ public SurfaceControl getSwipePipToHomeOverlay() {
+ return mSwipePipToHomeOverlay;
+ }
+
+ /**
+ * @return app bounds used to calculate
+ */
+ @NonNull
+ public Rect getSwipePipToHomeAppBounds() {
+ return mSwipePipToHomeAppBounds;
+ }
+
+ /**
+ * @return a custom state solely for internal use by the caller.
+ */
+ @TransitionState
+ public int getCustomState() {
+ return ++mPrevCustomState;
+ }
+
+ private String stateToString() {
+ switch (mState) {
+ case UNDEFINED: return "undefined";
+ case ENTERING_PIP: return "entering-pip";
+ case ENTERED_PIP: return "entered-pip";
+ case CHANGING_PIP_BOUNDS: return "changing-bounds";
+ case CHANGED_PIP_BOUNDS: return "changed-bounds";
+ case EXITING_PIP: return "exiting-pip";
+ case EXITED_PIP: return "exited-pip";
+ }
+ throw new IllegalStateException("Unknown state: " + mState);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PipTransitionState(mState=%s, mInSwipePipToHomeTransition=%b)",
+ stateToString(), mInSwipePipToHomeTransition);
+ }
+}
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 4c68106..5e9451a 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
@@ -201,7 +201,7 @@
private final DisplayImeController mDisplayImeController;
private final DisplayInsetsController mDisplayInsetsController;
private final TransactionPool mTransactionPool;
- private final SplitScreenTransitions mSplitTransitions;
+ private SplitScreenTransitions mSplitTransitions;
private final SplitscreenEventLogger mLogger;
private final ShellExecutor mMainExecutor;
// Cache live tile tasks while entering recents, evict them from stages in finish transaction
@@ -399,6 +399,11 @@
return mSplitTransitions;
}
+ @VisibleForTesting
+ void setSplitTransitions(SplitScreenTransitions splitScreenTransitions) {
+ mSplitTransitions = splitScreenTransitions;
+ }
+
public boolean isSplitScreenVisible() {
return mSideStageListener.mVisible && mMainStageListener.mVisible;
}
@@ -583,7 +588,7 @@
options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */);
wct.startTask(taskId, options);
// If this should be mixed, send the task to avoid split handle transition directly.
- if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(taskId, mTaskOrganizer)) {
+ if (mMixedHandler != null && mMixedHandler.isTaskInPip(taskId, mTaskOrganizer)) {
mTaskOrganizer.applyTransaction(wct);
return;
}
@@ -622,7 +627,7 @@
wct.sendPendingIntent(intent, fillInIntent, options);
// If this should be mixed, just send the intent to avoid split handle transition directly.
- if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(intent)) {
+ if (mMixedHandler != null && mMixedHandler.isIntentInPip(intent)) {
mTaskOrganizer.applyTransaction(wct);
return;
}
@@ -711,16 +716,7 @@
taskId1, taskId2, splitPosition, snapPosition);
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (taskId2 == INVALID_TASK_ID) {
- if (mMainStage.containsTask(taskId1) || mSideStage.containsTask(taskId1)) {
- prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
- }
- if (mRecentTasks.isPresent()) {
- mRecentTasks.get().removeSplitPair(taskId1);
- }
- options1 = options1 != null ? options1 : new Bundle();
- addActivityOptions(options1, null);
- wct.startTask(taskId1, options1);
- mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+ startSingleTask(taskId1, options1, wct, remoteTransition);
return;
}
@@ -741,11 +737,15 @@
"startIntentAndTask: intent=%s task1=%d position=%d snapPosition=%d",
pendingIntent.getIntent(), taskId, splitPosition, snapPosition);
final WindowContainerTransaction wct = new WindowContainerTransaction();
- if (taskId == INVALID_TASK_ID) {
- options1 = options1 != null ? options1 : new Bundle();
- addActivityOptions(options1, null);
- wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
- mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+ boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent);
+ boolean secondTaskPipped = mMixedHandler.isTaskInPip(taskId, mTaskOrganizer);
+ if (taskId == INVALID_TASK_ID || secondTaskPipped) {
+ startSingleIntent(pendingIntent, fillInIntent, options1, wct, remoteTransition);
+ return;
+ }
+
+ if (firstIntentPipped) {
+ startSingleTask(taskId, options2, wct, remoteTransition);
return;
}
@@ -757,6 +757,24 @@
startWithTask(wct, taskId, options2, snapPosition, remoteTransition, instanceId);
}
+ /**
+ * @param taskId Starts this task in fullscreen, removing it from existing pairs if it was part
+ * of one.
+ */
+ private void startSingleTask(int taskId, Bundle options, WindowContainerTransaction wct,
+ RemoteTransition remoteTransition) {
+ if (mMainStage.containsTask(taskId) || mSideStage.containsTask(taskId)) {
+ prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
+ }
+ if (mRecentTasks.isPresent()) {
+ mRecentTasks.get().removeSplitPair(taskId);
+ }
+ options = options != null ? options : new Bundle();
+ addActivityOptions(options, null);
+ wct.startTask(taskId, options);
+ mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+ }
+
/** Starts a shortcut and a task to a split pair in one transition. */
void startShortcutAndTask(ShortcutInfo shortcutInfo, @Nullable Bundle options1,
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
@@ -844,6 +862,21 @@
return;
}
+ boolean handledForPipSplitLaunch = handlePippedSplitIntentsLaunch(
+ pendingIntent1,
+ pendingIntent2,
+ options1,
+ options2,
+ shortcutInfo1,
+ shortcutInfo2,
+ wct,
+ fillInIntent1,
+ fillInIntent2,
+ remoteTransition);
+ if (handledForPipSplitLaunch) {
+ return;
+ }
+
if (!mMainStage.isActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
// while task 1 is on the side stage.
@@ -878,6 +911,46 @@
setEnterInstanceId(instanceId);
}
+ /**
+ * Checks if either of the apps in the desired split launch is currently in Pip. If so, it will
+ * launch the non-pipped app as a fullscreen app, otherwise no-op.
+ */
+ private boolean handlePippedSplitIntentsLaunch(PendingIntent pendingIntent1,
+ PendingIntent pendingIntent2, Bundle options1, Bundle options2,
+ ShortcutInfo shortcutInfo1, ShortcutInfo shortcutInfo2, WindowContainerTransaction wct,
+ Intent fillInIntent1, Intent fillInIntent2, RemoteTransition remoteTransition) {
+ // If one of the split apps to start is in Pip, only launch the non-pip app in fullscreen
+ boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent1);
+ boolean secondIntentPipped = mMixedHandler.isIntentInPip(pendingIntent2);
+ if (firstIntentPipped || secondIntentPipped) {
+ Bundle options = secondIntentPipped ? options1 : options2;
+ options = options == null ? new Bundle() : options;
+ addActivityOptions(options, null);
+ if (shortcutInfo1 != null || shortcutInfo2 != null) {
+ ShortcutInfo infoToLaunch = secondIntentPipped ? shortcutInfo1 : shortcutInfo2;
+ wct.startShortcut(mContext.getPackageName(), infoToLaunch, options);
+ mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+ } else {
+ PendingIntent intentToLaunch = secondIntentPipped ? pendingIntent1 : pendingIntent2;
+ Intent fillInIntentToLaunch = secondIntentPipped ? fillInIntent1 : fillInIntent2;
+ startSingleIntent(intentToLaunch, fillInIntentToLaunch, options, wct,
+ remoteTransition);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /** @param pendingIntent Starts this intent in fullscreen */
+ private void startSingleIntent(PendingIntent pendingIntent, Intent fillInIntent, Bundle options,
+ WindowContainerTransaction wct,
+ RemoteTransition remoteTransition) {
+ Bundle optionsToLaunch = options != null ? options : new Bundle();
+ addActivityOptions(optionsToLaunch, null);
+ wct.sendPendingIntent(pendingIntent, fillInIntent, optionsToLaunch);
+ mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+ }
+
/** Starts a pair of tasks using legacy transition. */
void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1,
int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition,
@@ -3351,6 +3424,11 @@
true /* reparentLeafTaskIfRelaunch */);
}
+ /** Call this when the animation from split screen to desktop is started. */
+ public void onSplitToDesktop() {
+ setSplitsVisible(false);
+ }
+
/** Call this when the recents animation finishes by doing pair-to-pair switch. */
public void onRecentsPairToPairAnimationFinish(WindowContainerTransaction finishWct) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onRecentsPairToPairAnimationFinish");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index ceac40d..66b3553 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -21,13 +21,14 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.window.flags.Flags.windowSessionRelayoutInfo;
+
import android.annotation.BinderThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.graphics.Paint;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
@@ -43,6 +44,7 @@
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.WindowRelayoutResult;
import android.window.ActivityWindowInfo;
import android.window.ClientWindowFrames;
import android.window.SnapshotDrawerUtils;
@@ -100,8 +102,6 @@
return null;
}
- final Point taskSize = snapshot.getTaskSize();
- final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final int orientation = snapshot.getOrientation();
final int displayId = runningTaskInfo.displayId;
@@ -139,9 +139,16 @@
}
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#relayout");
- session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, 0, 0,
- tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState,
- tmpControls, new Bundle());
+ if (windowSessionRelayoutInfo()) {
+ final WindowRelayoutResult outRelayoutResult = new WindowRelayoutResult(tmpFrames,
+ tmpMergedConfiguration, surfaceControl, tmpInsetsState, tmpControls);
+ session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, 0, 0,
+ outRelayoutResult);
+ } else {
+ session.relayoutLegacy(window, layoutParams, -1, -1, View.VISIBLE, 0, 0, 0,
+ tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState,
+ tmpControls, new Bundle());
+ }
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RemoteException e) {
snapshotSurface.clearWindowSynced();
@@ -150,7 +157,7 @@
}
SnapshotDrawerUtils.drawSnapshotOnSurface(info, layoutParams, surfaceControl, snapshot,
- taskBounds, tmpFrames.frame, topWindowInsetsState, true /* releaseAfterDraw */);
+ info.taskBounds, topWindowInsetsState, true /* releaseAfterDraw */);
snapshotSurface.mHasDrawn = true;
snapshotSurface.reportDrawn();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
index fed2f34..5c814dc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
@@ -23,7 +23,6 @@
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.content.Context;
-import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.view.Display;
@@ -77,15 +76,13 @@
runningTaskInfo.configuration, rootSurface);
final SurfaceControlViewHost mViewHost = new SurfaceControlViewHost(
mContext, display, wlw, "WindowlessSnapshotWindowCreator");
- final Point taskSize = snapshot.getTaskSize();
- final Rect snapshotBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final Rect windowBounds = runningTaskInfo.configuration.windowConfiguration.getBounds();
final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
final FrameLayout rootLayout = new FrameLayout(
mSplashscreenContentDrawer.createViewContextWrapper(mContext));
mViewHost.setView(rootLayout, lp);
SnapshotDrawerUtils.drawSnapshotOnSurface(info, lp, wlw.mChildSurface, snapshot,
- snapshotBounds, windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
+ windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
final ActivityManager.TaskDescription taskDescription =
SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
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 4bc0dc0..4d02ec2 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
@@ -563,22 +563,23 @@
/** Use to when split use intent to enter, check if this enter transition should be mixed or
* not.*/
- public boolean shouldSplitEnterMixed(PendingIntent intent) {
+ public boolean isIntentInPip(PendingIntent intent) {
// Check if this intent package is same as pip one or not, if true we want let the pip
// task enter split.
if (mPipHandler != null) {
- return mPipHandler.isInPipPackage(SplitScreenUtils.getPackageName(intent.getIntent()));
+ return mPipHandler
+ .isPackageActiveInPip(SplitScreenUtils.getPackageName(intent.getIntent()));
}
return false;
}
/** Use to when split use taskId to enter, check if this enter transition should be mixed or
* not.*/
- public boolean shouldSplitEnterMixed(int taskId, ShellTaskOrganizer shellTaskOrganizer) {
+ public boolean isTaskInPip(int taskId, ShellTaskOrganizer shellTaskOrganizer) {
// Check if this intent package is same as pip one or not, if true we want let the pip
// task enter split.
if (mPipHandler != null) {
- return mPipHandler.isInPipPackage(
+ return mPipHandler.isPackageActiveInPip(
SplitScreenUtils.getPackageName(taskId, shellTaskOrganizer));
}
return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index c6b127d..9b2922d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -44,9 +44,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityTaskManager;
+import android.app.AppGlobals;
import android.app.IApplicationThread;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.IBinder;
@@ -126,8 +128,7 @@
static final String TAG = "ShellTransitions";
/** Set to {@code true} to enable shell transitions. */
- public static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+ public static final boolean ENABLE_SHELL_TRANSITIONS = getShellTransitEnabled();
public static final boolean SHELL_TRANSITIONS_ROTATION = ENABLE_SHELL_TRANSITIONS
&& SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
@@ -1710,4 +1711,16 @@
}
}
}
+
+ private static boolean getShellTransitEnabled() {
+ try {
+ if (AppGlobals.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE, 0)) {
+ return SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+ }
+ } catch (RemoteException re) {
+ Log.w(TAG, "Error getting system features");
+ }
+ return true;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
index ed4ae05..1897560 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.transition.tracing;
+import static android.tracing.perfetto.DataSourceParams.PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT;
+
import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellHandlerMapping;
import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellHandlerMappings;
import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellTransition;
@@ -47,7 +49,8 @@
public PerfettoTransitionTracer() {
Producer.init(InitArguments.DEFAULTS);
- mDataSource.register(DataSourceParams.DEFAULTS);
+ mDataSource.register(
+ new DataSourceParams(PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT));
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 43fd32b..6671391 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -200,7 +200,6 @@
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
mRelayoutParams.mSetTaskPositionAndCrop = setTaskCropAndPosition;
- mRelayoutParams.mAllowCaptionInputFallthrough = false;
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
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 6a9d17f..01175f5 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
@@ -16,6 +16,7 @@
package com.android.wm.shell.windowdecor;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -34,6 +35,7 @@
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.compatui.AppCompatUtils.isSingleTopActivityTranslucent;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR;
+import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -272,10 +274,9 @@
mSplitScreenController.registerSplitScreenListener(new SplitScreen.SplitScreenListener() {
@Override
public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
- if (visible) {
+ if (visible && stage != STAGE_TYPE_UNDEFINED) {
DesktopModeWindowDecoration decor = mWindowDecorByTaskId.get(taskId);
- if (decor != null && DesktopModeStatus.isEnabled()
- && decor.mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ if (decor != null && DesktopModeStatus.isEnabled()) {
mDesktopTasksController.moveToSplit(decor.mTaskInfo);
}
}
@@ -915,6 +916,11 @@
@Nullable
private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
+ // If we are mid-transition, dragged task's decor is always relevant.
+ final int draggedTaskId = mDesktopTasksController.getDraggingTaskId();
+ if (draggedTaskId != INVALID_TASK_ID) {
+ return mWindowDecorByTaskId.get(draggedTaskId);
+ }
final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
if (focusedDecor == null) {
return null;
@@ -1037,7 +1043,6 @@
mSyncQueue,
mRootTaskDisplayAreaOrganizer);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
- windowDecoration.createResizeVeil();
final DragPositioningCallback dragPositioningCallback;
if (!DesktopModeStatus.isVeiledResizeEnabled()) {
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 9349c93..8c6bc73 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
@@ -44,6 +44,7 @@
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.os.Trace;
import android.util.Log;
import android.util.Size;
import android.view.Choreographer;
@@ -51,6 +52,7 @@
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.WindowManager;
import android.widget.ImageButton;
import android.window.WindowContainerTransaction;
@@ -152,13 +154,10 @@
surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
windowContainerTransactionSupplier, surfaceControlSupplier,
surfaceControlViewHostFactory);
-
mHandler = handler;
mChoreographer = choreographer;
mSyncQueue = syncQueue;
mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
-
- loadAppInfo();
}
void setCaptionListeners(
@@ -204,6 +203,7 @@
void relayout(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
+ Trace.beginSection("DesktopModeWindowDecoration#relayout");
if (isHandleMenuActive()) {
mHandleMenu.relayout(startT);
}
@@ -215,16 +215,22 @@
final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ Trace.beginSection("DesktopModeWindowDecoration#relayout-inner");
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
+ Trace.endSection();
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
+ Trace.beginSection("DesktopModeWindowDecoration#relayout-applyWCT");
mTaskOrganizer.applyTransaction(wct);
+ Trace.endSection();
if (mResult.mRootView == null) {
// This means something blocks the window decor from showing, e.g. the task is hidden.
// Nothing is set up in this case including the decoration surface.
+ Trace.endSection(); // DesktopModeWindowDecoration#relayout
return;
}
+
if (oldRootView != mResult.mRootView) {
if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_focused_window_decor) {
mWindowDecorViewHolder = new DesktopModeFocusedWindowDecorationViewHolder(
@@ -234,6 +240,7 @@
);
} else if (mRelayoutParams.mLayoutResId
== R.layout.desktop_mode_app_controls_window_decor) {
+ loadAppInfoIfNeeded();
mWindowDecorViewHolder = new DesktopModeAppControlsWindowDecorationViewHolder(
mResult.mRootView,
mOnCaptionTouchListener,
@@ -252,7 +259,9 @@
throw new IllegalArgumentException("Unexpected layout resource id");
}
}
+ Trace.beginSection("DesktopModeWindowDecoration#relayout-binding");
mWindowDecorViewHolder.bindData(mTaskInfo);
+ Trace.endSection();
if (!mTaskInfo.isFocused) {
closeHandleMenu();
@@ -268,11 +277,13 @@
updateExclusionRegion();
}
closeDragResizeListener();
+ Trace.endSection(); // DesktopModeWindowDecoration#relayout
return;
}
if (oldDecorationSurface != mDecorationContainerSurface || mDragResizeListener == null) {
closeDragResizeListener();
+ Trace.beginSection("DesktopModeWindowDecoration#relayout-DragResizeInputListener");
mDragResizeListener = new DragResizeInputListener(
mContext,
mHandler,
@@ -283,6 +294,7 @@
mSurfaceControlBuilderSupplier,
mSurfaceControlTransactionSupplier,
mDisplayController);
+ Trace.endSection();
}
final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
@@ -307,6 +319,7 @@
mMaximizeMenu.positionMenu(calculateMaximizeMenuPosition(), startT);
}
}
+ Trace.endSection(); // DesktopModeWindowDecoration#relayout
}
@VisibleForTesting
@@ -324,11 +337,12 @@
relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
if (captionLayoutId == R.layout.desktop_mode_app_controls_window_decor) {
- // If the app is requesting to customize the caption bar, allow input to fall through
- // to the windows below so that the app can respond to input events on their custom
- // content.
- relayoutParams.mAllowCaptionInputFallthrough =
- TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo);
+ if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) {
+ // If the app is requesting to customize the caption bar, allow input to fall
+ // through to the windows below so that the app can respond to input events on
+ // their custom content.
+ relayoutParams.mInputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY;
+ }
// Report occluding elements as bounding rects to the insets system so that apps can
// draw in the empty space in the center:
// First, the "app chip" section of the caption bar (+ some extra margins).
@@ -343,6 +357,11 @@
controlsElement.mWidthResId = R.dimen.desktop_mode_customizable_caption_margin_end;
controlsElement.mAlignment = RelayoutParams.OccludingCaptionElement.Alignment.END;
relayoutParams.mOccludingCaptionElements.add(controlsElement);
+ } else if (captionLayoutId == R.layout.desktop_mode_focused_window_decor) {
+ // The focused decor (fullscreen/split) does not need to handle input because input in
+ // the App Handle is handled by the InputMonitor in DesktopModeWindowDecorViewModel.
+ relayoutParams.mInputFeatures
+ |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
}
if (DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ taskInfo.isFocused)) {
relayoutParams.mShadowRadiusId = taskInfo.isFocused
@@ -434,22 +453,31 @@
return mDragResizeListener != null && mDragResizeListener.isHandlingDragResize();
}
- private void loadAppInfo() {
- final ActivityInfo activityInfo = mTaskInfo.topActivityInfo;
- if (activityInfo == null) {
- Log.e(TAG, "Top activity info not found in task");
- return;
+ private void loadAppInfoIfNeeded() {
+ // TODO(b/337370277): move this to another thread.
+ try {
+ Trace.beginSection("DesktopModeWindowDecoration#loadAppInfoIfNeeded");
+ if (mAppIconBitmap != null && mAppName != null) {
+ return;
+ }
+ final ActivityInfo activityInfo = mTaskInfo.topActivityInfo;
+ if (activityInfo == null) {
+ Log.e(TAG, "Top activity info not found in task");
+ return;
+ }
+ PackageManager pm = mContext.getApplicationContext().getPackageManager();
+ final IconProvider provider = new IconProvider(mContext);
+ final Drawable appIconDrawable = provider.getIcon(activityInfo);
+ final Resources resources = mContext.getResources();
+ final BaseIconFactory factory = new BaseIconFactory(mContext,
+ resources.getDisplayMetrics().densityDpi,
+ resources.getDimensionPixelSize(R.dimen.desktop_mode_caption_icon_radius));
+ mAppIconBitmap = factory.createScaledBitmap(appIconDrawable, MODE_DEFAULT);
+ final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
+ mAppName = pm.getApplicationLabel(applicationInfo);
+ } finally {
+ Trace.endSection();
}
- PackageManager pm = mContext.getApplicationContext().getPackageManager();
- final IconProvider provider = new IconProvider(mContext);
- final Drawable appIconDrawable = provider.getIcon(activityInfo);
- final Resources resources = mContext.getResources();
- final BaseIconFactory factory = new BaseIconFactory(mContext,
- resources.getDisplayMetrics().densityDpi,
- resources.getDimensionPixelSize(R.dimen.desktop_mode_caption_icon_radius));
- mAppIconBitmap = factory.createScaledBitmap(appIconDrawable, MODE_DEFAULT);
- final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
- mAppName = pm.getApplicationLabel(applicationInfo);
}
private void closeDragResizeListener() {
@@ -464,7 +492,9 @@
* Create the resize veil for this task. Note the veil's visibility is View.GONE by default
* until a resize event calls showResizeVeil below.
*/
- void createResizeVeil() {
+ private void createResizeVeilIfNeeded() {
+ if (mResizeVeil != null) return;
+ loadAppInfoIfNeeded();
mResizeVeil = new ResizeVeil(mContext, mDisplayController, mAppIconBitmap, mTaskInfo,
mTaskSurface, mSurfaceControlTransactionSupplier);
}
@@ -473,6 +503,7 @@
* Show the resize veil.
*/
public void showResizeVeil(Rect taskBounds) {
+ createResizeVeilIfNeeded();
mResizeVeil.showVeil(mTaskSurface, taskBounds);
}
@@ -480,6 +511,7 @@
* Show the resize veil.
*/
public void showResizeVeil(SurfaceControl.Transaction tx, Rect taskBounds) {
+ createResizeVeilIfNeeded();
mResizeVeil.showVeil(tx, mTaskSurface, taskBounds, false /* fadeIn */);
}
@@ -599,6 +631,7 @@
* Create and display handle menu window.
*/
void createHandleMenu() {
+ loadAppInfoIfNeeded();
mHandleMenu = new HandleMenu.Builder(this)
.setAppIcon(mAppIconBitmap)
.setAppName(mAppName)
@@ -623,10 +656,10 @@
}
@Override
- void releaseViews() {
+ void releaseViews(WindowContainerTransaction wct) {
closeHandleMenu();
closeMaximizeMenu();
- super.releaseViews();
+ super.releaseViews(wct);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
index a3c3ece..93e2a21 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
@@ -29,6 +29,7 @@
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.os.Trace;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
@@ -135,6 +136,7 @@
// Display may not be available yet, skip this until then.
return;
}
+ Trace.beginSection("ResizeVeil#setupResizeVeil");
mVeilSurface = mSurfaceControlBuilderFactory
.create("Resize veil of Task=" + mTaskInfo.taskId)
.setContainerLayer()
@@ -179,6 +181,7 @@
mViewHost = mSurfaceControlViewHostFactory.create(mContext, mDisplay, wwm, "ResizeVeil");
mViewHost.setView(root, lp);
+ Trace.endSection();
}
private boolean obtainDisplayOrRegisterListener() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 36da1ac..de6c035 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -18,6 +18,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowInsets.Type.captionBar;
+import static android.view.WindowInsets.Type.mandatorySystemGestures;
import static android.view.WindowInsets.Type.statusBars;
import android.annotation.NonNull;
@@ -33,6 +35,7 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
+import android.os.Trace;
import android.view.Display;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -40,11 +43,11 @@
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.View;
-import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
import android.window.SurfaceSyncGroup;
import android.window.TaskConstants;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -53,7 +56,9 @@
import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams.OccludingCaptionElement;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.function.Supplier;
/**
@@ -130,8 +135,9 @@
TaskDragResizer mTaskDragResizer;
private boolean mIsCaptionVisible;
+ /** The most recent set of insets applied to this window decoration. */
+ private WindowDecorationInsets mWindowDecorationInsets;
private final Binder mOwner = new Binder();
- private final Rect mCaptionInsetsRect = new Rect();
private final float[] mTmpColor = new float[3];
WindowDecoration(
@@ -202,7 +208,7 @@
mLayoutResId = params.mLayoutResId;
if (!mTaskInfo.isVisible) {
- releaseViews();
+ releaseViews(wct);
finishT.hide(mTaskSurface);
return;
}
@@ -225,7 +231,7 @@
|| mDisplay.getDisplayId() != mTaskInfo.displayId
|| oldLayoutResId != mLayoutResId
|| oldNightMode != newNightMode) {
- releaseViews();
+ releaseViews(wct);
if (!obtainDisplayOrRegisterListener()) {
outResult.mRootView = null;
@@ -299,8 +305,8 @@
// Caption inset is the full width of the task with the |captionHeight| and
// positioned at the top of the task bounds, also in absolute coordinates.
// So just reuse the task bounds and adjust the bottom coordinate.
- mCaptionInsetsRect.set(taskBounds);
- mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + outResult.mCaptionHeight;
+ final Rect captionInsetsRect = new Rect(taskBounds);
+ captionInsetsRect.bottom = captionInsetsRect.top + outResult.mCaptionHeight;
// Caption bounding rectangles: these are optional, and are used to present finer
// insets than traditional |Insets| to apps about where their content is occluded.
@@ -311,8 +317,8 @@
boundingRects = null;
} else {
// The customizable region can at most be equal to the caption bar.
- if (params.mAllowCaptionInputFallthrough) {
- outResult.mCustomizableCaptionRegion.set(mCaptionInsetsRect);
+ if (params.hasInputFeatureSpy()) {
+ outResult.mCustomizableCaptionRegion.set(captionInsetsRect);
}
boundingRects = new Rect[numOfElements];
for (int i = 0; i < numOfElements; i++) {
@@ -321,27 +327,28 @@
final int elementWidthPx =
resources.getDimensionPixelSize(element.mWidthResId);
boundingRects[i] =
- calculateBoundingRect(element, elementWidthPx, mCaptionInsetsRect);
+ calculateBoundingRect(element, elementWidthPx, captionInsetsRect);
// Subtract the regions used by the caption elements, the rest is
// customizable.
- if (params.mAllowCaptionInputFallthrough) {
+ if (params.hasInputFeatureSpy()) {
outResult.mCustomizableCaptionRegion.op(boundingRects[i],
Region.Op.DIFFERENCE);
}
}
}
- // Add this caption as an inset source.
- wct.addInsetsSource(mTaskInfo.token,
- mOwner, 0 /* index */, WindowInsets.Type.captionBar(), mCaptionInsetsRect,
- boundingRects);
- wct.addInsetsSource(mTaskInfo.token,
- mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures(),
- mCaptionInsetsRect, null /* boundingRects */);
+
+ final WindowDecorationInsets newInsets = new WindowDecorationInsets(
+ mTaskInfo.token, mOwner, captionInsetsRect, boundingRects);
+ if (!newInsets.equals(mWindowDecorationInsets)) {
+ // Add or update this caption as an insets source.
+ mWindowDecorationInsets = newInsets;
+ mWindowDecorationInsets.addOrUpdate(wct);
+ }
} else {
- wct.removeInsetsSource(mTaskInfo.token, mOwner, 0 /* index */,
- WindowInsets.Type.captionBar());
- wct.removeInsetsSource(mTaskInfo.token, mOwner, 0 /* index */,
- WindowInsets.Type.mandatorySystemGestures());
+ if (mWindowDecorationInsets != null) {
+ mWindowDecorationInsets.remove(wct);
+ mWindowDecorationInsets = null;
+ }
}
// Task surface itself
@@ -378,6 +385,7 @@
startT.unsetColor(mTaskSurface);
}
+ Trace.beginSection("CaptionViewHostLayout");
if (mCaptionWindowManager == null) {
// Put caption under a container surface because ViewRootImpl sets the destination frame
// of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
@@ -394,24 +402,25 @@
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
lp.setTrustedOverlay();
- if (params.mAllowCaptionInputFallthrough) {
- lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY;
- } else {
- lp.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_SPY;
- }
+ lp.inputFeatures = params.mInputFeatures;
if (mViewHost == null) {
+ Trace.beginSection("CaptionViewHostLayout-new");
mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
mCaptionWindowManager);
if (params.mApplyStartTransactionOnDraw) {
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
}
mViewHost.setView(outResult.mRootView, lp);
+ Trace.endSection();
} else {
+ Trace.beginSection("CaptionViewHostLayout-relayout");
if (params.mApplyStartTransactionOnDraw) {
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
}
mViewHost.relayout(lp);
+ Trace.endSection();
}
+ Trace.endSection(); // CaptionViewHostLayout
}
private Rect calculateBoundingRect(@NonNull OccludingCaptionElement element,
@@ -482,7 +491,7 @@
return true;
}
- void releaseViews() {
+ void releaseViews(WindowContainerTransaction wct) {
if (mViewHost != null) {
mViewHost.release();
mViewHost = null;
@@ -508,19 +517,21 @@
t.apply();
}
- final WindowContainerTransaction wct = mWindowContainerTransactionSupplier.get();
- wct.removeInsetsSource(mTaskInfo.token,
- mOwner, 0 /* index */, WindowInsets.Type.captionBar());
- wct.removeInsetsSource(mTaskInfo.token,
- mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures());
- mTaskOrganizer.applyTransaction(wct);
+ if (mWindowDecorationInsets != null) {
+ mWindowDecorationInsets.remove(wct);
+ mWindowDecorationInsets = null;
+ }
}
@Override
public void close() {
+ Trace.beginSection("WindowDecoration#close");
mDisplayController.removeDisplayWindowListener(mOnDisplaysChangedListener);
- releaseViews();
+ final WindowContainerTransaction wct = mWindowContainerTransactionSupplier.get();
+ releaseViews(wct);
+ mTaskOrganizer.applyTransaction(wct);
mTaskSurface.release();
+ Trace.endSection();
}
static int loadDimensionPixelSize(Resources resources, int resourceId) {
@@ -595,8 +606,12 @@
final int captionHeight = loadDimensionPixelSize(mContext.getResources(), captionHeightId);
final Rect captionInsets = new Rect(0, 0, 0, captionHeight);
- wct.addInsetsSource(mTaskInfo.token, mOwner, 0 /* index */, WindowInsets.Type.captionBar(),
- captionInsets, null /* boundingRects */);
+ final WindowDecorationInsets newInsets = new WindowDecorationInsets(mTaskInfo.token,
+ mOwner, captionInsets, null /* boundingRets */);
+ if (!newInsets.equals(mWindowDecorationInsets)) {
+ mWindowDecorationInsets = newInsets;
+ mWindowDecorationInsets.addOrUpdate(wct);
+ }
}
static class RelayoutParams {
@@ -605,7 +620,7 @@
int mCaptionHeightId;
int mCaptionWidthId;
final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>();
- boolean mAllowCaptionInputFallthrough;
+ int mInputFeatures;
int mShadowRadiusId;
int mCornerRadius;
@@ -620,7 +635,7 @@
mCaptionHeightId = Resources.ID_NULL;
mCaptionWidthId = Resources.ID_NULL;
mOccludingCaptionElements.clear();
- mAllowCaptionInputFallthrough = false;
+ mInputFeatures = 0;
mShadowRadiusId = Resources.ID_NULL;
mCornerRadius = 0;
@@ -630,6 +645,10 @@
mWindowDecorConfig = null;
}
+ boolean hasInputFeatureSpy() {
+ return (mInputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_SPY) != 0;
+ }
+
/**
* Describes elements within the caption bar that could occlude app content, and should be
* sent as bounding rectangles to the insets system.
@@ -674,6 +693,47 @@
}
}
+ private static class WindowDecorationInsets {
+ private static final int INDEX = 0;
+ private final WindowContainerToken mToken;
+ private final Binder mOwner;
+ private final Rect mFrame;
+ private final Rect[] mBoundingRects;
+
+ private WindowDecorationInsets(WindowContainerToken token, Binder owner, Rect frame,
+ Rect[] boundingRects) {
+ mToken = token;
+ mOwner = owner;
+ mFrame = frame;
+ mBoundingRects = boundingRects;
+ }
+
+ void addOrUpdate(WindowContainerTransaction wct) {
+ wct.addInsetsSource(mToken, mOwner, INDEX, captionBar(), mFrame, mBoundingRects);
+ wct.addInsetsSource(mToken, mOwner, INDEX, mandatorySystemGestures(), mFrame,
+ mBoundingRects);
+ }
+
+ void remove(WindowContainerTransaction wct) {
+ wct.removeInsetsSource(mToken, mOwner, INDEX, captionBar());
+ wct.removeInsetsSource(mToken, mOwner, INDEX, mandatorySystemGestures());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof WindowDecoration.WindowDecorationInsets that)) return false;
+ return Objects.equals(mToken, that.mToken) && Objects.equals(mOwner,
+ that.mOwner) && Objects.equals(mFrame, that.mFrame)
+ && Objects.deepEquals(mBoundingRects, that.mBoundingRects);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mToken, mOwner, mFrame, Arrays.hashCode(mBoundingRects));
+ }
+ }
+
/**
* Subclass for additional windows associated with this WindowDecoration
*/
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index d718e15..0f24bb5 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -12,3 +12,4 @@
nmusgrave@google.com
pbdr@google.com
tkachenkoi@google.com
+mpodolian@google.com
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
index 5b2ffec..4dd14f4 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
index 9f7d9fc..5c86a38 100644
--- a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
index 882b200..aa70c09 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
index f5a8655..bf040d2 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
@@ -20,6 +20,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
index 51a55e35..c7c804f 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt
index 75dfeba..17cace0 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt
@@ -23,6 +23,7 @@
import android.tools.flicker.assertors.assertions.AppWindowHasDesktopModeInitialBoundsAtTheEnd
import android.tools.flicker.assertors.assertions.AppWindowOnTopAtEnd
import android.tools.flicker.assertors.assertions.AppWindowOnTopAtStart
+import android.tools.flicker.assertors.assertions.AppWindowRemainInsideDisplayBounds
import android.tools.flicker.assertors.assertions.LauncherWindowMovesToTop
import android.tools.flicker.config.AssertionTemplates
import android.tools.flicker.config.FlickerConfigEntry
@@ -114,5 +115,30 @@
)
.associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
)
+
+ val CORNER_RESIZE =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("CORNER_RESIZE"),
+ extractor =
+ ShellTransitionScenarioExtractor(
+ transitionMatcher =
+ object : ITransitionMatcher {
+ override fun findAll(
+ transitions: Collection<Transition>
+ ): Collection<Transition> {
+ return transitions.filter {
+ it.type == TransitionType.CHANGE
+ }
+ }
+ }
+ ),
+ assertions =
+ AssertionTemplates.COMMON_ASSERTIONS +
+ listOf(
+ AppLayerIsVisibleAlways(Components.DESKTOP_MODE_APP),
+ AppWindowOnTopAtEnd(Components.DESKTOP_MODE_APP),
+ AppWindowRemainInsideDisplayBounds(Components.DESKTOP_MODE_APP),
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ )
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/ResizeAppWithCornerResizeLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/ResizeAppWithCornerResizeLandscape.kt
new file mode 100644
index 0000000..8d1a530
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/ResizeAppWithCornerResizeLandscape.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.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.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppWithCornerResizeLandscape : ResizeAppWithCornerResize(Rotation.ROTATION_90) {
+ @ExpectedScenarios(["CORNER_RESIZE"])
+ @Test
+ override fun resizeAppWithCornerResize() = super.resizeAppWithCornerResize()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/ResizeAppWithCornerResizePortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/ResizeAppWithCornerResizePortrait.kt
new file mode 100644
index 0000000..2d81c8c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/ResizeAppWithCornerResizePortrait.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.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.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppWithCornerResizePortrait : ResizeAppWithCornerResize(Rotation.ROTATION_0) {
+ @ExpectedScenarios(["CORNER_RESIZE"])
+ @Test
+ override fun resizeAppWithCornerResize() = super.resizeAppWithCornerResize()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/ResizeAppWithCornerResize.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/ResizeAppWithCornerResize.kt
new file mode 100644
index 0000000..289ca9f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/ResizeAppWithCornerResize.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.scenarios
+
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+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.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.flicker.service.common.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+
+@Ignore("Base Test Class")
+abstract class ResizeAppWithCornerResize
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0) {
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val tapl = LauncherInstrumentation()
+ private val wmHelper = WindowManagerStateHelper(instrumentation)
+ private val device = UiDevice.getInstance(instrumentation)
+ private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+
+ @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode())
+ tapl.setEnableRotation(true)
+ tapl.setExpectedRotation(rotation.value)
+ testApp.enterDesktopWithDrag(wmHelper, device)
+ }
+
+ @Test
+ open fun resizeAppWithCornerResize() {
+ testApp.cornerResize(wmHelper, device, DesktopModeAppHelper.Corners.RIGHT_TOP, 50, -50)
+ }
+
+ @After
+ fun teardown() {
+ testApp.exit(wmHelper)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
index 05f937a..214bdfa 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayoutTest.java
index 964711e..0431285 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayoutTest.java
@@ -69,7 +69,8 @@
// to animate child views out before actually removing them).
mTestableController.setAnimatedProperties(Sets.newHashSet(
DynamicAnimation.TRANSLATION_X,
- DynamicAnimation.TRANSLATION_Y));
+ DynamicAnimation.TRANSLATION_Y,
+ DynamicAnimation.TRANSLATION_Z));
mTestableController.setChainedProperties(Sets.newHashSet(DynamicAnimation.TRANSLATION_X));
mTestableController.setOffsetForProperty(
DynamicAnimation.TRANSLATION_X, TEST_TRANSLATION_X_OFFSET);
@@ -282,10 +283,13 @@
addOneMoreThanBubbleLimitBubbles();
assertFalse(mLayout.arePropertiesAnimating(
- DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y));
+ DynamicAnimation.TRANSLATION_X,
+ DynamicAnimation.TRANSLATION_Y,
+ DynamicAnimation.TRANSLATION_Z));
mTestableController.animationForChildAtIndex(0)
.translationX(100f)
+ .translationZ(100f)
.start();
// Wait for the animations to get underway.
@@ -293,11 +297,13 @@
assertTrue(mLayout.arePropertiesAnimating(DynamicAnimation.TRANSLATION_X));
assertFalse(mLayout.arePropertiesAnimating(DynamicAnimation.TRANSLATION_Y));
+ assertTrue(mLayout.arePropertiesAnimating(DynamicAnimation.TRANSLATION_Z));
- waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X);
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Z);
assertFalse(mLayout.arePropertiesAnimating(
- DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y));
+ DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y,
+ DynamicAnimation.TRANSLATION_Z));
}
@Test
@@ -307,7 +313,7 @@
addOneMoreThanBubbleLimitBubbles();
mTestableController.animationForChildAtIndex(0)
- .position(1000, 1000)
+ .position(1000, 1000, 1000)
.start();
mLayout.cancelAllAnimations();
@@ -315,6 +321,7 @@
// Animations should be somewhere before their end point.
assertTrue(mViews.get(0).getTranslationX() < 1000);
assertTrue(mViews.get(0).getTranslationY() < 1000);
+ assertTrue(mViews.get(0).getZ() < 10000);
}
/** Standard test of chained translation animations. */
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/PipTransitionStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/PipTransitionStateTest.java
new file mode 100644
index 0000000..bd8ac37
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/PipTransitionStateTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip2;
+
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.testing.AndroidTestingRunner;
+
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.pip.PhoneSizeSpecSource;
+import com.android.wm.shell.pip2.phone.PipTransitionState;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Unit test against {@link PhoneSizeSpecSource}.
+ *
+ * This test mocks the PiP2 flag to be true.
+ */
+@RunWith(AndroidTestingRunner.class)
+public class PipTransitionStateTest extends ShellTestCase {
+ private static final String EXTRA_ENTRY_KEY = "extra_entry_key";
+ private PipTransitionState mPipTransitionState;
+ private PipTransitionState.PipTransitionStateChangedListener mStateChangedListener;
+ private Parcelable mEmptyParcelable;
+
+ @Before
+ public void setUp() {
+ mPipTransitionState = new PipTransitionState();
+ mPipTransitionState.setState(PipTransitionState.UNDEFINED);
+ mEmptyParcelable = new Bundle();
+ }
+
+ @Test
+ public void testEnteredState_withoutExtra() {
+ mStateChangedListener = (oldState, newState, extra) -> {
+ Assert.assertEquals(PipTransitionState.ENTERED_PIP, newState);
+ Assert.assertNull(extra);
+ };
+ mPipTransitionState.addPipTransitionStateChangedListener(mStateChangedListener);
+ mPipTransitionState.setState(PipTransitionState.ENTERED_PIP);
+ mPipTransitionState.removePipTransitionStateChangedListener(mStateChangedListener);
+ }
+
+ @Test
+ public void testEnteredState_withExtra() {
+ mStateChangedListener = (oldState, newState, extra) -> {
+ Assert.assertEquals(PipTransitionState.ENTERED_PIP, newState);
+ Assert.assertNotNull(extra);
+ Assert.assertEquals(mEmptyParcelable, extra.getParcelable(EXTRA_ENTRY_KEY));
+ };
+ Bundle extra = new Bundle();
+ extra.putParcelable(EXTRA_ENTRY_KEY, mEmptyParcelable);
+
+ mPipTransitionState.addPipTransitionStateChangedListener(mStateChangedListener);
+ mPipTransitionState.setState(PipTransitionState.ENTERED_PIP, extra);
+ mPipTransitionState.removePipTransitionStateChangedListener(mStateChangedListener);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testEnteringState_withoutExtra() {
+ mPipTransitionState.setState(PipTransitionState.ENTERING_PIP);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSwipingToPipState_withoutExtra() {
+ mPipTransitionState.setState(PipTransitionState.SWIPING_TO_PIP);
+ }
+
+ @Test
+ public void testCustomState_withExtra_thenEntered_withoutExtra() {
+ final int customState = mPipTransitionState.getCustomState();
+ mStateChangedListener = (oldState, newState, extra) -> {
+ if (newState == customState) {
+ Assert.assertNotNull(extra);
+ Assert.assertEquals(mEmptyParcelable, extra.getParcelable(EXTRA_ENTRY_KEY));
+ return;
+ } else if (newState == PipTransitionState.ENTERED_PIP) {
+ Assert.assertNull(extra);
+ return;
+ }
+ Assert.fail("Neither custom not ENTERED_PIP state is received.");
+ };
+ Bundle extra = new Bundle();
+ extra.putParcelable(EXTRA_ENTRY_KEY, mEmptyParcelable);
+
+ mPipTransitionState.addPipTransitionStateChangedListener(mStateChangedListener);
+ mPipTransitionState.setState(customState, extra);
+ mPipTransitionState.setState(PipTransitionState.ENTERED_PIP);
+ mPipTransitionState.removePipTransitionStateChangedListener(mStateChangedListener);
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index d819261..d7c3835 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -40,10 +40,12 @@
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 static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.PendingIntent;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
@@ -51,6 +53,7 @@
import android.os.Looper;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
+import android.window.RemoteTransition;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -74,6 +77,7 @@
import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.DefaultMixedHandler;
import com.android.wm.shell.transition.HomeTransitionObserver;
import com.android.wm.shell.transition.Transitions;
@@ -111,6 +115,8 @@
private TransactionPool mTransactionPool;
@Mock
private LaunchAdjacentController mLaunchAdjacentController;
+ @Mock
+ private DefaultMixedHandler mDefaultMixedHandler;
private final Rect mBounds1 = new Rect(10, 20, 30, 40);
private final Rect mBounds2 = new Rect(5, 10, 15, 20);
@@ -370,6 +376,96 @@
}
}
+ @Test
+ public void testSplitIntentAndTaskWithPippedApp_launchFullscreen() {
+ int taskId = 9;
+ SplitScreenTransitions splitScreenTransitions =
+ spy(mStageCoordinator.getSplitTransitions());
+ mStageCoordinator.setSplitTransitions(splitScreenTransitions);
+ mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
+ PendingIntent pendingIntent = mock(PendingIntent.class);
+ RemoteTransition remoteTransition = mock(RemoteTransition.class);
+ when(remoteTransition.getDebugName()).thenReturn("");
+ // Test launching second task full screen
+ when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
+ mStageCoordinator.startIntentAndTask(
+ pendingIntent,
+ null /*fillInIntent*/,
+ null /*option1*/,
+ taskId,
+ null /*option2*/,
+ 0 /*splitPosition*/,
+ 1 /*snapPosition*/,
+ remoteTransition /*remoteTransition*/,
+ null /*instanceId*/);
+ verify(splitScreenTransitions, times(1))
+ .startFullscreenTransition(any(), any());
+
+ // Test launching first intent fullscreen
+ when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false);
+ when(mDefaultMixedHandler.isTaskInPip(taskId, mTaskOrganizer)).thenReturn(true);
+ mStageCoordinator.startIntentAndTask(
+ pendingIntent,
+ null /*fillInIntent*/,
+ null /*option1*/,
+ taskId,
+ null /*option2*/,
+ 0 /*splitPosition*/,
+ 1 /*snapPosition*/,
+ remoteTransition /*remoteTransition*/,
+ null /*instanceId*/);
+ verify(splitScreenTransitions, times(2))
+ .startFullscreenTransition(any(), any());
+ }
+
+ @Test
+ public void testSplitIntentsWithPippedApp_launchFullscreen() {
+ SplitScreenTransitions splitScreenTransitions =
+ spy(mStageCoordinator.getSplitTransitions());
+ mStageCoordinator.setSplitTransitions(splitScreenTransitions);
+ mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
+ PendingIntent pendingIntent = mock(PendingIntent.class);
+ PendingIntent pendingIntent2 = mock(PendingIntent.class);
+ RemoteTransition remoteTransition = mock(RemoteTransition.class);
+ when(remoteTransition.getDebugName()).thenReturn("");
+ // Test launching second task full screen
+ when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
+ mStageCoordinator.startIntents(
+ pendingIntent,
+ null /*fillInIntent*/,
+ null /*shortcutInfo1*/,
+ new Bundle(),
+ pendingIntent2,
+ null /*fillInIntent2*/,
+ null /*shortcutInfo1*/,
+ new Bundle(),
+ 0 /*splitPosition*/,
+ 1 /*snapPosition*/,
+ remoteTransition /*remoteTransition*/,
+ null /*instanceId*/);
+ verify(splitScreenTransitions, times(1))
+ .startFullscreenTransition(any(), any());
+
+ // Test launching first intent fullscreen
+ when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false);
+ when(mDefaultMixedHandler.isIntentInPip(pendingIntent2)).thenReturn(true);
+ mStageCoordinator.startIntents(
+ pendingIntent,
+ null /*fillInIntent*/,
+ null /*shortcutInfo1*/,
+ new Bundle(),
+ pendingIntent2,
+ null /*fillInIntent2*/,
+ null /*shortcutInfo1*/,
+ new Bundle(),
+ 0 /*splitPosition*/,
+ 1 /*snapPosition*/,
+ remoteTransition /*remoteTransition*/,
+ null /*instanceId*/);
+ verify(splitScreenTransitions, times(2))
+ .startFullscreenTransition(any(), any());
+ }
+
private Transitions createTestTransitions() {
ShellInit shellInit = new ShellInit(mMainExecutor);
final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index f9b5882..608f74b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -18,6 +18,7 @@
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.view.WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND;
import static com.google.common.truth.Truth.assertThat;
@@ -44,6 +45,7 @@
import android.view.Display;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
+import android.view.WindowManager;
import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
@@ -187,7 +189,7 @@
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false);
- assertThat(relayoutParams.mAllowCaptionInputFallthrough).isTrue();
+ assertThat(relayoutParams.hasInputFeatureSpy()).isTrue();
}
@Test
@@ -204,7 +206,7 @@
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false);
- assertThat(relayoutParams.mAllowCaptionInputFallthrough).isFalse();
+ assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
}
@Test
@@ -220,7 +222,55 @@
/* applyStartTransactionOnDraw= */ true,
/* shouldSetTaskPositionAndCrop */ false);
- assertThat(relayoutParams.mAllowCaptionInputFallthrough).isFalse();
+ assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
+ }
+
+ @Test
+ public void updateRelayoutParams_freeform_inputChannelNeeded() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false);
+
+ assertThat(hasNoInputChannelFeature(relayoutParams)).isFalse();
+ }
+
+ @Test
+ public void updateRelayoutParams_fullscreen_inputChannelNotNeeded() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false);
+
+ assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
+ }
+
+ @Test
+ public void updateRelayoutParams_multiwindow_inputChannelNotNeeded() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false);
+
+ assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
}
private void fillRoundedCornersResources(int fillValue) {
@@ -268,4 +318,9 @@
return taskInfo;
}
+
+ private static boolean hasNoInputChannelFeature(RelayoutParams params) {
+ return (params.mInputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL)
+ != 0;
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index a9f4492..48ac1e5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -197,7 +197,7 @@
rectAfterEnd.top += 20
rectAfterEnd.bottom += 20
- verify(mockDesktopWindowDecoration, never()).createResizeVeil()
+ verify(mockDesktopWindowDecoration, never()).showResizeVeil(any())
verify(mockDesktopWindowDecoration, never()).hideResizeVeil()
verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 5464937..4eb44d7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -42,6 +42,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.quality.Strictness.LENIENT;
@@ -64,6 +65,7 @@
import android.view.WindowInsets;
import android.view.WindowManager.LayoutParams;
import android.window.SurfaceSyncGroup;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
@@ -610,24 +612,25 @@
mockitoSession.finishMocking();
}
-
@Test
- public void testInsetsRemovedWhenCaptionIsHidden() {
+ public void testRelayout_captionHidden_insetsRemoved() {
final Display defaultDisplay = mock(Display.class);
doReturn(defaultDisplay).when(mMockDisplayController)
.getDisplay(Display.DEFAULT_DISPLAY);
- mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(false);
-
- final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
- new ActivityManager.TaskDescription.Builder();
final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
.setDisplayId(Display.DEFAULT_DISPLAY)
- .setTaskDescriptionBuilder(taskDescriptionBuilder)
.setVisible(true)
+ .setBounds(new Rect(0, 0, 1000, 1000))
.build();
final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+ // Run it once so that insets are added.
+ mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(true);
+ windowDecor.relayout(taskInfo);
+
+ // Run it again so that insets are removed.
+ mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(false);
windowDecor.relayout(taskInfo);
verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(),
@@ -637,6 +640,141 @@
}
@Test
+ public void testRelayout_captionHidden_neverWasVisible_insetsNotRemoved() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true)
+ .setBounds(new Rect(0, 0, 1000, 1000))
+ .build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+ // Hidden from the beginning, so no insets were ever added.
+ mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(false);
+ windowDecor.relayout(taskInfo);
+
+ // Never added.
+ verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(captionBar()), any(), any());
+ verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ // No need to remove them if they were never added.
+ verify(mMockWindowContainerTransaction, never()).removeInsetsSource(eq(taskInfo.token),
+ any(), eq(0) /* index */, eq(captionBar()));
+ verify(mMockWindowContainerTransaction, never()).removeInsetsSource(eq(taskInfo.token),
+ any(), eq(0) /* index */, eq(mandatorySystemGestures()));
+ }
+
+ @Test
+ public void testClose_withExistingInsets_insetsRemoved() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true)
+ .setBounds(new Rect(0, 0, 1000, 1000))
+ .build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+ // Relayout will add insets.
+ mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(true);
+ windowDecor.relayout(taskInfo);
+ verify(mMockWindowContainerTransaction).addInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(captionBar()), any(), any());
+ verify(mMockWindowContainerTransaction).addInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+
+ windowDecor.close();
+
+ // Insets should be removed.
+ verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(captionBar()));
+ verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(),
+ eq(0) /* index */, eq(mandatorySystemGestures()));
+ }
+
+ @Test
+ public void testClose_withoutExistingInsets_insetsNotRemoved() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true)
+ .setBounds(new Rect(0, 0, 1000, 1000))
+ .build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+ windowDecor.close();
+
+ // No need to remove insets.
+ verify(mMockWindowContainerTransaction, never()).removeInsetsSource(eq(taskInfo.token),
+ any(), eq(0) /* index */, eq(captionBar()));
+ verify(mMockWindowContainerTransaction, never()).removeInsetsSource(eq(taskInfo.token),
+ any(), eq(0) /* index */, eq(mandatorySystemGestures()));
+ }
+
+ @Test
+ public void testRelayout_captionFrameChanged_insetsReapplied() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+ mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(true);
+ final WindowContainerToken token = TestRunningTaskInfoBuilder.createMockWCToken();
+ final TestRunningTaskInfoBuilder builder = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true);
+
+ // Relayout twice with different bounds.
+ final ActivityManager.RunningTaskInfo firstTaskInfo =
+ builder.setToken(token).setBounds(new Rect(0, 0, 1000, 1000)).build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(firstTaskInfo);
+ windowDecor.relayout(firstTaskInfo);
+ final ActivityManager.RunningTaskInfo secondTaskInfo =
+ builder.setToken(token).setBounds(new Rect(50, 50, 1000, 1000)).build();
+ windowDecor.relayout(secondTaskInfo);
+
+ // Insets should be applied twice.
+ verify(mMockWindowContainerTransaction, times(2)).addInsetsSource(eq(token), any(),
+ eq(0) /* index */, eq(captionBar()), any(), any());
+ verify(mMockWindowContainerTransaction, times(2)).addInsetsSource(eq(token), any(),
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ }
+
+ @Test
+ public void testRelayout_captionFrameUnchanged_insetsNotApplied() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+ mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(true);
+ final WindowContainerToken token = TestRunningTaskInfoBuilder.createMockWCToken();
+ final TestRunningTaskInfoBuilder builder = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true);
+
+ // Relayout twice with the same bounds.
+ final ActivityManager.RunningTaskInfo firstTaskInfo =
+ builder.setToken(token).setBounds(new Rect(0, 0, 1000, 1000)).build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(firstTaskInfo);
+ windowDecor.relayout(firstTaskInfo);
+ final ActivityManager.RunningTaskInfo secondTaskInfo =
+ builder.setToken(token).setBounds(new Rect(0, 0, 1000, 1000)).build();
+ windowDecor.relayout(secondTaskInfo);
+
+ // Insets should only need to be applied once.
+ verify(mMockWindowContainerTransaction, times(1)).addInsetsSource(eq(token), any(),
+ eq(0) /* index */, eq(captionBar()), any(), any());
+ verify(mMockWindowContainerTransaction, times(1)).addInsetsSource(eq(token), any(),
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ }
+
+ @Test
public void testTaskPositionAndCropNotSetWhenFalse() {
final Display defaultDisplay = mock(Display.class);
doReturn(defaultDisplay).when(mMockDisplayController)
@@ -763,6 +901,7 @@
void relayout(ActivityManager.RunningTaskInfo taskInfo,
boolean applyStartTransactionOnDraw) {
+ mRelayoutParams.mRunningTaskInfo = taskInfo;
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
diff --git a/libs/hwui/hwui/DrawTextFunctor.h b/libs/hwui/hwui/DrawTextFunctor.h
index 1fcb692..cfca480 100644
--- a/libs/hwui/hwui/DrawTextFunctor.h
+++ b/libs/hwui/hwui/DrawTextFunctor.h
@@ -34,7 +34,9 @@
namespace android {
-inline constexpr int kHighContrastTextBorderWidth = 4;
+// These should match the constants in framework/base/core/java/android/text/Layout.java
+inline constexpr float kHighContrastTextBorderWidth = 4.0f;
+inline constexpr float kHighContrastTextBorderWidthFactor = 0.2f;
static inline void drawStroke(SkScalar left, SkScalar right, SkScalar top, SkScalar thickness,
const Paint& paint, Canvas* canvas) {
@@ -48,7 +50,16 @@
paint->setShader(nullptr);
paint->setColorFilter(nullptr);
paint->setLooper(nullptr);
- paint->setStrokeWidth(kHighContrastTextBorderWidth + 0.04 * paint->getSkFont().getSize());
+
+ if (flags::high_contrast_text_small_text_rect()) {
+ paint->setStrokeWidth(
+ std::max(kHighContrastTextBorderWidth,
+ kHighContrastTextBorderWidthFactor * paint->getSkFont().getSize()));
+ } else {
+ auto borderWidthFactor = 0.04f;
+ paint->setStrokeWidth(kHighContrastTextBorderWidth +
+ borderWidthFactor * paint->getSkFont().getSize());
+ }
paint->setStrokeJoin(SkPaint::kRound_Join);
paint->setLooper(nullptr);
}
@@ -106,36 +117,7 @@
Paint outlinePaint(paint);
simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
- if (flags::high_contrast_text_small_text_rect()) {
- const SkFont& font = paint.getSkFont();
- auto padding = kHighContrastTextBorderWidth + 0.1f * font.getSize();
-
- // Draw the background only behind each glyph's bounds. We do this instead of using
- // the bounds of the entire layout, because the layout includes alignment whitespace
- // etc which can obscure other text from separate passes (e.g. emojis).
- // Merge all the glyph bounds into one rect for this line, since drawing a rect for
- // each glyph is expensive.
- SkRect glyphBounds;
- SkRect bgBounds;
- for (size_t i = start; i < end; i++) {
- auto glyph = layout.getGlyphId(i);
-
- font.getBounds(reinterpret_cast<const SkGlyphID*>(&glyph), 1, &glyphBounds,
- &paint);
- glyphBounds.offset(layout.getX(i), layout.getY(i));
-
- bgBounds.join(glyphBounds);
- }
-
- if (!bgBounds.isEmpty()) {
- bgBounds.offset(x, y);
- bgBounds.outset(padding, padding);
- canvas->drawRect(bgBounds.fLeft, bgBounds.fTop, bgBounds.fRight,
- bgBounds.fBottom, outlinePaint);
- }
- } else {
- canvas->drawGlyphs(glyphFunc, glyphCount, outlinePaint, x, y, totalAdvance);
- }
+ canvas->drawGlyphs(glyphFunc, glyphCount, outlinePaint, x, y, totalAdvance);
// inner
gDrawTextBlobMode = DrawTextBlobMode::HctInner;
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index a8e8547..0f29613 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -322,11 +322,16 @@
return false;
}
- err = native_window_set_buffer_count(window, windowInfo.bufferCount);
- if (err != 0) {
- ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%zu) failed: %s (%d)",
- windowInfo.bufferCount, strerror(-err), err);
- return false;
+ // If bufferCount == 1 then we're in shared buffer mode and we cannot actually call
+ // set_buffer_count, it'll just fail.
+ if (windowInfo.bufferCount > 1) {
+ err = native_window_set_buffer_count(window, windowInfo.bufferCount);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%zu) failed: %s "
+ "(%d)",
+ windowInfo.bufferCount, strerror(-err), err);
+ return false;
+ }
}
err = native_window_set_usage(window, windowInfo.windowUsageFlags);
diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig
index 4981029..5f84862 100644
--- a/location/java/android/location/flags/location.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -80,10 +80,13 @@
}
flag {
- name: "subscriptions_listener_thread"
+ name: "subscriptions_changed_listener_thread"
namespace: "location"
- description: "Flag for running onSubscriptionsChangeListener on FgThread"
+ description: "Flag for running onSubscriptionsChangedListener on FgThread"
bug: "332451908"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index ffd6e16..554fe5e 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -1005,7 +1005,6 @@
* RoutingController#wasTransferInitiatedBySelf()}.
* @hide
*/
- @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
public void transfer(
@NonNull RoutingController controller,
@NonNull MediaRoute2Info route,
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 8609c4d..8874ff5 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -18,7 +18,10 @@
cc_library_shared {
name: "libmedia_jni",
- defaults: ["libcodec2-internal-defaults"],
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ "libcodec2-internal-defaults",
+ ],
min_sdk_version: "",
srcs: [
diff --git a/nfc/jarjar-rules.txt b/nfc/jarjar-rules.txt
index 99ae144..63a6a58 100644
--- a/nfc/jarjar-rules.txt
+++ b/nfc/jarjar-rules.txt
@@ -27,9 +27,8 @@
rule android.os.PersistableBundleProto* com.android.nfc.x.@0
# Used by framework-nfc for reading trunk stable flags
-rule android.nfc.FakeFeatureFlagsImpl* com.android.nfc.x.@0
-rule android.nfc.FeatureFlags* com.android.nfc.x.@0
-rule android.nfc.Flags* com.android.nfc.x.@0
+rule android.nfc.*Flags* com.android.nfc.x.@0
+rule android.nfc.Flags com.android.nfc.x.@0
rule android.permission.flags.** com.android.nfc.x.@0
# Used by framework-nfc for misc utilities
diff --git a/nfc/java/android/nfc/NfcActivityManager.java b/nfc/java/android/nfc/NfcActivityManager.java
index f03fc0a..0e40db6 100644
--- a/nfc/java/android/nfc/NfcActivityManager.java
+++ b/nfc/java/android/nfc/NfcActivityManager.java
@@ -195,16 +195,25 @@
Bundle extras) {
boolean isResumed;
Binder token;
+ int pollTech, listenTech;
synchronized (NfcActivityManager.this) {
NfcActivityState state = getActivityState(activity);
state.readerCallback = callback;
state.readerModeFlags = flags;
state.readerModeExtras = extras;
+ pollTech = state.mPollTech;
+ listenTech = state.mListenTech;
token = state.token;
isResumed = state.resumed;
}
if (isResumed) {
- setReaderMode(token, flags, extras);
+ if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
+ || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
+ throw new IllegalStateException(
+ "Cannot be used when alternative DiscoveryTechnology is set");
+ } else {
+ setReaderMode(token, flags, extras);
+ }
}
}
@@ -385,15 +394,12 @@
boolean readerModeFlagsSet;
synchronized (NfcActivityManager.this) {
NfcActivityState state = getActivityState(activity);
- readerModeFlagsSet = state.readerModeFlags != 0;
state.mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
state.mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
token = state.token;
isResumed = state.resumed;
}
- if (readerModeFlagsSet) {
- disableReaderMode(activity);
- } else if (isResumed) {
+ if (isResumed) {
changeDiscoveryTech(token, NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
}
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index 25fecac..e43d104 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -1880,10 +1880,7 @@
throw new UnsupportedOperationException();
}
}
- mNfcActivityManager.enableReaderMode(activity, null, pollTechnology, null);
- return;
- }
- if (pollTechnology == FLAG_READER_DISABLE) {
+ } else if (pollTechnology == FLAG_READER_DISABLE) {
synchronized (sLock) {
if (!sHasCeFeature) {
throw new UnsupportedOperationException();
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index ce8feb5..6aafb55 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -76,7 +76,7 @@
<string name="permission_app_streaming_summary" msgid="606923325679670624">"שידור אפליקציות מהטלפון"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
<string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"העברה של אפליקציות ותכונות מערכת אחרות בסטרימינג מהטלפון"</string>
- <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"גישה לרשימה של מכשירים זמינים ובחירה איזה מהם ישמש כדי לשדר או להעביר (cast) אודיו או וידאו מאפליקציות אחרות"</string>
+ <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"גישה לרשימה של מכשירים זמינים ובחירה איזה מהם ישמש כדי לשדר אודיו או וידאו או להפעיל Cast שלהם מאפליקציות אחרות"</string>
<string name="device_type" product="default" msgid="8268703872070046263">"טלפון"</string>
<string name="device_type" product="tablet" msgid="5038791954983067774">"טאבלט"</string>
</resources>
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index c2d452db..8d44d9c 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -48,7 +48,7 @@
<string name="passwords" msgid="5419394230391253816">"lozinke"</string>
<string name="sign_ins" msgid="4710739369149469208">"prijave"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informacije o prijavi"</string>
- <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvaj <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> na"</string>
+ <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvaj vrstu akreditiva \"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>\" na"</string>
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Kreirati pristupni ključ na drugom uređaju?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Sačuvati lozinku na drugom uređaju?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Sačuvati akreditive za prijavu na drugom uređaju?"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 32405a4..95b6c29 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"Gestor de credencials"</string>
<string name="string_cancel" msgid="6369133483981306063">"Cancel·la"</string>
<string name="string_continue" msgid="1346732695941131882">"Continua"</string>
- <string name="string_more_options" msgid="2763852250269945472">"Desa diferent"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"Desa d\'altra forma"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Més informació"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"Mostra la contrasenya"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"Amaga la contrasenya"</string>
@@ -74,7 +74,7 @@
<string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Utilitza el bloqueig de pantalla per iniciar la sessió a <xliff:g id="APP_NAME">%1$s</xliff:g> amb <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
<string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloqueja les opcions d\'inici de sessió per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Tria una clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Tria una clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Tria una contrasenya desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Tria un inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Selecciona un compte per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vols triar una opció per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index ccff535..115f544 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -48,7 +48,7 @@
<string name="passwords" msgid="5419394230391253816">"Passwörter"</string>
<string name="sign_ins" msgid="4710739369149469208">"Anmeldungen"</string>
<string name="sign_in_info" msgid="2627704710674232328">"Anmeldedaten"</string>
- <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> speichern unter"</string>
+ <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> speichern in"</string>
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Passkey auf einem anderen Gerät erstellen?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Passwort auf einem anderen Gerät speichern?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Anmeldedaten auf einem anderen Gerät speichern?"</string>
@@ -74,7 +74,7 @@
<string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Du kannst die Displaysperre verwenden, um dich in <xliff:g id="APP_NAME">%1$s</xliff:g> als <xliff:g id="USERNAME">%2$s</xliff:g> anzumelden"</string>
<string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Anmeldeoptionen für <xliff:g id="APP_NAME">%1$s</xliff:g> freischalten"</string>
<string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Einen gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
- <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Ein gespeichertes Passwort für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
+ <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Gespeichertes Passwort für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
<string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Konto für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
<string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Option für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen?"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index c406857..b239fc3 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"Gestionnaire d\'identifiants"</string>
<string name="string_cancel" msgid="6369133483981306063">"Annuler"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
- <string name="string_more_options" msgid="2763852250269945472">"Sauver autrement"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"Autre façon"</string>
<string name="string_learn_more" msgid="4541600451688392447">"En savoir plus"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"Afficher le mot de passe"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"Masquer le mot de passe"</string>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 2d90646..39abbb986 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"Upravitelj vjerodajnicama"</string>
<string name="string_cancel" msgid="6369133483981306063">"Odustani"</string>
<string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
- <string name="string_more_options" msgid="2763852250269945472">"Spremi drugi način"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"Spremi na drugi način"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Saznajte više"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"Prikaži zaporku"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"Sakrij zaporku"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index d23874b..868357f 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -30,7 +30,7 @@
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Դուք կարող եք մուտք գործել այլ սարքերում, քանի որ մուտքի բանալիները պահվում են գաղտնաբառերի կառավարիչում"</string>
<string name="more_about_passkeys_title" msgid="7797903098728837795">"Ավելին՝ անցաբառերի մասին"</string>
<string name="passwordless_technology_title" msgid="2497513482056606668">"Գաղտնաբառեր չպահանջող տեխնոլոգիա"</string>
- <string name="passwordless_technology_detail" msgid="6853928846532955882">"Անցաբառերը ձեզ թույլ են տալիս մուտք գործել առանց գաղտնաբառերի։ Ձեզ պարզապես հարկավոր է օգտագործել ձեր մատնահետքը, դիմաճանաչումը, PIN կոդը կամ նախշը՝ ձեր ինքնությունը հաստատելու և անցաբառ ստեղծելու համար։"</string>
+ <string name="passwordless_technology_detail" msgid="6853928846532955882">"Մուտքի բանալիները ձեզ թույլ են տալիս մուտք գործել առանց գաղտնաբառերի։ Ձեզ պարզապես հարկավոր է օգտագործել ձեր մատնահետքը, դիմաճանաչումը, PIN կոդը կամ նախշը՝ ձեր ինքնությունը հաստատելու և մուտքի բանալի ստեղծելու համար։"</string>
<string name="public_key_cryptography_title" msgid="6751970819265298039">"Բաց բանալու կրիպտոգրաֆիա"</string>
<string name="public_key_cryptography_detail" msgid="6937631710280562213">"Ըստ FIDO դաշինքի (որը ներառում է Google-ը, Apple-ը, Microsoft-ը և այլ ընկերություններ) և W3C ստանդարտների՝ անցաբառերն օգտագործում են կրիպտոգրաֆիկ բանալիների զույգ։ Օգտանվան և գաղտնաբառի փոխարեն հավելվածի կամ կայքի համար մենք ստեղծում ենք բաց-փակ բանալիների զույգ։ Փակ բանալին ապահով պահվում է ձեր սարքում կամ գաղտնաբառերի կառավարիչում և հաստատում է ձեր ինքնությունը։ Բաց բանալին փոխանցվում է հավելվածի կամ կայքի սերվերին։ Համապատասխան բանալիների միջոցով կարող եք ակնթարթորեն գրանցվել և մուտք գործել։"</string>
<string name="improved_account_security_title" msgid="1069841917893513424">"Հաշվի բարելավված անվտանգություն"</string>
@@ -39,17 +39,17 @@
<string name="seamless_transition_detail" msgid="4475509237171739843">"Թեև մենք առանց գաղտնաբառերի ապագայի ճանապարհին ենք, դրանք դեռ հասանելի կլինեն անցաբառերի հետ մեկտեղ։"</string>
<string name="choose_provider_title" msgid="8870795677024868108">"Նշեք, թե որտեղ եք ուզում պահել ձեր <xliff:g id="CREATETYPES">%1$s</xliff:g>ը"</string>
<string name="choose_provider_body" msgid="4967074531845147434">"Ընտրեք գաղտնաբառերի կառավարիչ՝ ձեր տեղեկությունները պահելու և հաջորդ անգամ ավելի արագ մուտք գործելու համար"</string>
- <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Ստեղծե՞լ անցաբառ՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
+ <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"Ստեղծե՞լ մուտքի բանալի՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
<string name="choose_create_option_password_title" msgid="4481366993598649224">"Պահե՞լ գաղտնաբառը՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
<string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Պահե՞լ «<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածի մուտքի տվյալները"</string>
- <string name="passkey" msgid="632353688396759522">"անցաբառ"</string>
+ <string name="passkey" msgid="632353688396759522">"մուտքի բանալի"</string>
<string name="password" msgid="6738570945182936667">"գաղտնաբառ"</string>
<string name="passkeys" msgid="5733880786866559847">"անցաբառեր"</string>
<string name="passwords" msgid="5419394230391253816">"գաղտնաբառեր"</string>
<string name="sign_ins" msgid="4710739369149469208">"մուտք"</string>
<string name="sign_in_info" msgid="2627704710674232328">"մուտքի տվյալներ"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Պահել <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ն այստեղ՝"</string>
- <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Ստեղծե՞լ անցաբառ այլ սարքում"</string>
+ <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Ստեղծե՞լ մուտքի բանալի այլ սարքում"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Պահե՞լ գաղտնաբառն այլ սարքում"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Պահե՞լ մուտքի տվյալներն այլ սարքում"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Միշտ մուտք գործե՞լ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> հավելվածի միջոցով"</string>
@@ -57,9 +57,9 @@
<string name="set_as_default" msgid="4415328591568654603">"Նշել որպես կանխադրված"</string>
<string name="settings" msgid="6536394145760913145">"Կարգավորումներ"</string>
<string name="use_once" msgid="9027366575315399714">"Օգտագործել մեկ անգամ"</string>
- <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> գաղտնաբառ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> անցաբառ"</string>
+ <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> գաղտնաբառ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> մուտքի բանալի"</string>
<string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> գաղտնաբառ"</string>
- <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> անցաբառ"</string>
+ <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> մուտքի բանալի"</string>
<string name="more_options_usage_credentials" msgid="1785697001787193984">"Մուտքի տվյալներ (<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g>)"</string>
<string name="passkey_before_subtitle" msgid="2448119456208647444">"Անցաբառ"</string>
<string name="another_device" msgid="5147276802037801217">"Այլ սարք"</string>
@@ -73,7 +73,7 @@
<string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Օգտագործեք ձեր հաշիվը՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
<string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Օգտագործեք ձեր էկրանի կողպումը՝ <xliff:g id="USERNAME">%2$s</xliff:g> հաշվի միջոցով <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
<string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Ապակողպեք մուտք գործելու տարբերակներ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
- <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Ընտրեք պահված անցաբառ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
+ <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Ընտրեք պահված մուտքի բանալի <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
<string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Ընտրեք պահված գաղտնաբառ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
<string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Ընտրեք մուտքի պահված տվյալներ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Ընտրեք հաշիվ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 468f4e7..7067a40 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -89,7 +89,7 @@
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"탭하여 잠금 해제"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"로그인 정보 없음"</string>
<string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>의 로그인 정보 없음"</string>
- <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"로그인 관리"</string>
+ <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"로그인 정보 관리"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"다른 기기에서"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"다른 기기 사용"</string>
<string name="request_cancelled_by" msgid="3735222326886267820">"<xliff:g id="APP_NAME">%1$s</xliff:g>에 의해 요청이 취소됨"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index 2f6086a..e0def18 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"အထောက်အထားမန်နေဂျာ"</string>
<string name="string_cancel" msgid="6369133483981306063">"မလုပ်တော့"</string>
<string name="string_continue" msgid="1346732695941131882">"ရှေ့ဆက်ရန်"</string>
- <string name="string_more_options" msgid="2763852250269945472">"အခြားနည်း သိမ်းရန်"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"အခြားနည်းသုံးရန်"</string>
<string name="string_learn_more" msgid="4541600451688392447">"ပိုမိုလေ့လာရန်"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"စကားဝှက်ကို ပြရန်"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"စကားဝှက်ကို ဖျောက်ရန်"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 336b29f..e3a9191 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"କ୍ରେଡେନସିଆଲ ମେନେଜର"</string>
<string name="string_cancel" msgid="6369133483981306063">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="string_continue" msgid="1346732695941131882">"ଜାରି ରଖନ୍ତୁ"</string>
- <string name="string_more_options" msgid="2763852250269945472">"ଅନ୍ୟ ଉପାୟରେ ସେଭ କର"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"ଅନ୍ୟ ଭାବେ ସେଭ କରନ୍ତୁ"</string>
<string name="string_learn_more" msgid="4541600451688392447">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"ପାସୱାର୍ଡ ଦେଖାନ୍ତୁ"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"ପାସୱାର୍ଡ ଲୁଚାନ୍ତୁ"</string>
diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index 3857de4..caa7b09 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"Menedżer danych logowania"</string>
<string name="string_cancel" msgid="6369133483981306063">"Anuluj"</string>
<string name="string_continue" msgid="1346732695941131882">"Dalej"</string>
- <string name="string_more_options" msgid="2763852250269945472">"Zapisz inny sposób"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"Zapisz w inny sposób"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Więcej informacji"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"Pokaż hasło"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"Ukryj hasło"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 2204e02..a3476d9 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"Credential Manager"</string>
<string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
- <string name="string_more_options" msgid="2763852250269945472">"Guardar outra forma"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"Guardar de outra forma"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Saber mais"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"Mostrar palavra-passe"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar palavra-passe"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index ec2a2d6..936ff79 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -20,7 +20,7 @@
<string name="app_name" msgid="4539824758261855508">"Менеджер учетных данных"</string>
<string name="string_cancel" msgid="6369133483981306063">"Отмена"</string>
<string name="string_continue" msgid="1346732695941131882">"Продолжить"</string>
- <string name="string_more_options" msgid="2763852250269945472">"Сохранить"</string>
+ <string name="string_more_options" msgid="2763852250269945472">"Другой способ"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Подробнее"</string>
<string name="content_description_show_password" msgid="3283502010388521607">"Показать пароль"</string>
<string name="content_description_hide_password" msgid="6841375971631767996">"Скрыть пароль"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 8dc0fc2..d943979 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -48,7 +48,7 @@
<string name="passwords" msgid="5419394230391253816">"fjalëkalime"</string>
<string name="sign_ins" msgid="4710739369149469208">"identifikimet"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informacionet e identifikimit"</string>
- <string name="save_credential_to_title" msgid="3172811692275634301">"Ruaj <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> te"</string>
+ <string name="save_credential_to_title" msgid="3172811692275634301">"Të ruhet <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> te"</string>
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Të krijohet çelësi i kalimit në një pajisje tjetër?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Të ruhet fjalëkalimi në një pajisje tjetër?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Të ruhet identifikimi në një pajisje tjetër?"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 3c9c3b7..b423b2c 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -74,7 +74,7 @@
<string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında <xliff:g id="USERNAME">%2$s</xliff:g> hesabıyla oturum açmak için ekran kilidinizi kullanın"</string>
<string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma seçeneklerinin kilidini açın"</string>
<string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir geçiş anahtarı kullanın"</string>
- <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir şifre kullanın"</string>
+ <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir şifre seçin"</string>
<string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgilerini kullanın"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması için bir hesap seçin"</string>
<string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> için bir seçim yapmak ister misiniz?"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index a3f79ca..cd5b7bb 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -82,7 +82,7 @@
<string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Увійти іншим способом"</string>
<string name="snackbar_action" msgid="37373514216505085">"Переглянути варіанти"</string>
<string name="get_dialog_button_label_continue" msgid="6446201694794283870">"Продовжити"</string>
- <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Опції входу"</string>
+ <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Способи входу"</string>
<string name="button_label_view_more" msgid="3429098227286495651">"Переглянути більше"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Для користувача <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблоковані менеджери паролів"</string>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index d5f3093..6b22e36 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -40,7 +40,7 @@
<string name="choose_provider_title" msgid="8870795677024868108">"選擇要將<xliff:g id="CREATETYPES">%1$s</xliff:g>存在哪裡"</string>
<string name="choose_provider_body" msgid="4967074531845147434">"選取密碼管理工具並儲存資訊,下次就能更快登入"</string>
<string name="choose_create_option_passkey_title" msgid="8762295821604276511">"要建立用於登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼金鑰嗎?"</string>
- <string name="choose_create_option_password_title" msgid="4481366993598649224">"要儲存用於登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼嗎?"</string>
+ <string name="choose_create_option_password_title" msgid="4481366993598649224">"要儲存登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼嗎?"</string>
<string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"要儲存「<xliff:g id="APP_NAME">%1$s</xliff:g>」的登入資訊嗎?"</string>
<string name="passkey" msgid="632353688396759522">"密碼金鑰"</string>
<string name="password" msgid="6738570945182936667">"密碼"</string>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index a2f55cd..8cde454 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -125,6 +125,7 @@
return Triple(true, false, null)
}
val shouldShowCancellationUi = cancelUiRequest.shouldShowCancellationExplanation()
+ viewModel?.onDeveloperCancellationReceivedForBiometricPrompt()
Log.d(
Constants.LOG_TAG, "Received UI cancellation intent. Should show cancellation" +
" ui = $shouldShowCancellationUi")
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index 7bc3241..d4a8110 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -19,6 +19,7 @@
import android.app.Activity
import android.hardware.biometrics.BiometricPrompt
import android.hardware.biometrics.BiometricPrompt.AuthenticationResult
+import android.os.CancellationSignal
import android.os.IBinder
import android.text.TextUtils
import android.util.Log
@@ -232,8 +233,13 @@
authResult: BiometricPrompt.AuthenticationResult? = null,
authError: BiometricError? = null,
) {
- Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
- ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
+ if (authError == null) {
+ Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
+ ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
+ } else {
+ Log.d(Constants.LOG_TAG, "Biometric flow error: ${authError.errorCode} " +
+ "propagating to provider, message: ${authError.errorMessage}.")
+ }
uiState = if (entry.pendingIntent != null) {
uiState.copy(
selectedEntry = entry,
@@ -385,9 +391,15 @@
val providerId = selectedEntry.providerId
val entryKey = selectedEntry.entryKey
val entrySubkey = selectedEntry.entrySubkey
- Log.d(
- Constants.LOG_TAG, "Option selected for entry: " +
- " {provider=$providerId, key=$entryKey, subkey=$entrySubkey")
+ if (authError == null) {
+ Log.d(
+ Constants.LOG_TAG, "Option selected for entry: " +
+ " {provider=$providerId, key=$entryKey, subkey=$entrySubkey"
+ )
+ } else {
+ Log.d(Constants.LOG_TAG, "Biometric flow error: ${authError.errorCode} " +
+ "propagating to provider, message: ${authError.errorMessage}.")
+ }
if (selectedEntry.pendingIntent != null) {
uiState = uiState.copy(
selectedEntry = selectedEntry,
@@ -424,6 +436,33 @@
/**************************************************************************/
/**
+ * Cancels the biometric prompt's cancellation signal. Should only be called when the credential
+ * manager ui receives a developer cancellation signal. If the prompt is already done, we do
+ * not allow a cancellation, given the UI cancellation will be caught by the backend. We also
+ * set the biometricStatus to CANCELED, so that only in this case, we do *not* propagate the
+ * ERROR_CANCELED when a developer cancellation signal is the root cause.
+ */
+ fun onDeveloperCancellationReceivedForBiometricPrompt() {
+ val biometricCancellationSignal = uiState.biometricState.biometricCancellationSignal
+ if (!biometricCancellationSignal.isCanceled && uiState.biometricState.biometricStatus
+ != BiometricPromptState.COMPLETE) {
+ uiState = uiState.copy(
+ biometricState = uiState.biometricState.copy(
+ biometricStatus = BiometricPromptState.CANCELED
+ )
+ )
+ biometricCancellationSignal.cancel()
+ }
+ }
+
+ /**
+ * Retrieve the biometric prompt's cancellation signal (e.g. to pass into the 'authenticate'
+ * API).
+ */
+ fun getBiometricCancellationSignal(): CancellationSignal =
+ uiState.biometricState.biometricCancellationSignal
+
+ /**
* This allows falling back from the biometric prompt screen to the normal get flow by applying
* a reset to all necessary states involved in the fallback.
*/
@@ -450,9 +489,9 @@
}
/**
- * This returns the present biometric state.
+ * This returns the present biometric prompt state's status.
*/
- fun getBiometricPromptState(): BiometricPromptState =
+ fun getBiometricPromptStateStatus(): BiometricPromptState =
uiState.biometricState.biometricStatus
/**************************************************************************/
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
index 0d19a45..b43b5f3 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
@@ -65,7 +65,6 @@
* ).
*
* The above are examples; the credential type can change depending on scenario.
- * // TODO(b/333445112) : Finalize once all the strings and create flow is iterated to completion
*/
data class BiometricDisplayInfo(
val providerIcon: Bitmap,
@@ -84,7 +83,8 @@
data class BiometricState(
val biometricResult: BiometricResult? = null,
val biometricError: BiometricError? = null,
- val biometricStatus: BiometricPromptState = BiometricPromptState.INACTIVE
+ val biometricStatus: BiometricPromptState = BiometricPromptState.INACTIVE,
+ val biometricCancellationSignal: CancellationSignal = CancellationSignal(),
)
/**
@@ -118,6 +118,7 @@
getBiometricPromptState: () -> BiometricPromptState,
onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
onBiometricFailureFallback: (BiometricFlowType) -> Unit,
+ getBiometricCancellationSignal: () -> CancellationSignal,
getRequestDisplayInfo: RequestDisplayInfo? = null,
getProviderInfoList: List<ProviderInfo>? = null,
getProviderDisplayInfo: ProviderDisplayInfo? = null,
@@ -141,11 +142,13 @@
val callback: BiometricPrompt.AuthenticationCallback =
setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry,
- onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange)
+ onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange,
+ getBiometricPromptState)
- Log.d(TAG, "The BiometricPrompt API call begins.")
+ Log.d(TAG, "The BiometricPrompt API call begins for Get.")
runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage,
- onBiometricFailureFallback, BiometricFlowType.GET, onCancelFlowAndFinish)
+ onBiometricFailureFallback, BiometricFlowType.GET, onCancelFlowAndFinish,
+ getBiometricCancellationSignal)
}
/**
@@ -163,6 +166,7 @@
getBiometricPromptState: () -> BiometricPromptState,
onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
onBiometricFailureFallback: (BiometricFlowType) -> Unit,
+ getBiometricCancellationSignal: () -> CancellationSignal,
createRequestDisplayInfo: com.android.credentialmanager.createflow
.RequestDisplayInfo? = null,
createProviderInfo: EnabledProviderInfo? = null,
@@ -185,11 +189,13 @@
val callback: BiometricPrompt.AuthenticationCallback =
setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry,
- onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange)
+ onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange,
+ getBiometricPromptState)
- Log.d(TAG, "The BiometricPrompt API call begins.")
+ Log.d(TAG, "The BiometricPrompt API call begins for Create.")
runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage,
- onBiometricFailureFallback, BiometricFlowType.CREATE, onCancelFlowAndFinish)
+ onBiometricFailureFallback, BiometricFlowType.CREATE, onCancelFlowAndFinish,
+ getBiometricCancellationSignal)
}
/**
@@ -206,7 +212,8 @@
openMoreOptionsPage: () -> Unit,
onBiometricFailureFallback: (BiometricFlowType) -> Unit,
biometricFlowType: BiometricFlowType,
- onCancelFlowAndFinish: () -> Unit
+ onCancelFlowAndFinish: () -> Unit,
+ getBiometricCancellationSignal: () -> CancellationSignal,
) {
try {
if (!canCallBiometricPrompt(biometricDisplayInfo, context)) {
@@ -217,12 +224,7 @@
val biometricPrompt = setupBiometricPrompt(context, biometricDisplayInfo,
openMoreOptionsPage, biometricDisplayInfo.biometricRequestInfo, onCancelFlowAndFinish)
- val cancellationSignal = CancellationSignal()
- cancellationSignal.setOnCancelListener {
- Log.d(TAG, "Your cancellation signal was called.")
- // TODO(b/333445112) : Migrate towards passing along the developer cancellation signal
- // or validate the necessity for this
- }
+ val cancellationSignal = getBiometricCancellationSignal()
val executor = getMainExecutor(context)
@@ -251,8 +253,6 @@
* Note that if device credential is the only available modality but not requested, or if none
* of the requested modalities are available, we fallback to the normal flow to ensure a selector
* shows up.
- * // TODO(b/334197980) : While we already fallback in cases the selector doesn't show, confirm
- * // final plan.
*/
private fun canCallBiometricPrompt(
biometricDisplayInfo: BiometricDisplayInfo,
@@ -270,12 +270,12 @@
return false
}
- if (ifOnlySupportsAtMostDeviceCredentials(biometricManager)) return false
+ if (onlySupportsAtMostDeviceCredentials(biometricManager)) return false
return true
}
-private fun ifOnlySupportsAtMostDeviceCredentials(biometricManager: BiometricManager): Boolean {
+private fun onlySupportsAtMostDeviceCredentials(biometricManager: BiometricManager): Boolean {
if (biometricManager.canAuthenticate(Authenticators.BIOMETRIC_WEAK) !=
BiometricManager.BIOMETRIC_SUCCESS &&
biometricManager.canAuthenticate(Authenticators.BIOMETRIC_STRONG) !=
@@ -343,11 +343,11 @@
selectedEntry: EntryInfo,
onCancelFlowAndFinish: () -> Unit,
onIllegalStateAndFinish: (String) -> Unit,
- onBiometricPromptStateChange: (BiometricPromptState) -> Unit
+ onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+ getBiometricPromptState: () -> BiometricPromptState,
): BiometricPrompt.AuthenticationCallback {
val callback: BiometricPrompt.AuthenticationCallback =
object : BiometricPrompt.AuthenticationCallback() {
- // TODO(b/333445772) : Validate remaining callbacks
override fun onAuthenticationSucceeded(
authResult: BiometricPrompt.AuthenticationResult?
) {
@@ -374,6 +374,12 @@
override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
super.onAuthenticationError(errorCode, errString)
Log.d(TAG, "Authentication error-ed out: $errorCode and $errString")
+ if (getBiometricPromptState() == BiometricPromptState.CANCELED && errorCode
+ == BiometricPrompt.BIOMETRIC_ERROR_CANCELED) {
+ Log.d(TAG, "Developer cancellation signal received. Nothing more to do.")
+ // This unique edge case means a developer cancellation signal was sent.
+ return
+ }
onBiometricPromptStateChange(BiometricPromptState.COMPLETE)
if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED) {
// Note that because the biometric prompt is imbued directly
@@ -471,8 +477,7 @@
val singleEntryType = selectedEntry.credentialType
val username = selectedEntry.userName
- // TODO(b/330396140) : Finalize localization and parsing for specific sign in option flows
- // (fingerprint, face, etc...))
+ // TODO(b/336362538) : In W, utilize updated localization strings
displayTitleText = context.getString(
generateDisplayTitleTextResCode(singleEntryType),
getRequestDisplayInfo.appName
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
index e1aa041..eb77937 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
@@ -22,5 +22,10 @@
/** The biometric prompt is active but data hasn't been returned yet. */
PENDING,
/** The biometric prompt has closed and returned data we then send to the provider activity. */
- COMPLETE
+ COMPLETE,
+ /**
+ * The biometric prompt has been canceled by a developer signal. If this is true, certain
+ * conditions can be triggered, such as no longer propagating ERROR_CANCELED.
+ */
+ CANCELED,
}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 282a1b5..7d61f73 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -18,6 +18,7 @@
import android.credentials.flags.Flags.selectorUiImprovementsEnabled
import android.hardware.biometrics.BiometricPrompt
+import android.os.CancellationSignal
import android.text.TextUtils
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
@@ -118,9 +119,11 @@
fallbackToOriginalFlow =
viewModel::fallbackFromBiometricToNormalFlow,
getBiometricPromptState =
- viewModel::getBiometricPromptState,
+ viewModel::getBiometricPromptStateStatus,
onBiometricPromptStateChange =
- viewModel::onBiometricPromptStateChange
+ viewModel::onBiometricPromptStateChange,
+ getBiometricCancellationSignal =
+ viewModel::getBiometricCancellationSignal
)
CreateScreenState.MORE_OPTIONS_SELECTION_ONLY -> MoreOptionsSelectionCard(
requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
@@ -638,6 +641,7 @@
fallbackToOriginalFlow: (BiometricFlowType) -> Unit,
getBiometricPromptState: () -> BiometricPromptState,
onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+ getBiometricCancellationSignal: () -> CancellationSignal,
) {
if (biometricEntry == null) {
fallbackToOriginalFlow(BiometricFlowType.CREATE)
@@ -655,5 +659,6 @@
createProviderInfo = enabledProviderInfo,
onBiometricFailureFallback = fallbackToOriginalFlow,
onIllegalStateAndFinish = onIllegalScreenStateAndFinish,
+ getBiometricCancellationSignal = getBiometricCancellationSignal,
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index c98bb5e..ba61b90 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -20,6 +20,7 @@
import android.credentials.flags.Flags.selectorUiImprovementsEnabled
import android.graphics.drawable.Drawable
import android.hardware.biometrics.BiometricPrompt
+import android.os.CancellationSignal
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.activity.result.IntentSenderRequest
@@ -161,9 +162,11 @@
fallbackToOriginalFlow =
viewModel::fallbackFromBiometricToNormalFlow,
getBiometricPromptState =
- viewModel::getBiometricPromptState,
+ viewModel::getBiometricPromptStateStatus,
onBiometricPromptStateChange =
- viewModel::onBiometricPromptStateChange
+ viewModel::onBiometricPromptStateChange,
+ getBiometricCancellationSignal =
+ viewModel::getBiometricCancellationSignal
)
} else if (credmanBiometricApiEnabled() &&
getCredentialUiState.currentScreenState
@@ -256,6 +259,7 @@
fallbackToOriginalFlow: (BiometricFlowType) -> Unit,
getBiometricPromptState: () -> BiometricPromptState,
onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+ getBiometricCancellationSignal: () -> CancellationSignal,
) {
if (biometricEntry == null) {
fallbackToOriginalFlow(BiometricFlowType.GET)
@@ -273,7 +277,8 @@
getRequestDisplayInfo = requestDisplayInfo,
getProviderInfoList = providerInfoList,
getProviderDisplayInfo = providerDisplayInfo,
- onBiometricFailureFallback = fallbackToOriginalFlow
+ onBiometricFailureFallback = fallbackToOriginalFlow,
+ getBiometricCancellationSignal = getBiometricCancellationSignal
)
}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_thai_pattachote.kcm b/packages/InputDevices/res/raw/keyboard_layout_thai_pattachote.kcm
new file mode 100644
index 0000000..a136aca
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_thai_pattachote.kcm
@@ -0,0 +1,317 @@
+# Copyright 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.
+
+#
+# Thai Pattachote keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '_'
+ base: '_'
+ shift, capslock: '\u0e3f'
+}
+
+key 1 {
+ label: '='
+ base: '='
+ shift, capslock: '+'
+}
+
+key 2 {
+ label: '\u0e52'
+ base: '\u0e52'
+ shift, capslock: '\u0022'
+}
+
+key 3 {
+ label: '\u0e53'
+ base: '\u0e53'
+ shift, capslock: '/'
+}
+
+key 4 {
+ label: '\u0e54'
+ base: '\u0e54'
+ shift, capslock: ','
+}
+
+key 5 {
+ label: '\u0e55'
+ base: '\u0e55'
+ shift, capslock: '?'
+}
+
+key 6 {
+ label: '\u0e39'
+ base: '\u0e39'
+ shift, capslock: '\u0e38'
+}
+
+key 7 {
+ label: '\u0e57'
+ base: '\u0e57'
+ shift, capslock: '_'
+}
+
+key 8 {
+ label: '\u0e58'
+ base: '\u0e58'
+ shift, capslock: '.'
+}
+
+key 9 {
+ label: '\u0e59'
+ base: '\u0e59'
+ shift, capslock: '('
+}
+
+key 0 {
+ label: '\u0e50'
+ base: '\u0e50'
+ shift, capslock: ')'
+}
+
+key MINUS {
+ label: '\u0e51'
+ base: '\u0e51'
+ shift, capslock: '-'
+}
+
+key EQUALS {
+ label: '\u0e56'
+ base: '\u0e56'
+ shift, capslock: '%'
+}
+
+### ROW 2
+
+key Q {
+ label: '\u0e47'
+ base: '\u0e47'
+ shift, capslock: '\u0e4a'
+}
+
+key W {
+ label: '\u0e15'
+ base: '\u0e15'
+ shift, capslock: '\u0e24'
+}
+
+key E {
+ label: '\u0e22'
+ base: '\u0e22'
+ shift, capslock: '\u0e46'
+}
+
+key R {
+ label: '\u0e2d'
+ base: '\u0e2d'
+ shift, capslock: '\u0e0d'
+}
+
+key T {
+ label: '\u0e23'
+ base: '\u0e23'
+ shift, capslock: '\u0e29'
+}
+
+key Y {
+ label: '\u0e48'
+ base: '\u0e48'
+ shift, capslock: '\u0e36'
+}
+
+key U {
+ label: '\u0e14'
+ base: '\u0e14'
+ shift, capslock: '\u0e1d'
+}
+
+key I {
+ label: '\u0e21'
+ base: '\u0e21'
+ shift, capslock: '\u0e0b'
+}
+
+key O {
+ label: '\u0e27'
+ base: '\u0e27'
+ shift, capslock: '\u0e16'
+}
+
+key P {
+ label: '\u0e41'
+ base: '\u0e41'
+ shift, capslock: '\u0e12'
+}
+
+key LEFT_BRACKET {
+ label: '\u0e43'
+ base: '\u0e43'
+ shift, capslock: '\u0e2f'
+}
+
+key RIGHT_BRACKET {
+ label: '\u0e0c'
+ base: '\u0e0c'
+ shift, capslock: '\u0e26'
+}
+
+### ROW 3
+
+key A {
+ label: '\u0e49'
+ base: '\u0e49'
+ shift, capslock: '\u0e4b'
+}
+
+key S {
+ label: '\u0e17'
+ base: '\u0e17'
+ shift, capslock: '\u0e18'
+}
+
+key D {
+ label: '\u0e07'
+ base: '\u0e07'
+ shift, capslock: '\u0e33'
+}
+
+key F {
+ label: '\u0e01'
+ base: '\u0e01'
+ shift, capslock: '\u0e13'
+}
+
+key G {
+ label: '\u0e31'
+ base: '\u0e31'
+ shift, capslock: '\u0e4c'
+}
+
+key H {
+ label: '\u0e35'
+ base: '\u0e35'
+ shift, capslock: '\u0e37'
+}
+
+key J {
+ label: '\u0e32'
+ base: '\u0e32'
+ shift, capslock: '\u0e1c'
+}
+
+key K {
+ label: '\u0e19'
+ base: '\u0e19'
+ shift, capslock: '\u0e0a'
+}
+
+key L {
+ label: '\u0e40'
+ base: '\u0e40'
+ shift, capslock: '\u0e42'
+}
+
+key SEMICOLON {
+ label: '\u0e44'
+ base: '\u0e44'
+ shift, capslock: '\u0e06'
+}
+
+key APOSTROPHE {
+ label: '\u0e02'
+ base: '\u0e02'
+ shift, capslock: '\u0e11'
+}
+
+key BACKSLASH {
+ label: '\u0e45'
+ base: '\u0e45'
+ shift, capslock: '\u0e4d'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\u0e45'
+ base: '\u0e45'
+ shift, capslock: '\u0e4d'
+}
+
+key Z {
+ label: '\u0e1a'
+ base: '\u0e1a'
+ shift, capslock: '\u0e0e'
+}
+
+key X {
+ label: '\u0e1b'
+ base: '\u0e1b'
+ shift, capslock: '\u0e0f'
+}
+
+key C {
+ label: '\u0e25'
+ base: '\u0e25'
+ shift, capslock: '\u0e10'
+}
+
+key V {
+ label: '\u0e2b'
+ base: '\u0e2b'
+ shift, capslock: '\u0e20'
+}
+
+key B {
+ label: '\u0e34'
+ base: '\u0e34'
+ shift, capslock: '\u0e31'
+}
+
+key N {
+ label: '\u0e04'
+ base: '\u0e04'
+ shift, capslock: '\u0e28'
+}
+
+key M {
+ label: '\u0e2a'
+ base: '\u0e2a'
+ shift, capslock: '\u0e2e'
+}
+
+key COMMA {
+ label: '\u0e30'
+ base: '\u0e30'
+ shift, capslock: '\u0e1f'
+}
+
+key PERIOD {
+ label: '\u0e08'
+ base: '\u0e08'
+ shift, capslock: '\u0e09'
+}
+
+key SLASH {
+ label: '\u0e1e'
+ base: '\u0e1e'
+ shift, capslock: '\u0e2c'
+}
\ No newline at end of file
diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml
index 72bb640..232df24 100644
--- a/packages/InputDevices/res/values-af/strings.xml
+++ b/packages/InputDevices/res/values-af/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgies"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index 0eea57b..9a8bd37 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ሞንጎሊያኛ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ጂዮርጂያኛ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ታይላንድኛ (ኬድማኒ)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index 88be85a..e79519a 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"المنغولية"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"الجورجية"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"التايلاندية (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml
index 3cd707f..802b13e 100644
--- a/packages/InputDevices/res/values-as/strings.xml
+++ b/packages/InputDevices/res/values-as/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"থাই (কেডমানি)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-az/strings.xml b/packages/InputDevices/res/values-az/strings.xml
index 332fd1c..4a8e7ff 100644
--- a/packages/InputDevices/res/values-az/strings.xml
+++ b/packages/InputDevices/res/values-az/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Monqol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcü"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tay (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <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 a7ede75..9126a74 100644
--- a/packages/InputDevices/res/values-b+sr+Latn/strings.xml
+++ b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolska"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajski (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml
index 011ad66..4dd59bf 100644
--- a/packages/InputDevices/res/values-be/strings.xml
+++ b/packages/InputDevices/res/values-be/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Мангольская"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузінская"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайская (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index 68f120a..3dbd6f7 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузински"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тайландски (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-bn/strings.xml b/packages/InputDevices/res/values-bn/strings.xml
index 74b2462..0d8e5d8 100644
--- a/packages/InputDevices/res/values-bn/strings.xml
+++ b/packages/InputDevices/res/values-bn/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"মঙ্গোলিয়ান"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"জর্জিয়ান"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"থাই (কেডমানি)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-bs/strings.xml b/packages/InputDevices/res/values-bs/strings.xml
index ea8d91e..bb12f00 100644
--- a/packages/InputDevices/res/values-bs/strings.xml
+++ b/packages/InputDevices/res/values-bs/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijski"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajlandski (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml
index 573e325..86b6421 100644
--- a/packages/InputDevices/res/values-ca/strings.xml
+++ b/packages/InputDevices/res/values-ca/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgià"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index 331da96..7832e6e 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolština"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínština"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thajština (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index e399f2c..51cb1ae 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index 75fb724..c4de5a8 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisch"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailändisch (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index 1510708..48f7c025 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Μογγολικά"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Γεωργιανά"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Ταϊλανδικά (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml
index 6db501e..2d37370 100644
--- a/packages/InputDevices/res/values-en-rAU/strings.xml
+++ b/packages/InputDevices/res/values-en-rAU/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml
index ac8ad0a..f863fe9 100644
--- a/packages/InputDevices/res/values-en-rCA/strings.xml
+++ b/packages/InputDevices/res/values-en-rCA/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index 6db501e..2d37370 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index 6db501e..2d37370 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-en-rXC/strings.xml b/packages/InputDevices/res/values-en-rXC/strings.xml
index 159b0e0..0a4344b 100644
--- a/packages/InputDevices/res/values-en-rXC/strings.xml
+++ b/packages/InputDevices/res/values-en-rXC/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index 755491e..216e91f 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index 9387812..648b3d2 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml
index 1543669..0aba840 100644
--- a/packages/InputDevices/res/values-et/strings.xml
+++ b/packages/InputDevices/res/values-et/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruusia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 098ed6f..c1a0dac 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliarra"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiarra"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailandiarra (kedmanee-a)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index 67bdfc8..4fba26d 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"مغولی"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"گرجستانی"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"تایلندی (کدمانی)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index 567c416..b8199a8 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thai (kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index c03fd6d..f375dad 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thaï (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index 8c70b0d..e19d9dc4 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thaï (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml
index 897f7d2..c878e1e 100644
--- a/packages/InputDevices/res/values-gl/strings.xml
+++ b/packages/InputDevices/res/values-gl/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Xeorxiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml
index 3627c5c..d5fe48c 100644
--- a/packages/InputDevices/res/values-gu/strings.xml
+++ b/packages/InputDevices/res/values-gu/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"મોંગોલિયન"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"જ્યોર્જિઅન"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"થાઇ (કેડમાની)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index 4fbcde0..3fa45b1 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन कीबोर्ड का लेआउट"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमेनी)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index c5f46c4..409a321 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolski"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzijska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajlandski (kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index a02f934..3131bc5 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"grúz"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thai (kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml
index cf0a9c7..2307a9b 100644
--- a/packages/InputDevices/res/values-hy/strings.xml
+++ b/packages/InputDevices/res/values-hy/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Մոնղոլերեն"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"վրացերեն"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"թայերեն (քեդմանի)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml
index 5ac0439..69ba58a 100644
--- a/packages/InputDevices/res/values-in/strings.xml
+++ b/packages/InputDevices/res/values-in/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolia"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-is/strings.xml b/packages/InputDevices/res/values-is/strings.xml
index d25497c..5107503 100644
--- a/packages/InputDevices/res/values-is/strings.xml
+++ b/packages/InputDevices/res/values-is/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongólska"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgíska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Taílenskt (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml
index ae86156..740cf37 100644
--- a/packages/InputDevices/res/values-it/strings.xml
+++ b/packages/InputDevices/res/values-it/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolo"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index 9eed7be..6badc3f 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"מונגולית"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"גיאורגית"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"תאית (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 297f351..9676886 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"モンゴル語"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ジョージア語"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"タイ語(Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ka/strings.xml b/packages/InputDevices/res/values-ka/strings.xml
index c471c44..93735c9 100644
--- a/packages/InputDevices/res/values-ka/strings.xml
+++ b/packages/InputDevices/res/values-ka/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"მონღოლური"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ქართული"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ტაილანდური (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-kk/strings.xml b/packages/InputDevices/res/values-kk/strings.xml
index 4c7779e..603b6c7 100644
--- a/packages/InputDevices/res/values-kk/strings.xml
+++ b/packages/InputDevices/res/values-kk/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Моңғол"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузин"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тай (кедмани)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml
index d43fe36..0f3832e 100644
--- a/packages/InputDevices/res/values-km/strings.xml
+++ b/packages/InputDevices/res/values-km/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"មុងហ្គោលី"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ហ្សកហ្ស៊ី"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ថៃ (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml
index 5fd766f..96b9294 100644
--- a/packages/InputDevices/res/values-kn/strings.xml
+++ b/packages/InputDevices/res/values-kn/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ಮಂಗೋಲಿಯನ್"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ಜಾರ್ಜಿಯನ್"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ಥಾಯ್ (ಕೆಡ್ಮನೀ)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index 6c06d2d..9956f26 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"몽골어"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"조지아어"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"태국어(Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ky/strings.xml b/packages/InputDevices/res/values-ky/strings.xml
index 67047d3..0b1ab5a 100644
--- a/packages/InputDevices/res/values-ky/strings.xml
+++ b/packages/InputDevices/res/values-ky/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монголчо"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинче"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайча (Kedmanee баскычтобу)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-lo/strings.xml b/packages/InputDevices/res/values-lo/strings.xml
index 0ffa3ce..3effea7 100644
--- a/packages/InputDevices/res/values-lo/strings.xml
+++ b/packages/InputDevices/res/values-lo/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ມອງໂກລຽນ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ຈໍຈຽນ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ໄທ (ເກດມະນີ)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml
index d6e20eb..82cf221 100644
--- a/packages/InputDevices/res/values-lt/strings.xml
+++ b/packages/InputDevices/res/values-lt/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolų"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzinų"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tajų („Kedmanee“)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml
index 254c70e..952f803 100644
--- a/packages/InputDevices/res/values-lv/strings.xml
+++ b/packages/InputDevices/res/values-lv/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoļu"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzīnu"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Taju valoda (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml
index 16df119..2709689 100644
--- a/packages/InputDevices/res/values-mk/strings.xml
+++ b/packages/InputDevices/res/values-mk/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузиски"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тајландски (кедмани)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ml/strings.xml b/packages/InputDevices/res/values-ml/strings.xml
index 59ee6e6..8559a21 100644
--- a/packages/InputDevices/res/values-ml/strings.xml
+++ b/packages/InputDevices/res/values-ml/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"മംഗോളിയൻ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ജോര്ജ്ജിയൻ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"തായ് (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml
index f013532..397c947 100644
--- a/packages/InputDevices/res/values-mn/strings.xml
+++ b/packages/InputDevices/res/values-mn/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгол"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Гүрж"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тай (кедмани)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index 4dfdbf0..a818afe 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमानी)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ms/strings.xml b/packages/InputDevices/res/values-ms/strings.xml
index 6f8f171..94ec21a 100644
--- a/packages/InputDevices/res/values-ms/strings.xml
+++ b/packages/InputDevices/res/values-ms/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Bahasa Mongolia"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Bahasa Georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-my/strings.xml b/packages/InputDevices/res/values-my/strings.xml
index 4d71a7b..babd1ea 100644
--- a/packages/InputDevices/res/values-my/strings.xml
+++ b/packages/InputDevices/res/values-my/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"မွန်ဂိုလီးယား"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ဂျော်ဂျီယာ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ထိုင်း (ကတ်မနီး)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index 8a1d653..5c465da 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml
index 7a6cbe8..c32e458 100644
--- a/packages/InputDevices/res/values-ne/strings.xml
+++ b/packages/InputDevices/res/values-ne/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मङ्गोलियाली"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"जर्जियाली"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमानी)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml
index bb8acd0..1d399ae 100644
--- a/packages/InputDevices/res/values-nl/strings.xml
+++ b/packages/InputDevices/res/values-nl/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
index d1c2ccc..0d0fbaf 100644
--- a/packages/InputDevices/res/values-or/strings.xml
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ମଙ୍ଗୋଲିଆନ୍"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ଜର୍ଜିଆନ୍"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ଥାଇ (କେଡମାନି)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index 6725072f..fbf50ae 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ਮੰਗੋਲੀਆਈ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ਜਾਰਜੀਆਈ"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ਥਾਈ (ਕੇਦਮਨੀ)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 31a3dac..6bf6f48 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruziński"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajski (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml
index 24db406..e2bad4f 100644
--- a/packages/InputDevices/res/values-pt-rBR/strings.xml
+++ b/packages/InputDevices/res/values-pt-rBR/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml
index 2cc6a8c..7ade82f 100644
--- a/packages/InputDevices/res/values-pt-rPT/strings.xml
+++ b/packages/InputDevices/res/values-pt-rPT/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index 24db406..e2bad4f 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index 49cb306..248b3ad 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolă"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiană"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailandeză (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index d1fbfd6..171b713 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монгольский"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузинский"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайский (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-si/strings.xml b/packages/InputDevices/res/values-si/strings.xml
index e4e4791..27b031b 100644
--- a/packages/InputDevices/res/values-si/strings.xml
+++ b/packages/InputDevices/res/values-si/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"මොන්ගෝලියානු"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ජෝර්ජියානු"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"තායි (කෙඩ්මනී)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index ffe3c8d..7d4315b 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolské"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínske"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thajčina (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index 36f10c7..fc8f146 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolščina"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzinščina"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajščina (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sq/strings.xml b/packages/InputDevices/res/values-sq/strings.xml
index 51da8d7..65cec14 100644
--- a/packages/InputDevices/res/values-sq/strings.xml
+++ b/packages/InputDevices/res/values-sq/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisht"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gjeorgjisht"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tajlandisht (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index 563fe4a..2f500138f 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголска"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузијска"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тајски (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index 878f1ed..f29b665 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoliska"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgiska"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index f8cf6c6..ade2c28 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Kimongolia"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Kijojia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Kithai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ta/strings.xml b/packages/InputDevices/res/values-ta/strings.xml
index e6edc61..14a17ad 100644
--- a/packages/InputDevices/res/values-ta/strings.xml
+++ b/packages/InputDevices/res/values-ta/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"மங்கோலியன்"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ஜார்ஜியன்"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"தாய் (கேட்மேனி)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-te/strings.xml b/packages/InputDevices/res/values-te/strings.xml
index 6ea08d3..676dd92 100644
--- a/packages/InputDevices/res/values-te/strings.xml
+++ b/packages/InputDevices/res/values-te/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"మంగోలియన్"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"జార్జియన్"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"థాయ్ (కెడ్మనీ)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index e3c4a7a..2473128 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ภาษามองโกเลีย"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"ภาษาจอร์เจีย"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ไทย (เกษมณี)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml
index c82a067..cefa8ac 100644
--- a/packages/InputDevices/res/values-tl/strings.xml
+++ b/packages/InputDevices/res/values-tl/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index 74b77e7..ba4703c 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Moğolca"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcüce"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tayca (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index e78d826..c74b1c1 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгольська"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинська"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайська (кедмані)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ur/strings.xml b/packages/InputDevices/res/values-ur/strings.xml
index 644d364..70ce599 100644
--- a/packages/InputDevices/res/values-ur/strings.xml
+++ b/packages/InputDevices/res/values-ur/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"منگؤلی"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"جارجیائی"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"تھائی (کیڈمینی)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml
index 581dea5..bd6c713 100644
--- a/packages/InputDevices/res/values-uz/strings.xml
+++ b/packages/InputDevices/res/values-uz/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzin"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tay (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml
index d58ac65..d665f8e 100644
--- a/packages/InputDevices/res/values-vi/strings.xml
+++ b/packages/InputDevices/res/values-vi/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Tiếng Mông Cổ"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Tiếng Georgia"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tiếng Thái (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index 6a1a5b1..e6c19b3 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古语"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"格鲁吉亚语"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰语 (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml
index 4f761a4..ee3f598 100644
--- a/packages/InputDevices/res/values-zh-rHK/strings.xml
+++ b/packages/InputDevices/res/values-zh-rHK/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"格魯吉亞文"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰文 (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml
index be56620..b25001b 100644
--- a/packages/InputDevices/res/values-zh-rTW/strings.xml
+++ b/packages/InputDevices/res/values-zh-rTW/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"喬治亞文"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰文 (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index 832ce1b..8f07a9b 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -51,4 +51,6 @@
<string name="keyboard_layout_mongolian" msgid="7678483495823936626">"isi-Mongolian"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
<string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Isi-Thai (Kedmanee)"</string>
+ <!-- no translation found for keyboard_layout_thai_pattachote (2547992342794252205) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 33a1d76..e10bd7f 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -149,4 +149,7 @@
<!-- Thai (Kedmanee variant) keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_thai_kedmanee">Thai (Kedmanee)</string>
+
+ <!-- Thai (Pattachote variant) keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_thai_pattachote">Thai (Pattachote)</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 4b7ea90..c18d73c 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -325,4 +325,11 @@
android:keyboardLayout="@raw/keyboard_layout_thai_kedmanee"
android:keyboardLocale="th-Thai"
android:keyboardLayoutType="extended" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_thai_pattachote"
+ android:label="@string/keyboard_layout_thai_pattachote"
+ android:keyboardLayout="@raw/keyboard_layout_thai_pattachote"
+ android:keyboardLocale="th-Thai"
+ android:keyboardLayoutType="extended" />
</keyboard-layouts>
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
index c39956d..a0a1eb9 100644
--- a/packages/PackageInstaller/res/values-pt-rPT/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -99,7 +99,7 @@
<string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"Para sua segurança, o relógio não está atualmente autorizado a instalar apps desconhecidas a partir desta origem. Pode alterar esta opção nas Definições."</string>
<string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"Para sua segurança, o telemóvel não está atualmente autorizado a instalar apps desconhecidas a partir desta origem. Pode alterar esta opção nas Definições."</string>
<string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"O seu telemóvel e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados ao telemóvel ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
- <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"O seu tablet e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados ao tablet ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
+ <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"O seu tablet e os dados pessoais estão mais vulneráveis a ataques por parte de apps desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados ao tablet ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
<string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"A sua TV e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados à TV ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
<string name="cloned_app_label" msgid="7503612829833756160">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
<string name="archiving_app_label" msgid="1127085259724124725">"Arquivar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index f9800b3..9641204 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Gekoppel (geen foon nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Gekoppel (geen media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Gekoppel (geen foon of media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktief. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktief. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterykrag"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Regs: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktief"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gestoor"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktief, net links"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktief, net regs"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktief, links en regs"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktief (net media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Steun oudiodeling"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktief (net media), net linkerkant"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 729ac28..51cf441 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ንቁ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ተቀምጧል"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ገቢር፣ ግራ ብቻ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ገቢር፣ ቀኝ ብቻ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ገቢር፣ ግራ እና ቀኝ"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 9f13551..4b1e925 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"متّصل (بدون هاتف)، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"متّصل (بدون وسائط)، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"متّصل (بدون هاتف أو وسائط)، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"البلوتوث نشِط. مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"البلوتوث نشِط. مستوى الشحن في سماعة الرأس اليسرى: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"مستوى الشحن في سماعة الرأس اليسرى: <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" msgid="5725764679536058365">"مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"نشط"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"السمّاعة الطبية اليسرى فقط مفعَّلة"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"السمّاعة الطبية اليمنى فقط مفعَّلة"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"السمّاعتان اليسرى واليمنى مفعَّلتان"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"البلوتوث مفعَّل (للوسائط فقط)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"تتوفّر ميزة \"مشاركة الصوت\""</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"السماعة اليسرى فقط مشغَّلة (للوسائط فقط)"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 62c1201..13b639a 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"সক্ৰিয়"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ছেভ কৰা হৈছে"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"কেৱল বাঁওফালৰটো সক্ৰিয় হৈছে"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"কেৱল সোঁফালৰটো সক্ৰিয় হৈছে"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাওঁ আৰু সোঁ দুয়োফালৰ সক্ৰিয় হৈছে"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index b1bbf34..a3c0aac 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Qoşuludur (telefon yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Qoşuludur (media yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Qoşuludur (telefon və ya media yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiv. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiv. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Yadda saxlandı"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, yalnız sol"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, yalnız sağ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, sol və sağ"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (yalnız media)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio paylaşma dəstəklənir"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (yalnız media), yalnız sol"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 4af26f2..24830b4 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo s leve strane"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, s desne strane"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, s leve i desne strane"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 9998c9e..986c089 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Узровень зараду: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Уключана"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Захавана"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Уключана, толькі для левага вуха"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Уключана, толькі для правага вуха"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Уключана, для левага і правага вуха"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 03065c6..7097078 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Запазено"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно – само лявото"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно – само дясното"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно – лявото и дясното"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b69a542..e4637fe 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"চালু আছে"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"সেভ করা আছে"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"শুধুমাত্র বাঁদিকের হিয়ারিং এড অ্যাক্টিভ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"শুধুমাত্র ডানদিকের হিয়ারিং এড অ্যাক্টিভ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাঁ ও ডানদিকের হিয়ারিং এড, অ্যাক্টিভ"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 2cc6dc5..e71c2ec 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevi"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desni"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevi i desni"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5a4a923..09b4297 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actiu"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Desat"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actiu, només l\'esquerre"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actiu, només el dret"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actiu, esquerre i dret"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 9a3ba63..b2d75bd 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivní"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Uloženo"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivní, pouze levé"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivní, pouze pravé"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivní, levé a pravé"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c7f1c6e..0f92316 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gemt"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, kun venstre"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, kun højre"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og højre"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index cc962b4..c8d7acd 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gespeichert"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, nur links"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, nur rechts"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, links und rechts"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 2ea96a7..2cc9350 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ενεργό"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Αποθηκεύτηκε"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ενεργό, μόνο το αριστερό"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ενεργό, μόνο το δεξί"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ενεργό, αριστερό και δεξί"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index d4f14f4..2d80c35 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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_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_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 6b49bc9..bc08544 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. 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_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Active. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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>
@@ -107,9 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</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_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index d4f14f4..2d80c35 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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_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_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index d4f14f4..2d80c35 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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_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_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index c255633..b123a13 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -96,10 +96,8 @@
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. 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_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Active. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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>
@@ -107,9 +105,9 @@
<string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</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_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 6a40c42..5142f24 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activado"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo; solo oído izquierdo"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo; solo oído derecho"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo; oídos izquierdo y derecho"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index ab75219..7dc1225 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo, solo oído izquierdo"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo, solo oído derecho"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo, oídos izquierdo y derecho"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index c730457..1236629 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ühendatud (telefoni pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ühendatud (meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ühendatud (telefoni ega meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktiivne. Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktiivne. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akutase: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Vasak: aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Parem: aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivne"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvestatud"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivne, ainult vasak"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivne, ainult parem"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivne, vasak ja parem"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivne (ainult meedia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Toetab heli jagamist"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivne (ainult meedia), ainult vasak"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 0668fb2..91b9d20be 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gordeta"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, ezkerrekoa soilik"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, eskuinekoa soilik"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, ezkerreko eta eskuineko audifonoak"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 3c7f1f8..7ab13ba 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> شارژ باتری"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ذخیرهشده"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، فقط چپ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، فقط راست"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، چپ و راست"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index da80499..cafeb1b 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivinen"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Tallennettu"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivinen, vain vasen"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivinen, vain oikea"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivinen, vasen ja oikea"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6988384..0eab7c3 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connecté (aucun téléphone), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connecté (aucun média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connecté (aucun téléphone ni média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Actif. Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Actif. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Gauche : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Droite : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche seulement"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, droite seulement"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, gauche et droite"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actif (contenu multimédia uniquement)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Prise en charge du partage audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actif (contenu multimédia uniquement), côté gauche seulement"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 709477b..1928f32 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterie (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche uniquement"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actif, droit uniquement"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actifs, gauche et droit"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index e5c7f1e..d0f47a8 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Gardado"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo (só o esquerdo)"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo (só o dereito)"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activos (o esquerdo e o dereito)"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index d520536..ef53786 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન અથવા મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"સક્રિય. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"સક્રિય. ડાબી બાજુ: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ડાબી બાજુ: <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" msgid="5725764679536058365">"ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"સક્રિય"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"સાચવેલું"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"સક્રિય, માત્ર ડાબું"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"સક્રિય, માત્ર જમણું"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"સક્રિય, ડાબું અને જમણું બન્ને"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"સક્રિય છે (માત્ર મીડિયા માટે)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ઑડિયો શેરિંગને સપોર્ટ કરે છે"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"સક્રિય છે (માત્ર મીડિયા માટે), માત્ર ડાબી બાજુ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a81daf7..9499120 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -94,41 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"जुड़ गया (मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"जुड़ गया (फ़ोन या मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"चालू है. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"चालू है. बायां हेडसेट: <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_active_battery_level_untethered_left" msgid="2895644748625343977">"चालू है. बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"चालू है. दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"बायां हेडसेट: <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" msgid="5725764679536058365">"बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"चालू"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"सेव किया गया"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"सिर्फ़ बाईं तरफ़ वाला चालू है"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सिर्फ़ दाईं तरफ़ वाला चालू है"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"बाईं और दाईं तरफ़ वाला चालू है"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"सिर्फ़ बाईं तरफ़ वाला चालू है"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"सिर्फ़ दाईं तरफ़ वाला चालू है"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"बाईं और दाईं तरफ़ वाला चालू है"</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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"चालू है (सिर्फ़ मीडिया के लिए)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडियो शेयर करने की सुविधा काम करती है"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"चालू है (सिर्फ़ मीडिया के लिए), सिर्फ़ बाएं कान की मशीन"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 362393e..db2c318 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Spremljeno"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevo"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevo i desno"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index f251464..207e84a 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktív"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Mentve"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktív, csak bal"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktív, csak jobb"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktív, bal és jobb"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 4b6d727..1b8b236 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ակտիվ է"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Պահված է"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ակտիվ, միայն ձախ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ակտիվ, միայն աջ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ակտիվ, ձախ և աջ"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 1594d11..d9730b3 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, hanya kiri"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, hanya kanan"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index b85f453..60370f5 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Rafhlaða <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Virkt"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Vistað"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Virkt, aðeins vinstra"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Virkt, aðeins hægra"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Virkt, vinstra og hægra"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 08a2397..fbae08d 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Attivo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Dispositivo salvato"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Attiva, solo sinistra"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Attiva, solo destra"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Attivo, destra e sinistra"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 9ecf47b..5a6c751 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"סוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"פעיל"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"בוצעה שמירה"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"פועל: שמאל בלבד"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"פועל: ימין בלבד"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"פועל: ימין ושמאל"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index a51ba39..26bf76e 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"接続済み(電話なし)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"接続済み(メディアなし)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"接続済み(電話、メディアなし)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"有効。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"有効。左: バッテリー残量 <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"左: バッテリー残量 <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" msgid="5725764679536058365">"左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"有効"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"保存済み"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"有効、左のみ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"有効、右のみ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"有効、左と右"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"有効(メディアのみ)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"音声の共有をサポートしています"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"有効(メディアのみ)、左のみ"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index ba1dae0..266a557 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -94,41 +94,36 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"დაკავშირებულია (ტელეფონი არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"დაკავშირებულია (მედია არ არის). ბატარეა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"დაკავშირებულია (ტელეფონი ან მედია არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+ <!-- String.format failed for translation -->
<!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"აქტიური. მარცხენა: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"მარცხენა: <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" msgid="5725764679536058365">"მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"აქტიური"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"შენახული"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"აქტიური, მხოლოდ მარცხნივ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"აქტიური, მხოლოდ მარჯვნივ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"აქტიური, მარცხნივ და მარჯვნივ"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
+ <!-- String.format failed for translation -->
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"აქტიური (მხოლოდ მედია)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"აუდიოს გაზიარება მხარდაჭერილია"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"აქტიური (მხოლოდ მედია), მხოლოდ მარცხენა"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index b8f8fa3..eee0ac6 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Қосулы"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сақталған"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Тек сол жағы қосулы"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Тек оң жағы қосулы"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Екеуі де қосулы"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index d049fd4..2ba422b 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -94,41 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"បានភ្ជាប់ (គ្មានទូរសព្ទទេ) ហើយថ្មមានកម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"បានភ្ជាប់ (គ្មានមេឌៀទេ) ហើយថ្មមានកម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"បានភ្ជាប់ (គ្មានទូរសព្ទ ឬមេឌៀទេ) ហើយថ្មមានកម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"សកម្ម។ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"សកម្ម។ ឆ្វេង៖ ថ្ម <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_active_battery_level_untethered_left" msgid="2895644748625343977">"សកម្ម។ ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"សកម្ម។ ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ឆ្វេង៖ ថ្ម <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" msgid="5725764679536058365">"ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"សកម្ម"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"បានរក្សាទុក"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"សកម្ម ខាងឆ្វេងតែប៉ុណ្ណោះ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"សកម្មខាងស្ដាំតែប៉ុណ្ណោះ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"សកម្មខាងឆ្វេង និងស្ដាំ"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"សកម្ម (ខាងឆ្វេងប៉ុណ្ណោះ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"សកម្ម (ខាងស្ដាំប៉ុណ្ណោះ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"សកម្ម (ខាងឆ្វេង និងខាងស្ដាំ)"</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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"អាចប្រើការស្ដាប់សំឡេងរួមគ្នា"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) តែខាងឆ្វេងប៉ុណ្ណោះ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 70257de..64facff 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಇಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಮಾಧ್ಯಮವಿಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಅಥವಾ ಮಾಧ್ಯಮವಿಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ಸಕ್ರಿಯವಾಗಿದೆ. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ಸಕ್ರಿಯವಾಗಿದೆ. ಎಡ: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಇದೆ"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ಎಡ: <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" msgid="5725764679536058365">"ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ಸಕ್ರಿಯ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ಎಡಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ಬಲಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ಎಡ ಮತ್ತು ಬಲಕಿವಿಯ ಸಾಧನಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಎಡ ಭಾಗದ ಮಾತ್ರ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 9ced8a0..b6988ce 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"활성"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"저장됨"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"활성, 왼쪽만"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"활성, 오른쪽만"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"활성, 왼쪽 및 오른쪽"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 7be7f38..d084a9bf 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батареянын кубаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Жигердүү"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сакталган"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Иштеп жатат, сол кулак гана"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Жигердүү, оң кулакчын гана"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Жигердүү, сол жана оң кулакчын"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index c6a5bd4..cb0c5da 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -94,41 +94,27 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ ຫຼື ມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ນຳໃຊ້ຢູ່. ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ນຳໃຊ້ຢູ່. ຊ: ແບັດເຕີຣີ <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_active_battery_level_untethered_left" msgid="2895644748625343977">"ນຳໃຊ້ຢູ່. ຊ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"ນຳໃຊ້ຢູ່. ຂ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ຊ: ແບັດເຕີຣີ <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" msgid="5725764679536058365">"ຊ້າຍ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"ຂວາ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ອອນລາຍ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ບັນທຶກແລ້ວ"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ນຳໃຊ້ຢູ່, ຊ້າຍເທົ່ານັ້ນ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ນຳໃຊ້ຢູ່, ຂວາເທົ່ານັ້ນ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ນຳໃຊ້ຢູ່, ຊ້າຍ ແລະ ຂວາ"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
- <skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ນຳໃຊ້ຢູ່ (ຊ້າຍເທົ່ານັ້ນ)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ນຳໃຊ້ຢູ່ (ຂວາເທົ່ານັ້ນ)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ນຳໃຊ້ຢູ່ (ຊ້າຍ ແລະ ຂວາ)"</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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ຮອງຮັບການແບ່ງປັນສຽງ"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ້າຍເທົ່ານັ້ນ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 94b8173..0d97309 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (telefono nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (medijos nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (telefono ar medijos nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktyvus. Akumuliatorius lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktyvus. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumuliatoriaus įkrova: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumuliatorius: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Akumuliatoriaus lygis dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktyvus"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Išsaugota"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktyvus, tik kairysis"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktyvus, tik dešinysis"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktyvus, kairysis ir dešinysis"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktyvus (tik medija)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Palaikomas garso įrašų bendrinimas"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktyvus (tik medija), tik kairė"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index ff1f3f3..55fa4d3 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktīvs"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saglabāta"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ierīce aktīva, tikai kreisā auss"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ierīce aktīva, tikai labā auss"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ierīces aktīvas, kreisā un labā auss"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index c5b4a5e..6d3d54c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активен"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Зачувано"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само лево"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, само десно"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, лево и десно"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 0ba9122..3da1218 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"കണക്റ്റ് ചെയ്തു (ഫോൺ ഇല്ല), ബാറ്ററി നില <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"കണക്റ്റ് ചെയ്തു (മീഡിയ ഇല്ല), ബാറ്ററി <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"കണക്റ്റ് ചെയ്തു (ഫോണോ മീഡിയയോ ഇല്ല), ബാറ്ററി നില <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"സജീവം. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"സജീവം. ഇടതുവശത്ത്: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ബാറ്ററി ചാർജ് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ആണ്"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ഇടതുവശത്ത്: <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" msgid="5725764679536058365">"ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"വലത് വശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"സജീവം"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"സംരക്ഷിച്ചു"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"സജീവമാണ്, ഇടത്തേത് മാത്രം"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"സജീവമാണ്, വലത്തേത് മാത്രം"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"സജീവമാണ്, ഇടത്തേതും വലത്തേതും"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"സജീവം (മീഡിയ മാത്രം)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്ത് മാത്രം"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index c431857..c39717c 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Идэвхтэй"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Хадгалсан"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Идэвхтэй, зөвхөн зүүн тал"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Идэвхтэй, зөвхөн баруун тал"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Идэвхтэй, зүүн болон баруун тал"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a916a1c..549c784 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"कनेक्ट केले (फोन नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"कनेक्ट केले (मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"कनेक्ट केले (फोन किंवा मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ॲक्टिव्ह आहे. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ॲक्टिव्ह आहे. डावीकडे: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"डावीकडे: <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" msgid="5725764679536058365">"डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"अॅक्टिव्ह"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"सेव्ह केली आहेत"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"फक्त डावे अॅक्टिव्ह आहे"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"फक्त उजवे अॅक्टिव्ह आहे"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"डावे आणि उजवे अॅक्टिव्ह आहे"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"अॅक्टिव्ह आहे (फक्त मीडिया)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडिओ शेअरिंगला सपोर्ट करते"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"अॅक्टिव्ह आहे (फक्त मीडिया), फक्त डावे"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index f86206c..e621643 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Disambungkan (tiada telefon), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Disambungkan (tiada media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Disambungkan (tiada telefon atau media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktif. Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktif. L: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <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" msgid="5725764679536058365">"Kiri: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Kanan: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, kiri sahaja"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, kanan sahaja"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (media sahaja)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Menyokong perkongsian audio"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (media sahaja), kiri sahaja"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 2dde99f..f4ee284 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -98,10 +98,8 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"သုံးနေသည်။ ဘယ်ဘက်- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"သုံးနေသည်။ ညာဘက်- ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
@@ -112,9 +110,9 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ဖွင့်ထားသည်"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"သိမ်းထားသည်များ"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ဖွင့်ထားသည်၊ ဘယ်သီးသန့်"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ဖွင့်ထားသည်၊ ညာသီးသန့်"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ဖွင့်ထားသည်၊ ဘယ်နှင့် ညာ"</string>
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"သုံးနေသည် (ဘယ်ဘက်သီးသန့်)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"သုံးနေသည် (ညာဘက်သီးသန့်)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"သုံးနေသည် (ဘယ်နှင့်ညာ)"</string>
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d2021ba..d7814eb 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Lagret"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bare venstre"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bare høyre"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og høyre"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d01fc16..abe48e9 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"जडान गरियो (फोनबाहेेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"जडान गरियो (मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"जडान गरियो (फोन वा मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"सक्रिय। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"सक्रिय। बायाँ: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"बायाँ: <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" msgid="5725764679536058365">"बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"सक्रिय"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"सेभ गरिएको"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"बायाँ मात्र अन छ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सक्रिय, दायाँ मात्र"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"सक्रिय, बायाँ र दायाँ"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"सक्रिय छ (मिडिया मात्र)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"अडियो सेयर गर्न मिल्छ"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"सक्रिय छ (मिडिया मात्र), बायाँ मात्र"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 6394cb6..3f2e003 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actief"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Opgeslagen"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actief, alleen links"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actief, alleen rechts"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actief, links en rechts"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index eb31f96..b233b544 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ବେଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ସକ୍ରିୟ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ସେଭ କରାଯାଇଛି"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ସକ୍ରିୟ, କେବଳ ବାମ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ସକ୍ରିୟ, କେବଳ ଡାହାଣ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ସକ୍ରିୟ, ବାମ ଏବଂ ଡାହାଣ"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
@@ -195,7 +198,7 @@
<string name="accessibility_wifi_security_type_secured" msgid="2399774097343238942">"ସୁରକ୍ଷିତ ନେଟ୍ୱର୍କ"</string>
<string name="process_kernel_label" msgid="950292573930336765">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"କଢ଼ାଯାଇଥିବା ଆପ୍ଗୁଡ଼ିକ"</string>
- <string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"ଆପ୍ ଏବଂ ଉପଯୋଗକର୍ତ୍ତା ବାହାର କରାଗଲା"</string>
+ <string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"ଆପ୍ସ ଏବଂ ୟୁଜରଙ୍କୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
<string name="data_usage_ota" msgid="7984667793701597001">"ସିଷ୍ଟମ୍ ଅପ୍ଡେଟ୍"</string>
<string name="tether_settings_title_usb" msgid="3728686573430917722">"USB ଟିଥରିଂ"</string>
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"ପୋର୍ଟବଲ୍ ହଟସ୍ପଟ୍"</string>
@@ -204,7 +207,7 @@
<string name="tether_settings_title_all" msgid="8910259483383010470">"ଟିଥରିଙ୍ଗ ଓ ପୋର୍ଟବଲ୍ ହଟ୍ସ୍ପଟ୍"</string>
<string name="managed_user_title" msgid="449081789742645723">"ସମସ୍ତ କାର୍ଯ୍ୟ ଆପ୍"</string>
<string name="unknown" msgid="3544487229740637809">"ଅଜଣା"</string>
- <string name="running_process_item_user_label" msgid="3988506293099805796">"ଉପଯୋଗକର୍ତ୍ତା: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
+ <string name="running_process_item_user_label" msgid="3988506293099805796">"ୟୁଜର: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="3631650616557252926">"କିଛି ପୂର୍ବ-ନିର୍ଦ୍ଧାରିତ ମାନ ସେଟ୍ ହୋଇଛି"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"କୌଣସି ଡିଫଲ୍ଟ ସେଟ୍ ହୋଇନାହିଁ"</string>
<string name="tts_settings" msgid="8130616705989351312">"ଟେକ୍ସଟ୍-ଟୁ-ସ୍ପିଚ୍ ସେଟିଂସ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 64c4e96..73fe924 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ਕਿਰਿਆਸ਼ੀਲ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਖੱਬਾ"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਸੱਜਾ"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ਕਿਰਿਆਸ਼ੀਲ, ਖੱਬਾ ਅਤੇ ਸੱਜਾ"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index d4d27e1..6907102 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Połączono (bez telefonu), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Połączono (bez multimediów), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Połączono (bez telefonu i multimediów), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktywne. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktywne. Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> naładowania baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> naładowania baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Urządzenie aktywne"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Zapisano"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktywne, tylko lewa strona"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktywne, tylko prawa strona"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktywny, lewa i prawa strona"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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> baterii, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string>
+ <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> naładowania baterii, 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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktywne (tylko multimedia)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Obsługa udostępniania dźwięku"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktywne (tylko multimedia), tylko lewa"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 38df760..5bc01f1 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 9e98623..671c9f7 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -98,10 +98,8 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Ativo. E: bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Ativo. D: bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
@@ -112,9 +110,9 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas esquerdo"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas direito"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ativo (apenas esquerdo)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ativo (apenas direito)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ativo (esquerdo e direito)"</string>
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 38df760..5bc01f1 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index dddc116..4d6638a 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activ"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvat"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activ, numai stânga"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activ, numai dreapta"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activ, stânga și dreapta"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 9a5a400..e155948 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Уровень заряда: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сохранено"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активен, только левое ухо"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активен, только правое ухо"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активен, оба уха"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0fce42b..0c494e4 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"සම්බන්ධිතයි (දුරකථනය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"සම්බන්ධිතයි (මාධ්ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"සම්බන්ධිතයි (දුරකථනය හෝ මාධ්ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"ක්රියාත්මකයි. බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"ක්රියාත්මකයි. බැටරිය ව: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"බැටරිය ව: <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" msgid="5725764679536058365">"වම: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"දකුණ: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ක්රියාකාරී"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"සුරැකිණි"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"සක්රිය, වම පමණි"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"සක්රිය, දකුණ පමණි"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"සක්රිය, වම සහ දකුණ"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"සක්රිය (මාධ්ය පමණි)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ශ්රව්ය බෙදා ගැනීම සහය දක්වයි"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"සක්රිය (මාධ්ය පමණි), වම පමණි"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 74c9e1f..fe41beb 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefónu), úroveň batérie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez médií), úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefónu a médií), úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktívne. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktívne. Ľ: <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>
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"Ľ: <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" msgid="5725764679536058365">"Ľavá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Pravá strana: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktívne"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Uložené"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktívne, iba ľavá strana"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktívne, iba pravá strana"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktívne, ľavá aj pravá strana"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktívne (iba médiá)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje zdieľanie zvuku"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktívne (iba médiá), iba ľavá strana"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index a6d35c80..32b6d21 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (brez telefona), raven napolnjenosti baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (brez predstavnosti), raven napolnjenosti baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (brez telefona ali predstavnosti), raven napolnjenosti baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktivno. Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktivno. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Levo – baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Desno – baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivna"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Shranjeno"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo levo"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, levo in desno"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo predstavnost)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podpira deljenje zvoka"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo predstavnost), samo levo"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 3f6e803..f112060 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Të ruajtura"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktive, vetëm majtas"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktive, vetëm djathtas"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktive, majtas dhe djathtas"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 135176b..9341616 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активан"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Сачувано"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само с леве стране"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, с десне стране"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, с леве и десне стране"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 7712203..d3370e8 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Sparad"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bara vänster"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bara höger"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, vänster och höger"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 53d583a..f1d2207 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -98,10 +98,8 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
- <skip />
+ <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Inatumika. Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Inatumika. Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
@@ -112,9 +110,9 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Kimeunganishwa"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Imeokoa"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Inatumika, kushoto pekee"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Inatumika, kulia pekee"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Inatumika, kushoto na kulia"</string>
+ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Inatumika (kushoto pekee)"</string>
+ <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Inatumika (kulia pekee)"</string>
+ <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Inatumika (kushoto na kulia)"</string>
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index db11263..8097be0 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"செயலில் உள்ளது"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"சேமிக்கப்பட்டது"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"இடது பக்கம் மட்டும் செயலில் உள்ளது"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"வலது பக்கம் மட்டும் செயலில் உள்ளது"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"வலது மற்றும் இடது பக்கம் செயலில் உள்ளது"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c2faca9..fbedf33 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"కనెక్ట్ చేయబడింది (మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"యాక్టివ్గా ఉంది. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"యాక్టివ్గా ఉంది. ఎడమ వైపు: <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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"ఎడమ వైపు: <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" msgid="5725764679536058365">"ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"కుడి వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"యాక్టివ్గా ఉంది"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"సేవ్ చేయబడింది"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"యాక్టివ్గా ఉంది, ఎడమవైపు మాత్రమే యాక్టివ్గా ఉంది"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"యాక్టివ్గా ఉంది, కుడివైపు యాక్టివ్గా ఉంది"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"యాక్టివ్గా ఉంది, ఎడమవైపు, కుడివైపు యాక్టివ్గా ఉంది"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"యాక్టివ్ (మీడియా మాత్రమే)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ వైపు మాత్రమే"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 7b03f81..8f59f36 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ใช้งานอยู่"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"บันทึกแล้ว"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ใช้งานอยู่ เฉพาะข้างซ้าย"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ใช้งานอยู่ เฉพาะข้างขวา"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ใช้งานอยู่ ข้างซ้ายและขวา"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8eef17e..58b6e84 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Na-save"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, kaliwa lang"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, kanan lang"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, kaliwa at kanan"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index cf5bd2d..0300ddc 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Etkin"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Kaydedildi"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Yalnızca sol tarafta etkin"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Yalnızca sağ tarafta etkin"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Sol ve sağ tarafta etkin"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 4b40503..807bc51 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Заряд акумулятора: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активовано"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Збережено"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активовано, лише лівий"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активовано, лише правий"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активовано, лівий і правий"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index a1b2198..8084162 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"منسلک ہے (فون کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"منسلک ہے (میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"منسلک ہے (فون یا میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"فعال۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"فعال۔ 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"بائيں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"دائيں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ ہے"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، صرف بائیں طرف"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، صرف دائیں طرف"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، صرف بائیں اور دائیں طرف"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (صرف میڈیا)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"آڈیو کے اشتراک کو سپورٹ کرتا ہے"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (صرف میڈیا)، صرف بائیں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 82f4576..4415667 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Faol"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Saqlangan"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Faol, faqat chap"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Faol, faqat oʻng"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Faol, chap va oʻng"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 9a1386e..f33d909 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Đang hoạt động"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Đã lưu"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Đang hoạt động, chỉ tai bên trái"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Đang hoạt động, chỉ tai phải"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Đang hoạt động, cả tai phải và tai trái"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index d3f8945..816ba8d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 的电量"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"电池电量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"已保存的设备"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,仅左耳助听器"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,仅右耳助听器"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳助听器"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index b5a1d51..b26efb2 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index a131c12..149022c 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -98,9 +98,9 @@
<skip />
<!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
<skip />
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string>
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+ <skip />
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+ <skip />
<!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
<skip />
<!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f9bdfbf..8448814 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -94,41 +94,32 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ixhunyiwe (ayikho ifoni), ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ixhunyiwe (ayikho imidiya), ibhethri iku-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ixhunyiwe (ayikho ifoni noma imidiya), ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+ <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Iyasebenza. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string>
+ <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Iyasebenza. 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_active_battery_level_untethered_left (2895644748625343977) -->
<skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
- <skip />
- <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+ <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
<skip />
<string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
<string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Ibhethri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
- <skip />
+ <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"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" msgid="5725764679536058365">"Kwesobunxele: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
+ <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Kwesokudla: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Iyasebenza"</string>
<string name="bluetooth_saved_device" msgid="4895871321722311428">"Ilondoloziwe"</string>
- <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Iyasebenza, ngakwesokunxele kuphela"</string>
- <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Iyasebenza, ngakwesokudla kuphela"</string>
- <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Iyasebenza, ngakwesokunxele nakwesokudla"</string>
- <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
<skip />
- <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+ <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+ <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
<skip />
- <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
- <skip />
- <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
- <skip />
+ <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>
+ <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>
<string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Kuyasebenza (imidiya kuphela)"</string>
<string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Isekela ukwabelana ngokuqoshiwe"</string>
<string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Iyasebenza (imidiya kuphela), ngakwesokunxele kuphela"</string>
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 45253bb..68b81db 100644
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -22,6 +22,9 @@
<!-- Threshold in micro watts above which a charger is rated as "fast"; 1.5A @ 5V -->
<integer name="config_chargingFastThreshold">7500000</integer>
+ <!-- Threshold in micro watts above which a charger is rated as "fast"; 20W -->
+ <integer name="config_chargingFastThreshold_v2">20000000</integer>
+
<!-- When true, show 1/2G networks as 3G. -->
<bool name="config_showMin3G">false</bool>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 1515811..adbfc72 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1745,4 +1745,7 @@
<string name="feminine">Feminine</string>
<!-- List entry in developer settings to set the grammatical gender to Masculine [CHAR LIMIT=30]-->
<string name="masculine">Masculine</string>
+
+ <!-- The name of the screen for seeing and installing system updates. [CHAR LIMIT=40]-->
+ <string name="system_update_settings_list_item_title">System Updates</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index fa27db9..dc40304 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -202,8 +202,8 @@
dreamInfo.componentName = componentName;
dreamInfo.isActive = dreamInfo.componentName.equals(activeDream);
- final DreamService.DreamMetadata dreamMetadata = DreamService.getDreamMetadata(mContext,
- resolveInfo.serviceInfo);
+ final DreamService.DreamMetadata dreamMetadata = DreamService.getDreamMetadata(
+ mContext.getPackageManager(), resolveInfo.serviceInfo);
if (dreamMetadata != null) {
dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
dreamInfo.previewImage = dreamMetadata.previewImage;
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
index 2032328..f659e38 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
@@ -145,7 +145,8 @@
final int slowThreshold = context.getResources().getInteger(
R.integer.config_chargingSlowlyThreshold);
final int fastThreshold = context.getResources().getInteger(
- R.integer.config_chargingFastThreshold);
+ getFastChargingThresholdResId());
+
return maxChargingWattage <= 0 ? CHARGING_UNKNOWN :
maxChargingWattage < slowThreshold ? CHARGING_SLOWLY :
maxChargingWattage > fastThreshold ? CHARGING_FAST :
@@ -382,7 +383,7 @@
< context.getResources().getInteger(R.integer.config_chargingSlowlyThreshold)) {
return CHARGING_SLOWLY;
} else if (maxChargingMicroWatt
- > context.getResources().getInteger(R.integer.config_chargingFastThreshold)) {
+ > context.getResources().getInteger(getFastChargingThresholdResId())) {
return CHARGING_FAST;
} else {
return CHARGING_REGULAR;
@@ -410,4 +411,10 @@
return -1;
}
}
+
+ private static int getFastChargingThresholdResId() {
+ return BatteryUtils.isChargingStringV2Enabled()
+ ? R.integer.config_chargingFastThreshold_v2
+ : R.integer.config_chargingFastThreshold;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
index 327e470..ca3af53 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
@@ -27,6 +27,7 @@
import android.util.ArraySet;
import android.view.accessibility.AccessibilityManager;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.util.List;
@@ -97,9 +98,18 @@
/** Used to override the system property to enable or reset for charging string V2. */
@VisibleForTesting
public static void setChargingStringV2Enabled(Boolean enabled) {
- SystemProperties.set(
- BatteryUtils.PROPERTY_CHARGING_STRING_V2_KEY,
- enabled == null ? "" : String.valueOf(enabled));
+ setChargingStringV2Enabled(enabled, true /* updateProperty */);
+ }
+
+ /** Used to override the system property to enable or reset for charging string V2. */
+ @VisibleForTesting
+ public static void setChargingStringV2Enabled(
+ @Nullable Boolean enabled, boolean updateProperty) {
+ if (updateProperty) {
+ SystemProperties.set(
+ BatteryUtils.PROPERTY_CHARGING_STRING_V2_KEY,
+ enabled == null ? "" : String.valueOf(enabled));
+ }
BatteryUtils.sChargingStringV2Enabled = enabled;
}
}
diff --git a/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt b/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt
index 6c0c1a7..4940610 100644
--- a/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt
+++ b/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt
@@ -38,6 +38,7 @@
import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_SLOWLY
import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_UNKNOWN
import com.android.settingslib.fuelgauge.BatteryStatus.isBatteryDefender
+import com.android.settingslib.fuelgauge.BatteryUtils
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import java.util.Optional
@@ -253,12 +254,17 @@
private val maxChargingCurrent: Optional<Int>,
private val maxChargingVoltage: Optional<Int>,
private val expectedChargingSpeed: Int,
+ private val chargingStringV2Enabled: Boolean,
) {
val context: Context = ApplicationProvider.getApplicationContext()
@Test
fun getChargingSpeed_() {
+ BatteryUtils.setChargingStringV2Enabled(
+ chargingStringV2Enabled,
+ false /* updateProperty */
+ )
val batteryChangedIntent =
Intent(Intent.ACTION_BATTERY_CHANGED).apply {
maxChargingCurrent.ifPresent { putExtra(EXTRA_MAX_CHARGING_CURRENT, it) }
@@ -278,37 +284,57 @@
"maxCurrent=n/a, maxVoltage=n/a -> UNKNOWN",
Optional.empty<Int>(),
Optional.empty<Int>(),
- CHARGING_UNKNOWN
+ CHARGING_UNKNOWN,
+ false /* chargingStringV2Enabled */
),
arrayOf(
"maxCurrent=0, maxVoltage=9000000 -> UNKNOWN",
Optional.of(0),
Optional.of(0),
- CHARGING_UNKNOWN
+ CHARGING_UNKNOWN,
+ false /* chargingStringV2Enabled */
),
arrayOf(
"maxCurrent=1500000, maxVoltage=5000000 -> CHARGING_REGULAR",
Optional.of(1500000),
Optional.of(5000000),
- CHARGING_REGULAR
+ CHARGING_REGULAR,
+ false /* chargingStringV2Enabled */
),
arrayOf(
"maxCurrent=1000000, maxVoltage=5000000 -> CHARGING_REGULAR",
Optional.of(1000000),
Optional.of(5000000),
- CHARGING_REGULAR
+ CHARGING_REGULAR,
+ false /* chargingStringV2Enabled */
),
arrayOf(
"maxCurrent=1500001, maxVoltage=5000000 -> CHARGING_FAST",
Optional.of(1501000),
Optional.of(5000000),
- CHARGING_FAST
+ CHARGING_FAST,
+ false /* chargingStringV2Enabled */
),
arrayOf(
"maxCurrent=999999, maxVoltage=5000000 -> CHARGING_SLOWLY",
Optional.of(999999),
Optional.of(5000000),
- CHARGING_SLOWLY
+ CHARGING_SLOWLY,
+ false /* chargingStringV2Enabled */
+ ),
+ arrayOf(
+ "maxCurrent=3000000, maxVoltage=9000000 -> CHARGING_FAST",
+ Optional.of(3000000),
+ Optional.of(9000000),
+ CHARGING_FAST,
+ true /* chargingStringV2Enabled */
+ ),
+ arrayOf(
+ "maxCurrent=2200000, maxVoltage=9000000 -> CHARGING_REGULAR",
+ Optional.of(2200000),
+ Optional.of(9000000),
+ CHARGING_REGULAR,
+ true /* chargingStringV2Enabled */
),
)
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 9d02074..be3f410 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -272,7 +272,7 @@
Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
Settings.Secure.AUDIO_DEVICE_INVENTORY,
Settings.Secure.SCREEN_RESOLUTION_MODE,
- Settings.Secure.ACCESSIBILITY_FLOATING_MENU_TARGETS,
+ Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS,
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_SATURATION_LEVEL,
Settings.Secure.CHARGE_OPTIMIZATION_MODE
};
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 6cb9d50..b1feede 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -326,7 +326,7 @@
Secure.ACCESSIBILITY_BUTTON_TARGETS,
ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
VALIDATORS.put(
- Secure.ACCESSIBILITY_FLOATING_MENU_TARGETS,
+ Secure.ACCESSIBILITY_GESTURE_TARGETS,
ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
VALIDATORS.put(
Secure.ACCESSIBILITY_QS_TARGETS,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 9e9350b..2e9075c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -186,9 +186,14 @@
sendBroadcast = sBroadcastOnRestore.contains(name);
sendBroadcastSystemUI = sBroadcastOnRestoreSystemUI.contains(name);
- if (sendBroadcast || sendBroadcastSystemUI) {
+ if (sendBroadcast) {
// TODO: http://b/22388012
oldValue = table.lookup(cr, name, UserHandle.USER_SYSTEM);
+ } else if (sendBroadcastSystemUI) {
+ // This is only done for broadcasts sent to system ui as the consumers are known.
+ // It would probably be correct to do it for the ones sent to the system, but consumers
+ // may be depending on the current behavior.
+ oldValue = table.lookup(cr, name, context.getUserId());
}
try {
@@ -266,7 +271,7 @@
if (sendBroadcastSystemUI) {
intent.setPackage(
context.getString(com.android.internal.R.string.config_systemUi));
- context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null);
+ context.sendBroadcastAsUser(intent, context.getUser(), null);
}
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 52e9b6d5..461b6b3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1841,8 +1841,8 @@
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
SecureSettingsProto.Accessibility.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED);
dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_FLOATING_MENU_TARGETS,
- SecureSettingsProto.Accessibility.ACCESSIBILITY_FLOATING_MENU_TARGETS);
+ Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS,
+ SecureSettingsProto.Accessibility.ACCESSIBILITY_GESTURE_TARGETS);
dumpSetting(s, p,
Settings.Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED,
SecureSettingsProto.Accessibility.ODI_CAPTIONS_VOLUME_UI_ENABLED);
diff --git a/packages/Shell/Android.bp b/packages/Shell/Android.bp
index c87916f..2531454 100644
--- a/packages/Shell/Android.bp
+++ b/packages/Shell/Android.bp
@@ -19,6 +19,9 @@
include_dirs: ["frameworks/native/cmds/dumpstate/binder"],
},
static_libs: shell_static_libs,
+ libs: [
+ "device_policy_aconfig_flags_lib",
+ ],
platform_apis: true,
certificate: "platform",
privileged: true,
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 5ac0e44..bcfd8f6 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -16,6 +16,7 @@
package com.android.shell;
+import static android.app.admin.flags.Flags.onboardingBugreportStorageBugFix;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
@@ -89,10 +90,10 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.google.android.collect.Lists;
-
import libcore.io.Streams;
+import com.google.android.collect.Lists;
+
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -109,6 +110,8 @@
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@@ -442,10 +445,14 @@
}
}
- private static void sendRemoteBugreportFinishedBroadcast(Context context,
+ private void sendRemoteBugreportFinishedBroadcast(Context context,
String bugreportFileName, File bugreportFile, long nonce) {
- cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE,
- bugreportFile.getParentFile());
+ // Remote bugreports are stored in the same directory as normal bugreports, meaning that
+ // the remote bugreport storage limit will get applied to normal bugreports whenever a
+ // remote bugreport is triggered. The fix in cleanupOldFiles applies the normal bugreport
+ // limit to the remote bugreports as a quick fix.
+ cleanupOldFiles(
+ REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE, bugreportFile.getParentFile());
final Intent intent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
final Uri bugreportUri = getUri(context, bugreportFile);
final String bugreportHash = generateFileHash(bugreportFileName);
@@ -496,12 +503,16 @@
return fileHash;
}
- static void cleanupOldFiles(final int minCount, final long minAge, File bugreportsDir) {
+ void cleanupOldFiles(final int minCount, final long minAge, File bugreportsDir) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
- FileUtils.deleteOlderFiles(bugreportsDir, minCount, minAge);
+ if (onboardingBugreportStorageBugFix()) {
+ cleanupOldBugreports();
+ } else {
+ FileUtils.deleteOlderFiles(bugreportsDir, minCount, minAge);
+ }
} catch (RuntimeException e) {
Log.e(TAG, "RuntimeException deleting old files", e);
}
@@ -510,6 +521,42 @@
}.execute();
}
+ private void cleanupOldBugreports() {
+ final File[] files = mBugreportsDir.listFiles();
+ if (files == null) return;
+
+ // Sort with newest files first
+ Arrays.sort(files, new Comparator<File>() {
+ @Override
+ public int compare(File lhs, File rhs) {
+ return Long.compare(rhs.lastModified(), lhs.lastModified());
+ }
+ });
+
+ int normalBugreportFilesCount = 0;
+ int deferredBugreportFilesCount = 0;
+ for (int i = 0; i < files.length; i++) {
+ final File file = files[i];
+
+ // tmp files are deferred bugreports which have their separate storage limit
+ boolean isDeferredBugreportFile = file.getName().endsWith(".tmp");
+ if (isDeferredBugreportFile) {
+ deferredBugreportFilesCount++;
+ } else {
+ normalBugreportFilesCount++;
+ }
+ // Keep files newer than minAgeMs
+ final long age = System.currentTimeMillis() - file.lastModified();
+ final int count = isDeferredBugreportFile
+ ? deferredBugreportFilesCount : normalBugreportFilesCount;
+ if (count > MIN_KEEP_COUNT && age > MIN_KEEP_AGE) {
+ if (file.delete()) {
+ Log.d(TAG, "Deleted old file " + file);
+ }
+ }
+ }
+ }
+
/**
* Main thread used to handle all requests but taking screenshots.
*/
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 5cc3caf..59e2b91 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -906,14 +906,6 @@
android:exported="true"
/>
- <activity
- android:name=".volume.panel.ui.activity.VolumePanelActivity"
- android:label="@string/accessibility_volume_settings"
- android:excludeFromRecents="true"
- android:exported="false"
- android:launchMode="singleInstance"
- android:theme="@style/Theme.VolumePanelActivity" />
-
<activity android:name=".wallet.ui.WalletActivity"
android:label="@string/wallet_title"
android:theme="@style/Wallet.Theme"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml
index 749a6f2..199b0c9 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml
@@ -9,7 +9,7 @@
<string name="power_label" msgid="7699720321491287839">"Napajanje"</string>
<string name="power_utterance" msgid="7444296686402104807">"Opcije napajanja"</string>
<string name="recent_apps_label" msgid="6583276995616385847">"Nedavne aplikacije"</string>
- <string name="lockscreen_label" msgid="648347953557887087">"Zaključavanje ekrana"</string>
+ <string name="lockscreen_label" msgid="648347953557887087">"Zaključani ekran"</string>
<string name="quick_settings_label" msgid="2999117381487601865">"Brze postavke"</string>
<string name="notifications_label" msgid="6829741046963013567">"Obavještenja"</string>
<string name="screenshot_label" msgid="863978141223970162">"Snimak ekrana"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
index 64dcf6e..395354e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
@@ -34,6 +34,7 @@
"compatibility-device-util-axt",
"platform-test-annotations",
"truth",
+ "uiautomator-helpers",
],
srcs: [
"src/**/*.java",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
index 0ab99fa..66943d4 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
@@ -30,6 +30,8 @@
import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_TOGGLE_MENU;
import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.PACKAGE_NAME;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Instrumentation;
import android.app.KeyguardManager;
@@ -43,6 +45,8 @@
import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.os.PowerManager;
+import android.os.RemoteException;
+import android.platform.uiautomator_helpers.WaitUtils;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
@@ -51,6 +55,8 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.Configurator;
+import androidx.test.uiautomator.UiDevice;
import com.android.compatibility.common.util.TestUtils;
import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut.ShortcutId;
@@ -60,7 +66,6 @@
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -76,11 +81,13 @@
private static final int TIMEOUT_SERVICE_STATUS_CHANGE_S = 5;
private static final int TIMEOUT_UI_CHANGE_S = 5;
private static final int NO_GLOBAL_ACTION = -1;
- private static final Intent INTENT_OPEN_MENU = new Intent(INTENT_TOGGLE_MENU)
- .setPackage(PACKAGE_NAME);
+ private static final Intent INTENT_OPEN_MENU =
+ new Intent(INTENT_TOGGLE_MENU).setPackage(PACKAGE_NAME);
+ private static final String SERVICE_NAME = PACKAGE_NAME + "/.AccessibilityMenuService";
private static Instrumentation sInstrumentation;
private static UiAutomation sUiAutomation;
+ private static UiDevice sUiDevice;
private static final AtomicInteger sLastGlobalAction = new AtomicInteger(NO_GLOBAL_ACTION);
private static final AtomicBoolean sOpenBlocked = new AtomicBoolean(false);
@@ -91,12 +98,14 @@
@BeforeClass
public static void classSetup() throws Throwable {
- final String serviceName = PACKAGE_NAME + "/.AccessibilityMenuService";
+ Configurator.getInstance()
+ .setUiAutomationFlags(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
sInstrumentation = InstrumentationRegistry.getInstrumentation();
sUiAutomation = sInstrumentation.getUiAutomation(
UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
sUiAutomation.adoptShellPermissionIdentity(
UiAutomation.ALL_PERMISSIONS.toArray(new String[0]));
+ sUiDevice = UiDevice.getInstance(sInstrumentation);
final Context context = sInstrumentation.getTargetContext();
sAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -117,13 +126,13 @@
// Enable a11yMenu service.
Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, serviceName);
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, SERVICE_NAME);
TestUtils.waitUntil("Failed to enable service",
TIMEOUT_SERVICE_STATUS_CHANGE_S,
() -> sAccessibilityManager.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK).stream().filter(
- info -> info.getId().contains(serviceName)).count() == 1);
+ info -> info.getId().contains(SERVICE_NAME)).count() == 1);
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -159,8 +168,11 @@
public void tearDown() throws Throwable {
closeMenu();
sLastGlobalAction.set(NO_GLOBAL_ACTION);
+ // Leave the device in clean state when the test finished
+ unlockSignal();
// dismisses screenshot popup if present.
- sUiAutomation.executeShellCommand("input keyevent KEYCODE_BACK");
+ sUiDevice.pressBack();
+ sUiDevice.pressHome();
}
private static boolean isMenuVisible() {
@@ -168,38 +180,25 @@
return root != null && root.getPackageName().toString().equals(PACKAGE_NAME);
}
- private static void wakeUpScreen() throws Throwable {
- sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP");
- TestUtils.waitUntil("Screen did not wake up.",
- TIMEOUT_UI_CHANGE_S,
- () -> sPowerManager.isInteractive());
+ private static void wakeUpScreen() throws RemoteException {
+ sUiDevice.wakeUp();
+ WaitUtils.waitForValueToSettle("Screen On", AccessibilityMenuServiceTest::isScreenOn);
+ assertWithMessage("Screen is on").that(isScreenOn()).isTrue();
}
private static void closeScreen() throws Throwable {
- Display display = sDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
sUiAutomation.performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN);
- TestUtils.waitUntil("Screen did not close.",
- TIMEOUT_UI_CHANGE_S,
- () -> !sPowerManager.isInteractive()
- && display.getState() == Display.STATE_OFF
- );
+ WaitUtils.waitForValueToSettle("Screen Off", AccessibilityMenuServiceTest::isScreenOff);
+ assertWithMessage("Screen is off").that(isScreenOff()).isTrue();
}
private static void openMenu() throws Throwable {
unlockSignal();
- sInstrumentation.getContext().sendBroadcast(INTENT_OPEN_MENU);
-
- TestUtils.waitUntil("Timed out before menu could appear.",
- TIMEOUT_UI_CHANGE_S,
- () -> {
- if (isMenuVisible()) {
- return true;
- } else {
- unlockSignal();
- sInstrumentation.getContext().sendBroadcast(INTENT_OPEN_MENU);
- return false;
- }
- });
+ if (!isMenuVisible()) {
+ sInstrumentation.getTargetContext().sendBroadcast(INTENT_OPEN_MENU);
+ sUiDevice.waitForIdle();
+ WaitUtils.ensureThat("Accessibility Menu is visible", () -> isMenuVisible());
+ }
}
private static void closeMenu() throws Throwable {
@@ -342,7 +341,9 @@
sUiAutomation.executeAndWaitForEvent(
() -> assistantButton.performAction(CLICK_ID),
- (event) -> expectedPackage.contains(event.getPackageName()),
+ (event) ->
+ event.getPackageName() != null
+ && expectedPackage.contains(event.getPackageName()),
TIMEOUT_UI_CHANGE_S * 1000
);
}
@@ -358,7 +359,9 @@
sUiAutomation.executeAndWaitForEvent(
() -> settingsButton.performAction(CLICK_ID),
- (event) -> expectedPackage.contains(event.getPackageName()),
+ (event) ->
+ event.getPackageName() != null
+ && expectedPackage.contains(event.getPackageName()),
TIMEOUT_UI_CHANGE_S * 1000
);
}
@@ -454,24 +457,40 @@
}
@Test
- @Ignore("Test failure in pre/postsubmit cannot be replicated on local devices. "
- + "Coverage is low-impact.")
public void testOnScreenLock_cannotOpenMenu() throws Throwable {
closeScreen();
wakeUpScreen();
+ sInstrumentation.getContext().sendBroadcast(INTENT_OPEN_MENU);
+ sUiDevice.waitForIdle();
TestUtils.waitUntil("Did not receive signal that menu cannot open",
TIMEOUT_UI_CHANGE_S,
- () -> {
- sInstrumentation.getContext().sendBroadcast(INTENT_OPEN_MENU);
- return sOpenBlocked.get();
- });
+ sOpenBlocked::get);
}
- private static void unlockSignal() {
- // MENU unlocks screen,
- // BACK closes any menu that may appear if the screen wasn't locked.
- sUiAutomation.executeShellCommand("input keyevent KEYCODE_MENU");
- sUiAutomation.executeShellCommand("input keyevent KEYCODE_BACK");
+ private static void unlockSignal() throws RemoteException {
+ if (!sKeyguardManager.isKeyguardLocked()) {
+ return;
+ }
+ // go/adb-cheats#unlock-screen
+ wakeUpScreen();
+ if (sKeyguardManager.isKeyguardLocked()) {
+ sUiDevice.pressMenu();
+ }
+ WaitUtils.ensureThat(
+ "Device unlocked & isInteractive",
+ () -> isScreenOn() && !sKeyguardManager.isKeyguardLocked());
+ }
+
+ private static boolean isScreenOn() {
+ int display = Display.DEFAULT_DISPLAY;
+ return sPowerManager.isInteractive(display)
+ && sDisplayManager.getDisplay(display).getState() == Display.STATE_ON;
+ }
+
+ private static boolean isScreenOff() {
+ int display = Display.DEFAULT_DISPLAY;
+ return !sPowerManager.isInteractive(display)
+ && sDisplayManager.getDisplay(display).getState() == Display.STATE_OFF;
}
}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 7033e2b..b3aa7e1 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -226,6 +226,13 @@
}
flag {
+ name: "dual_shade"
+ namespace: "systemui"
+ description: "Enables the BC25 Dual Shade (go/bc25-dual-shade-design)."
+ bug: "337259436"
+}
+
+flag {
name: "keyguard_bottom_area_refactor"
namespace: "systemui"
description: "Bottom area of keyguard refactor move into KeyguardRootView. Includes "
@@ -835,3 +842,13 @@
description: "Enforce BaseUserRestriction for DISALLOW_CONFIG_BRIGHTNESS."
bug: "329205638"
}
+
+flag {
+ name: "ambient_touch_monitor_listen_to_display_changes"
+ namespace: "systemui"
+ description: "listen to display changes and cache window metrics"
+ bug: "330906135"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt
deleted file mode 100644
index ffa2b46..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.revealeffect
-
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import android.graphics.RenderEffect
-import androidx.core.graphics.ColorUtils
-import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
-import com.android.systemui.surfaceeffects.utils.MathUtils
-import kotlin.math.max
-import kotlin.math.min
-
-/** Creates a reveal effect with a circular ripple sparkles on top. */
-class RippleRevealEffect(
- private val config: RippleRevealEffectConfig,
- private val renderEffectCallback: RenderEffectDrawCallback,
- private val stateChangedCallback: AnimationStateChangedCallback? = null
-) {
- private val rippleRevealShader = RippleRevealShader().apply { applyConfig(config) }
- private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
-
- fun play() {
- if (animator.isRunning) {
- return
- }
-
- animator.duration = config.duration.toLong()
- animator.addUpdateListener { updateListener ->
- val playTime = updateListener.currentPlayTime.toFloat()
- rippleRevealShader.setTime(playTime * TIME_SCALE_FACTOR)
-
- // Compute radius.
- val progress = updateListener.animatedValue as Float
- val innerRad = MathUtils.lerp(config.innerRadiusStart, config.innerRadiusEnd, progress)
- val outerRad = MathUtils.lerp(config.outerRadiusStart, config.outerRadiusEnd, progress)
- rippleRevealShader.setInnerRadius(innerRad)
- rippleRevealShader.setOuterRadius(outerRad)
-
- // Compute alphas.
- val innerAlphaProgress =
- MathUtils.constrainedMap(
- 1f,
- 0f,
- config.innerFadeOutStart,
- config.duration,
- playTime
- )
- val outerAlphaProgress =
- MathUtils.constrainedMap(
- 1f,
- 0f,
- config.outerFadeOutStart,
- config.duration,
- playTime
- )
- val innerAlpha = MathUtils.lerp(0f, 255f, innerAlphaProgress)
- val outerAlpha = MathUtils.lerp(0f, 255f, outerAlphaProgress)
-
- val innerColor = ColorUtils.setAlphaComponent(config.innerColor, innerAlpha.toInt())
- val outerColor = ColorUtils.setAlphaComponent(config.outerColor, outerAlpha.toInt())
- rippleRevealShader.setInnerColor(innerColor)
- rippleRevealShader.setOuterColor(outerColor)
-
- // Pass in progresses since those functions take in normalized alpha values.
- rippleRevealShader.setBackgroundAlpha(max(innerAlphaProgress, outerAlphaProgress))
- rippleRevealShader.setSparkleAlpha(min(innerAlphaProgress, outerAlphaProgress))
-
- // Trigger draw callback.
- renderEffectCallback.onDraw(
- RenderEffect.createRuntimeShaderEffect(
- rippleRevealShader,
- RippleRevealShader.BACKGROUND_UNIFORM
- )
- )
- }
- animator.addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator) {
- stateChangedCallback?.onAnimationEnd()
- }
- }
- )
- animator.start()
- stateChangedCallback?.onAnimationStart()
- }
-
- interface AnimationStateChangedCallback {
- fun onAnimationStart()
- fun onAnimationEnd()
- }
-
- private companion object {
- private const val TIME_SCALE_FACTOR = 0.00175f
- }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt
deleted file mode 100644
index 9675f19..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.revealeffect
-
-import android.graphics.Color
-
-/** Defines parameters needed for [RippleRevealEffect]. */
-data class RippleRevealEffectConfig(
- /** Total duration of the animation. */
- val duration: Float = 0f,
- /** Timestamp of when the inner mask starts fade out. (Linear fadeout) */
- val innerFadeOutStart: Float = 0f,
- /** Timestamp of when the outer mask starts fade out. (Linear fadeout) */
- val outerFadeOutStart: Float = 0f,
- /** Center x position of the effect. */
- val centerX: Float = 0f,
- /** Center y position of the effect. */
- val centerY: Float = 0f,
- /** Start radius of the inner circle. */
- val innerRadiusStart: Float = 0f,
- /** End radius of the inner circle. */
- val innerRadiusEnd: Float = 0f,
- /** Start radius of the outer circle. */
- val outerRadiusStart: Float = 0f,
- /** End radius of the outer circle. */
- val outerRadiusEnd: Float = 0f,
- /**
- * Pixel density of the display. Do not pass a random value. The value must come from
- * [context.resources.displayMetrics.density].
- */
- val pixelDensity: Float = 1f,
- /**
- * The amount the circle masks should be softened. Higher value will make the edge of the circle
- * mask soft.
- */
- val blurAmount: Float = 0f,
- /** Color of the inner circle mask. */
- val innerColor: Int = Color.WHITE,
- /** Color of the outer circle mask. */
- val outerColor: Int = Color.WHITE,
- /** Multiplier to make the sparkles visible. */
- val sparkleStrength: Float = SPARKLE_STRENGTH,
- /** Size of the sparkle. Expected range [0, 1]. */
- val sparkleScale: Float = SPARKLE_SCALE
-) {
- /** Default parameters. */
- companion object {
- const val SPARKLE_STRENGTH: Float = 0.3f
- const val SPARKLE_SCALE: Float = 0.8f
- }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt
deleted file mode 100644
index a3f9795..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.revealeffect
-
-import android.graphics.RuntimeShader
-import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
-import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
-
-/** Circular reveal effect with sparkles. */
-class RippleRevealShader : RuntimeShader(SHADER) {
- // language=AGSL
- companion object {
- const val BACKGROUND_UNIFORM = "in_dst"
- private const val MAIN =
- """
- uniform shader ${BACKGROUND_UNIFORM};
- uniform half in_dstAlpha;
- uniform half in_time;
- uniform vec2 in_center;
- uniform half in_innerRadius;
- uniform half in_outerRadius;
- uniform half in_sparkleStrength;
- uniform half in_blur;
- uniform half in_pixelDensity;
- uniform half in_sparkleScale;
- uniform half in_sparkleAlpha;
- layout(color) uniform vec4 in_innerColor;
- layout(color) uniform vec4 in_outerColor;
-
- vec4 main(vec2 p) {
- half innerMask = soften(sdCircle(p - in_center, in_innerRadius), in_blur);
- half outerMask = soften(sdCircle(p - in_center, in_outerRadius), in_blur);
-
- // Flip it since we are interested in the circle.
- innerMask = 1.-innerMask;
- outerMask = 1.-outerMask;
-
- // Color two circles using the mask.
- vec4 inColor = vec4(in_innerColor.rgb, 1.) * in_innerColor.a;
- vec4 outColor = vec4(in_outerColor.rgb, 1.) * in_outerColor.a;
- vec4 blend = mix(inColor, outColor, innerMask);
-
- vec4 dst = vec4(in_dst.eval(p).rgb, 1.);
- dst *= in_dstAlpha;
-
- blend *= blend.a;
- // Do normal blend with the background.
- blend = blend + dst * (1. - blend.a);
-
- half sparkle =
- sparkles(p - mod(p, in_pixelDensity * in_sparkleScale), in_time);
- // Add sparkles using additive blending.
- blend += sparkle * in_sparkleStrength * in_sparkleAlpha;
-
- // Mask everything at the end.
- blend *= outerMask;
-
- return blend;
- }
- """
-
- private const val SHADER =
- ShaderUtilLibrary.SHADER_LIB +
- SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
- SdfShaderLibrary.CIRCLE_SDF +
- MAIN
- }
-
- fun applyConfig(config: RippleRevealEffectConfig) {
- setCenter(config.centerX, config.centerY)
- setInnerRadius(config.innerRadiusStart)
- setOuterRadius(config.outerRadiusStart)
- setBlurAmount(config.blurAmount)
- setPixelDensity(config.pixelDensity)
- setSparkleScale(config.sparkleScale)
- setSparkleStrength(config.sparkleStrength)
- setInnerColor(config.innerColor)
- setOuterColor(config.outerColor)
- }
-
- fun setTime(time: Float) {
- setFloatUniform("in_time", time)
- }
-
- fun setCenter(centerX: Float, centerY: Float) {
- setFloatUniform("in_center", centerX, centerY)
- }
-
- fun setInnerRadius(radius: Float) {
- setFloatUniform("in_innerRadius", radius)
- }
-
- fun setOuterRadius(radius: Float) {
- setFloatUniform("in_outerRadius", radius)
- }
-
- fun setBlurAmount(blurAmount: Float) {
- setFloatUniform("in_blur", blurAmount)
- }
-
- fun setPixelDensity(density: Float) {
- setFloatUniform("in_pixelDensity", density)
- }
-
- fun setSparkleScale(scale: Float) {
- setFloatUniform("in_sparkleScale", scale)
- }
-
- fun setSparkleStrength(strength: Float) {
- setFloatUniform("in_sparkleStrength", strength)
- }
-
- fun setInnerColor(color: Int) {
- setColorUniform("in_innerColor", color)
- }
-
- fun setOuterColor(color: Int) {
- setColorUniform("in_outerColor", color)
- }
-
- /** Sets the background alpha. Range [0,1]. */
- fun setBackgroundAlpha(alpha: Float) {
- setFloatUniform("in_dstAlpha", alpha)
- }
-
- /** Sets the sparkle alpha. Range [0,1]. */
- fun setSparkleAlpha(alpha: Float) {
- setFloatUniform("in_sparkleAlpha", alpha)
- }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt
deleted file mode 100644
index 1411c32..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.utils
-
-/** Copied from android.utils.MathUtils */
-object MathUtils {
- fun constrainedMap(
- rangeMin: Float,
- rangeMax: Float,
- valueMin: Float,
- valueMax: Float,
- value: Float
- ): Float {
- return lerp(rangeMin, rangeMax, lerpInvSat(valueMin, valueMax, value))
- }
-
- fun lerp(start: Float, stop: Float, amount: Float): Float {
- return start + (stop - start) * amount
- }
-
- fun lerpInv(a: Float, b: Float, value: Float): Float {
- return if (a != b) (value - a) / (b - a) else 0.0f
- }
-
- fun saturate(value: Float): Float {
- return constrain(value, 0.0f, 1.0f)
- }
-
- fun lerpInvSat(a: Float, b: Float, value: Float): Float {
- return saturate(lerpInv(a, b, value))
- }
-
- fun constrain(amount: Float, low: Float, high: Float): Float {
- return if (amount < low) low else if (amount > high) high else amount
- }
-}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index 19d6038..7af8408 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -52,7 +52,6 @@
import com.android.internal.R
import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PatternDotViewModel
-import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.sqrt
@@ -110,30 +109,14 @@
remember(dots) {
dots.associateWith { dot -> with(density) { (80 + (20 * dot.y)).dp.toPx() } }
}
- val dotAppearScaleAnimatables = remember(dots) { dots.associateWith { Animatable(0f) } }
LaunchedEffect(Unit) {
dotAppearFadeInAnimatables.forEach { (dot, animatable) ->
scope.launch {
- // Maps a dot at x and y to an ordinal number to denote the order in which all dots
- // are visited by the fade-in animation.
- //
- // The order is basically starting from the top-left most dot (at 0,0) and ending at
- // the bottom-right most dot (at 2,2). The visitation order happens
- // diagonal-by-diagonal. Here's a visual representation of the expected output:
- // [0][1][3]
- // [2][4][6]
- // [5][7][8]
- //
- // There's an assumption here that the grid is 3x3. If it's not, this formula needs
- // to be revisited.
- check(viewModel.columnCount == 3 && viewModel.rowCount == 3)
- val staggerOrder = max(0, min(8, 2 * (dot.x + dot.y) + (dot.y - 1)))
-
animatable.animateTo(
targetValue = 1f,
animationSpec =
tween(
- delayMillis = 33 * staggerOrder,
+ delayMillis = 33 * dot.y,
durationMillis = 450,
easing = Easings.LegacyDecelerate,
)
@@ -153,19 +136,6 @@
)
}
}
- dotAppearScaleAnimatables.forEach { (dot, animatable) ->
- scope.launch {
- animatable.animateTo(
- targetValue = 1f,
- animationSpec =
- tween(
- delayMillis = 33 * dot.y,
- durationMillis = 450,
- easing = Easings.LegacyDecelerate,
- )
- )
- }
- }
}
val view = LocalView.current
@@ -401,10 +371,7 @@
),
color =
dotColor.copy(alpha = checkNotNull(dotAppearFadeInAnimatables[dot]).value),
- radius =
- dotRadius *
- checkNotNull(dotScalingAnimatables[dot]).value *
- checkNotNull(dotAppearScaleAnimatables[dot]).value,
+ radius = dotRadius * checkNotNull(dotScalingAnimatables[dot]).value
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index e07cd05..ec3c003 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -27,6 +27,7 @@
import com.android.compose.animation.scene.transitions
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalTransitionKeys
+import com.android.systemui.communal.ui.compose.extensions.allowGestures
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.util.CommunalColors
import com.android.systemui.res.R
@@ -79,6 +80,7 @@
) {
val coroutineScope = rememberCoroutineScope()
val currentSceneKey: SceneKey by viewModel.currentScene.collectAsState(CommunalScenes.Blank)
+ val touchesAllowed by viewModel.touchesAllowed.collectAsState(initial = false)
val state: MutableSceneTransitionLayoutState = remember {
MutableSceneTransitionLayoutState(
initialScene = currentSceneKey,
@@ -128,6 +130,10 @@
CommunalScene(viewModel, colors, dialogFactory, modifier = modifier)
}
}
+
+ // Touches on the notification shade in blank areas fall through to the glanceable hub. When the
+ // shade is showing, we block all touches in order to prevent this unwanted behavior.
+ Box(modifier = Modifier.fillMaxSize().allowGestures(touchesAllowed))
}
/** Scene containing the glanceable hub UI. */
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 89d4343..dff9b3b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -20,6 +20,8 @@
import android.graphics.drawable.Icon
import android.os.Bundle
import android.util.SizeF
+import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
+import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
import android.widget.FrameLayout
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
@@ -103,6 +105,7 @@
import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.customActions
+import androidx.compose.ui.semantics.onClick
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.style.TextAlign
@@ -115,8 +118,6 @@
import androidx.compose.ui.window.Popup
import androidx.core.view.setPadding
import androidx.window.layout.WindowMetricsCalculator
-import com.android.compose.modifiers.height
-import com.android.compose.modifiers.padding
import com.android.compose.modifiers.thenIf
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
@@ -132,6 +133,7 @@
import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
+import com.android.systemui.communal.ui.viewmodel.PopupType
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
@@ -148,8 +150,7 @@
onEditDone: (() -> Unit)? = null,
) {
val communalContent by viewModel.communalContent.collectAsState(initial = emptyList())
- val isPopupOnDismissCtaShowing by
- viewModel.isPopupOnDismissCtaShowing.collectAsState(initial = false)
+ val currentPopup by viewModel.currentPopup.collectAsState(initial = null)
var removeButtonCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
var toolbarSize: IntSize? by remember { mutableStateOf(null) }
var gridCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
@@ -161,7 +162,6 @@
val removeButtonEnabled by remember {
derivedStateOf { selectedKey.value != null || reorderingWidgets }
}
- var isButtonToEditWidgetsShowing by remember { mutableStateOf(false) }
val isEmptyState by viewModel.isEmptyState.collectAsState(initial = false)
val contentPadding = gridContentPadding(viewModel.isEditMode, toolbarSize)
@@ -214,7 +214,7 @@
communalContent[index] is
CommunalContentModel.CtaTileInViewMode
) {
- isButtonToEditWidgetsShowing = true
+ viewModel.onShowCustomizeWidgetButton()
}
val key =
index?.let { keyAtIndexIfEditable(communalContent, index) }
@@ -290,18 +290,22 @@
)
}
- if (isPopupOnDismissCtaShowing) {
- PopupOnDismissCtaTile(viewModel::onHidePopupAfterDismissCta)
- }
-
- if (isButtonToEditWidgetsShowing) {
- ButtonToEditWidgets(
- onClick = {
- isButtonToEditWidgetsShowing = false
- viewModel.onOpenWidgetEditor(selectedKey.value)
- },
- onHide = { isButtonToEditWidgetsShowing = false },
- )
+ if (currentPopup != null) {
+ when (currentPopup) {
+ PopupType.CtaTile -> {
+ PopupOnDismissCtaTile(viewModel::onHidePopup)
+ }
+ PopupType.CustomizeWidgetButton -> {
+ ButtonToEditWidgets(
+ onClick = {
+ viewModel.onHidePopup()
+ viewModel.onOpenWidgetEditor(selectedKey.value)
+ },
+ onHide = { viewModel.onHidePopup() }
+ )
+ }
+ null -> {}
+ }
}
if (viewModel is CommunalViewModel && dialogFactory != null) {
@@ -371,7 +375,7 @@
liveContentKeys.indexOfFirst { !prevLiveContentKeys.contains(it) }
// Scroll if current position is behind the first updated content
- if (indexOfFirstUpdatedContent in 0..<gridState.firstVisibleItemIndex) {
+ if (indexOfFirstUpdatedContent in 0 until gridState.firstVisibleItemIndex) {
// Launching with a scope to prevent the job from being canceled in the case of a
// recomposition during scrolling
coroutineScope.launch { gridState.animateScrollToItem(indexOfFirstUpdatedContent) }
@@ -679,11 +683,11 @@
}
@Composable
-private fun PopupOnDismissCtaTile(onHidePopupAfterDismissCta: () -> Unit) {
+private fun PopupOnDismissCtaTile(onHidePopup: () -> Unit) {
Popup(
alignment = Alignment.TopCenter,
offset = IntOffset(0, 40),
- onDismissRequest = onHidePopupAfterDismissCta
+ onDismissRequest = onHidePopup
) {
val colors = LocalAndroidColorScheme.current
Row(
@@ -838,17 +842,31 @@
widgetConfigurator: WidgetConfigurator?,
modifier: Modifier = Modifier,
) {
+ val context = LocalContext.current
+ val isFocusable by viewModel.isFocusable.collectAsState(initial = false)
+ val accessibilityLabel =
+ remember(model, context) {
+ model.providerInfo.loadLabel(context.packageManager).toString().trim()
+ }
+ val clickActionLabel = stringResource(R.string.accessibility_action_label_select_widget)
Box(
modifier =
- modifier.thenIf(!viewModel.isEditMode && model.inQuietMode) {
- Modifier.pointerInput(Unit) {
- // consume tap to prevent the child view from triggering interactions with the
- // app widget
- observeTaps(shouldConsume = true) { _ ->
- viewModel.onOpenEnableWorkProfileDialog()
+ modifier
+ .thenIf(!viewModel.isEditMode && model.inQuietMode) {
+ Modifier.pointerInput(Unit) {
+ // consume tap to prevent the child view from triggering interactions with
+ // the app widget
+ observeTaps(shouldConsume = true) { _ ->
+ viewModel.onOpenEnableWorkProfileDialog()
+ }
}
}
- }
+ .thenIf(viewModel.isEditMode) {
+ Modifier.semantics {
+ contentDescription = accessibilityLabel
+ onClick(label = clickActionLabel, action = null)
+ }
+ }
) {
AndroidView(
modifier = Modifier.fillMaxSize().allowGestures(allowed = !viewModel.isEditMode),
@@ -860,8 +878,19 @@
// Remove the extra padding applied to AppWidgetHostView to allow widgets to
// occupy the entire box.
setPadding(0)
+ accessibilityDelegate = viewModel.widgetAccessibilityDelegate
}
},
+ update = {
+ it.apply {
+ importantForAccessibility =
+ if (isFocusable) {
+ IMPORTANT_FOR_ACCESSIBILITY_AUTO
+ } else {
+ IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ }
+ }
+ },
// For reusing composition in lazy lists.
onReset = {},
)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
index e7bfee3..33d2cc4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
@@ -40,6 +40,7 @@
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.pointerInteropFilter
+import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.toOffset
import androidx.compose.ui.unit.toSize
@@ -274,6 +275,9 @@
AnimatedVisibility(
modifier =
Modifier.matchParentSize()
+ // Avoid taking focus away from the content when using explore-by-touch with
+ // accessibility tools.
+ .clearAndSetSemantics {}
// Do not consume motion events in the highlighted item and pass them down to
// the content.
.pointerInteropFilter { false },
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt
index dae120c..556bbbe 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt
@@ -17,21 +17,14 @@
package com.android.systemui.keyguard.ui.composable.section
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.res.dimensionResource
import com.android.compose.animation.scene.SceneScope
import com.android.systemui.keyguard.ui.viewmodel.MediaCarouselViewModel
import com.android.systemui.media.controls.ui.composable.MediaCarousel
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.res.R
-import com.android.systemui.util.animation.MeasurementInput
import javax.inject.Inject
import javax.inject.Named
@@ -43,29 +36,19 @@
private val mediaCarouselViewModel: MediaCarouselViewModel,
) {
- @Composable
- fun SceneScope.MediaCarousel(modifier: Modifier = Modifier) {
- if (!mediaCarouselViewModel.isMediaVisible) {
- return
- }
-
+ private fun isVisible(): Boolean {
if (mediaCarouselController.mediaFrame == null) {
- return
+ return false
}
+ return mediaCarouselViewModel.isMediaVisible
+ }
- val mediaHeight = dimensionResource(R.dimen.qs_media_session_height_expanded)
- // TODO(b/312714128): MediaPlayer background size is not as expected.
+ @Composable
+ fun SceneScope.KeyguardMediaCarousel() {
MediaCarousel(
- modifier =
- modifier.height(mediaHeight).fillMaxWidth().onSizeChanged { size ->
- // Notify controller to size the carousel for the
- // current space
- mediaHost.measurementInput = MeasurementInput(size.width, size.height)
- mediaCarouselController.setSceneContainerSize(size.width, size.height)
- },
+ isVisible = ::isVisible,
mediaHost = mediaHost,
- layoutWidth = 0, // Layout width is not used.
- layoutHeight = with(LocalDensity.current) { mediaHeight.toPx() }.toInt(),
+ modifier = Modifier.fillMaxWidth(),
carouselController = mediaCarouselController,
)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
index e0540bf..722032c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
@@ -125,7 +125,7 @@
onTopChanged = burnIn.onSmartspaceTopChanged,
)
}
- with(mediaCarouselSection) { MediaCarousel() }
+ with(mediaCarouselSection) { KeyguardMediaCarousel() }
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
index f0d356c..241c171 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
@@ -18,14 +18,20 @@
import android.view.ViewGroup
import android.widget.FrameLayout
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.layout
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.contains
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.SceneScope
import com.android.systemui.media.controls.ui.controller.MediaCarouselController
import com.android.systemui.media.controls.ui.view.MediaHost
+import com.android.systemui.res.R
import com.android.systemui.util.animation.MeasurementInput
private object MediaCarousel {
@@ -36,18 +42,40 @@
@Composable
fun SceneScope.MediaCarousel(
+ isVisible: () -> Boolean,
mediaHost: MediaHost,
modifier: Modifier = Modifier,
- layoutWidth: Int,
- layoutHeight: Int,
carouselController: MediaCarouselController,
) {
+ if (!isVisible()) {
+ return
+ }
+
+ val density = LocalDensity.current
+ val mediaHeight = dimensionResource(R.dimen.qs_media_session_height_expanded)
+
+ val layoutWidth = 0
+ val layoutHeight = with(density) { mediaHeight.toPx() }.toInt()
+
// Notify controller to size the carousel for the current space
mediaHost.measurementInput = MeasurementInput(layoutWidth, layoutHeight)
carouselController.setSceneContainerSize(layoutWidth, layoutHeight)
AndroidView(
- modifier = modifier.element(MediaCarousel.Elements.Content),
+ modifier =
+ modifier
+ .element(MediaCarousel.Elements.Content)
+ .height(mediaHeight)
+ .fillMaxWidth()
+ .layout { measurable, constraints ->
+ val placeable = measurable.measure(constraints)
+
+ // Notify controller to size the carousel for the current space
+ mediaHost.measurementInput = MeasurementInput(placeable.width, placeable.height)
+ carouselController.setSceneContainerSize(placeable.width, placeable.height)
+
+ layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) }
+ },
factory = { context ->
FrameLayout(context).apply {
val mediaFrame = carouselController.mediaFrame
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index f6575dc..62619f5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -67,6 +67,10 @@
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.media.controls.ui.composable.MediaCarousel
+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.notifications.ui.composable.NotificationScrollingStack
import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel
@@ -82,6 +86,7 @@
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
import javax.inject.Inject
+import javax.inject.Named
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
@@ -98,6 +103,8 @@
private val tintedIconManagerFactory: TintedIconManager.Factory,
private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
private val statusBarIconController: StatusBarIconController,
+ private val mediaCarouselController: MediaCarouselController,
+ @Named(MediaModule.QS_PANEL) private val mediaHost: MediaHost,
) : ComposableScene {
override val key = Scenes.QuickSettings
@@ -118,6 +125,8 @@
createTintedIconManager = tintedIconManagerFactory::create,
createBatteryMeterViewController = batteryMeterViewControllerFactory::create,
statusBarIconController = statusBarIconController,
+ mediaCarouselController = mediaCarouselController,
+ mediaHost = mediaHost,
modifier = modifier,
)
}
@@ -130,6 +139,8 @@
createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager,
createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController,
statusBarIconController: StatusBarIconController,
+ mediaCarouselController: MediaCarouselController,
+ mediaHost: MediaHost,
modifier: Modifier = Modifier,
) {
val brightnessMirrorShowing by viewModel.brightnessMirrorViewModel.isShowing.collectAsState()
@@ -282,6 +293,13 @@
isSplitShade = false,
modifier = Modifier.sysuiResTag("expanded_qs_scroll_view"),
)
+
+ MediaCarousel(
+ isVisible = viewModel::isMediaVisible,
+ mediaHost = mediaHost,
+ modifier = Modifier.fillMaxWidth(),
+ carouselController = mediaCarouselController,
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 91a9d2a..cda8059 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -50,11 +50,9 @@
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.layout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.colorResource
-import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexScenePicker
@@ -85,7 +83,6 @@
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
-import com.android.systemui.util.animation.MeasurementInput
import javax.inject.Inject
import javax.inject.Named
import kotlin.math.roundToInt
@@ -243,10 +240,11 @@
)
}
- MediaIfVisible(
- viewModel = viewModel,
- mediaCarouselController = mediaCarouselController,
+ MediaCarousel(
+ isVisible = viewModel::isMediaVisible,
mediaHost = mediaHost,
+ modifier = Modifier.fillMaxWidth(),
+ carouselController = mediaCarouselController,
)
Spacer(modifier = Modifier.height(16.dp))
@@ -406,11 +404,11 @@
)
}
- MediaIfVisible(
- viewModel = viewModel,
- mediaCarouselController = mediaCarouselController,
+ MediaCarousel(
+ isVisible = viewModel::isMediaVisible,
mediaHost = mediaHost,
modifier = Modifier.fillMaxWidth(),
+ carouselController = mediaCarouselController,
)
}
FooterActionsWithAnimatedVisibility(
@@ -437,34 +435,3 @@
}
}
}
-
-@Composable
-private fun SceneScope.MediaIfVisible(
- viewModel: ShadeSceneViewModel,
- mediaCarouselController: MediaCarouselController,
- mediaHost: MediaHost,
- modifier: Modifier = Modifier,
-) {
- if (viewModel.isMediaVisible()) {
- val density = LocalDensity.current
- val mediaHeight = dimensionResource(R.dimen.qs_media_session_height_expanded)
-
- MediaCarousel(
- modifier =
- modifier.height(mediaHeight).fillMaxWidth().layout { measurable, constraints ->
- val placeable = measurable.measure(constraints)
-
- // Notify controller to size the carousel for the
- // current space
- mediaHost.measurementInput = MeasurementInput(placeable.width, placeable.height)
- mediaCarouselController.setSceneContainerSize(placeable.width, placeable.height)
-
- layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) }
- },
- mediaHost = mediaHost,
- layoutWidth = 0,
- layoutHeight = with(density) { mediaHeight.toPx() }.toInt(),
- carouselController = mediaCarouselController,
- )
- }
-}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/EdgeToEdgeDialogDelegate.kt b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/EdgeToEdgeDialogDelegate.kt
new file mode 100644
index 0000000..55dfed4
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/EdgeToEdgeDialogDelegate.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.os.Bundle
+import android.view.Gravity
+import android.view.WindowManager
+
+/** [DialogDelegate] that configures a dialog to be an edge-to-edge one. */
+class EdgeToEdgeDialogDelegate : DialogDelegate<SystemUIDialog> {
+
+ override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ dialog.window?.apply {
+ setGravity(Gravity.BOTTOM or Gravity.CENTER)
+ attributes =
+ attributes.apply {
+ fitInsetsSides = 0
+ attributes.apply {
+ layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ }
+ }
+ }
+ }
+
+ override fun getWidth(dialog: SystemUIDialog): Int = WindowManager.LayoutParams.MATCH_PARENT
+
+ override fun getHeight(dialog: SystemUIDialog): Int = WindowManager.LayoutParams.MATCH_PARENT
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
index d66bada..fe97405 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
@@ -17,13 +17,33 @@
package com.android.systemui.statusbar.phone
import android.content.Context
+import android.content.res.Configuration
+import android.os.Bundle
import androidx.annotation.GravityInt
+import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
import com.android.compose.theme.PlatformTheme
+import com.android.systemui.res.R
/**
* Create a [SystemUIDialog] with the given [content].
@@ -56,7 +76,73 @@
@GravityInt dialogGravity: Int? = null,
content: @Composable (SystemUIDialog) -> Unit,
): ComponentSystemUIDialog {
- val dialog = create(context, theme, dismissOnDeviceLock, dialogGravity)
+ return create(
+ context = context,
+ theme = theme,
+ dismissOnDeviceLock = dismissOnDeviceLock,
+ delegate =
+ object : DialogDelegate<SystemUIDialog> {
+ override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ super.onCreate(dialog, savedInstanceState)
+ dialogGravity?.let { dialog.window?.setGravity(it) }
+ }
+ },
+ content = content,
+ )
+}
+
+/** Same as [create] but creates a bottom sheet dialog. */
+fun SystemUIDialogFactory.createBottomSheet(
+ context: Context = this.applicationContext,
+ theme: Int = R.style.Theme_SystemUI_BottomSheet,
+ dismissOnDeviceLock: Boolean = SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK,
+ content: @Composable (SystemUIDialog) -> Unit,
+): ComponentSystemUIDialog {
+ return create(
+ context = context,
+ theme = theme,
+ dismissOnDeviceLock = dismissOnDeviceLock,
+ delegate = EdgeToEdgeDialogDelegate(),
+ content = { dialog ->
+ Box(
+ modifier = Modifier.bottomSheetClickable { dialog.dismiss() },
+ contentAlignment = Alignment.BottomCenter
+ ) {
+ val radius = dimensionResource(R.dimen.bottom_sheet_corner_radius)
+ Surface(
+ modifier =
+ Modifier.bottomSheetPaddings()
+ // consume input so it doesn't get to the parent Composable
+ .bottomSheetClickable {}
+ // TODO(b/337205027) change width
+ .widthIn(max = 800.dp),
+ shape = RoundedCornerShape(topStart = radius, topEnd = radius),
+ color = MaterialTheme.colorScheme.surfaceContainer,
+ ) {
+ Box(
+ Modifier.padding(
+ bottom =
+ with(LocalDensity.current) {
+ WindowInsets.safeDrawing.getBottom(this).toDp()
+ }
+ )
+ ) {
+ content(dialog)
+ }
+ }
+ }
+ },
+ )
+}
+
+private fun SystemUIDialogFactory.create(
+ context: Context,
+ theme: Int,
+ dismissOnDeviceLock: Boolean,
+ delegate: DialogDelegate<SystemUIDialog>,
+ content: @Composable (SystemUIDialog) -> Unit,
+): ComponentSystemUIDialog {
+ val dialog = create(context, theme, dismissOnDeviceLock, delegate)
// Create the dialog so that it is properly constructed before we set the Compose content.
// Otherwise, the ComposeView won't render properly.
@@ -79,3 +165,29 @@
return dialog
}
+
+/** Adds paddings for the bottom sheet surface. */
+@Composable
+private fun Modifier.bottomSheetPaddings(): Modifier {
+ val isPortrait = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT
+ return with(LocalDensity.current) {
+ val insets = WindowInsets.safeDrawing
+ // TODO(b/337205027) change paddings
+ val horizontalPadding: Dp = if (isPortrait) 0.dp else 48.dp
+ padding(
+ start = insets.getLeft(this, LocalLayoutDirection.current).toDp() + horizontalPadding,
+ top = insets.getTop(this).toDp(),
+ end = insets.getRight(this, LocalLayoutDirection.current).toDp() + horizontalPadding
+ )
+ }
+}
+
+/**
+ * For some reason adding clickable modifier onto the VolumePanel affects the traversal order:
+ * b/331155283.
+ *
+ * TODO(b/334870995) revert this to Modifier.clickable
+ */
+@Composable
+private fun Modifier.bottomSheetClickable(onClick: () -> Unit) =
+ pointerInput(onClick) { detectTapGestures { onClick() } }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
index f354b80..74af3ca 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
@@ -98,10 +98,10 @@
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
- return onClick != null || super.onInterceptTouchEvent(ev)
+ return (isSliceViewClickable && onClick != null) || super.onInterceptTouchEvent(ev)
}
override fun onClick(v: View?) {
- onClick?.let { it() } ?: super.onClick(v)
+ onClick?.takeIf { isSliceViewClickable }?.let { it() } ?: super.onClick(v)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
index 4f3a6c8..874c0a2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
@@ -38,6 +38,8 @@
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.toggleableState
+import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.unit.dp
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
@@ -79,6 +81,12 @@
modifier =
Modifier.fillMaxSize().padding(8.dp).semantics {
role = Role.Switch
+ toggleableState =
+ if (viewModel.isActive) {
+ ToggleableState.On
+ } else {
+ ToggleableState.Off
+ }
contentDescription = label
},
onClick = { onCheckedChange(!viewModel.isActive) },
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
index c73656e..f1cc71b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
@@ -16,9 +16,9 @@
package com.android.systemui.volume.panel.component.mediaoutput
-import com.android.systemui.volume.panel.component.mediaoutput.domain.MediaOutputAvailabilityCriteria
import com.android.systemui.volume.panel.component.mediaoutput.ui.composable.MediaOutputComponent
import com.android.systemui.volume.panel.component.shared.model.VolumePanelComponents
+import com.android.systemui.volume.panel.domain.AlwaysAvailableCriteria
import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent
import dagger.Binds
@@ -39,6 +39,6 @@
@IntoMap
@StringKey(VolumePanelComponents.MEDIA_OUTPUT)
fun bindComponentAvailabilityCriteria(
- criteria: MediaOutputAvailabilityCriteria
+ criteria: AlwaysAvailableCriteria
): ComponentAvailabilityCriteria
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt
index b489dfc..bb4e957 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt
@@ -65,7 +65,7 @@
) {
val dialog =
dialogFactory.create(
- theme = R.style.Theme_VolumePanelActivity_Popup,
+ theme = R.style.Theme_VolumePanel_Popup,
dialogGravity = Gravity.BOTTOM,
) {
PopupComposable(it, title, content)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
index 1bf541a..c51e8b0 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
@@ -16,40 +16,22 @@
package com.android.systemui.volume.panel.ui.composable
-import androidx.compose.foundation.gestures.detectTapGestures
-import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.displayCutout
-import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
-import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.widthIn
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.max
-import com.android.compose.theme.PlatformTheme
-import com.android.systemui.res.R
import com.android.systemui.volume.panel.ui.layout.ComponentsLayout
import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelState
import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
-import kotlin.math.max
private val padding = 24.dp
@@ -67,39 +49,20 @@
}
}
- PlatformTheme(isSystemInDarkTheme()) {
- val state: VolumePanelState by viewModel.volumePanelState.collectAsState()
- val components by viewModel.componentsLayout.collectAsState(null)
+ val state: VolumePanelState by viewModel.volumePanelState.collectAsState()
+ val components by viewModel.componentsLayout.collectAsState(null)
- with(VolumePanelComposeScope(state)) {
- Box(
- modifier =
- modifier
- .fillMaxSize()
- .volumePanelClick(onDismiss)
- .volumePanelPaddings(isPortrait = isPortrait),
- contentAlignment = Alignment.BottomCenter,
- ) {
- val radius = dimensionResource(R.dimen.volume_panel_corner_radius)
- Surface(
- modifier = Modifier.volumePanelClick {},
- shape = RoundedCornerShape(topStart = radius, topEnd = radius),
- color = MaterialTheme.colorScheme.surfaceContainer,
- ) {
- components?.let { componentsState ->
- Components(
- componentsState,
- Modifier.padding(
- start = padding,
- top = padding,
- end = padding,
- bottom = 20.dp,
- )
- .navigationBarsPadding()
- )
- }
- }
- }
+ with(VolumePanelComposeScope(state)) {
+ components?.let { componentsState ->
+ Components(
+ componentsState,
+ modifier.padding(
+ start = padding,
+ top = padding,
+ end = padding,
+ bottom = 20.dp,
+ )
+ )
}
}
}
@@ -116,7 +79,7 @@
if (isPortrait) Arrangement.spacedBy(padding) else Arrangement.spacedBy(4.dp)
}
Column(
- modifier = modifier.widthIn(max = 800.dp),
+ modifier = modifier,
verticalArrangement = arrangement,
) {
if (isPortrait || isLargeScreen) {
@@ -153,38 +116,3 @@
}
}
}
-
-/**
- * Makes sure volume panel stays symmetrically in the middle of the screen while still avoiding
- * being under the cutouts.
- */
-@Composable
-private fun Modifier.volumePanelPaddings(isPortrait: Boolean): Modifier {
- val cutout = WindowInsets.displayCutout
- return with(LocalDensity.current) {
- val horizontalCutout =
- max(
- cutout.getLeft(density = this, layoutDirection = LocalLayoutDirection.current),
- cutout.getRight(density = this, layoutDirection = LocalLayoutDirection.current)
- )
- val minHorizontalPadding = if (isPortrait) 0.dp else 48.dp
- val horizontalPadding = max(horizontalCutout.toDp(), minHorizontalPadding)
-
- padding(
- start = horizontalPadding,
- top = cutout.getTop(this).toDp(),
- end = horizontalPadding,
- bottom = cutout.getBottom(this).toDp(),
- )
- }
-}
-
-/**
- * For some reason adding clickable modifier onto the VolumePanel affects the traversal order:
- * b/331155283.
- *
- * TODO(b/334870995) revert this to Modifier.clickable
- */
-@Composable
-private fun Modifier.volumePanelClick(onClick: () -> Unit) =
- pointerInput(onClick) { detectTapGestures { onClick() } }
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 4273b4f..ca64323 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
@@ -217,18 +217,18 @@
maybePruneMaps(layoutImpl, prevElement, prevSceneState)
}
- override fun isMeasurementApproachComplete(lookaheadSize: IntSize): Boolean {
+ override fun isMeasurementApproachInProgress(lookaheadSize: IntSize): Boolean {
// TODO(b/324191441): Investigate whether making this check more complex (checking if this
// element is shared or transformed) would lead to better performance.
- return layoutImpl.state.currentTransitions.isEmpty()
+ return layoutImpl.state.isTransitioning()
}
- override fun Placeable.PlacementScope.isPlacementApproachComplete(
+ override fun Placeable.PlacementScope.isPlacementApproachInProgress(
lookaheadCoordinates: LayoutCoordinates
): Boolean {
// TODO(b/324191441): Investigate whether making this check more complex (checking if this
// element is shared or transformed) would lead to better performance.
- return layoutImpl.state.currentTransitions.isEmpty()
+ return layoutImpl.state.isTransitioning()
}
@ExperimentalComposeUiApi
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
index 7fb5a4d..339868c 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
@@ -26,7 +26,7 @@
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.intermediateLayout
+import androidx.compose.ui.layout.approachLayout
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.zIndex
@@ -74,7 +74,9 @@
Box(
modifier
.zIndex(zIndex)
- .intermediateLayout { measurable, constraints ->
+ .approachLayout(
+ isMeasurementApproachInProgress = { scope.layoutState.isTransitioning() }
+ ) { measurable, constraints ->
targetSize = lookaheadSize
val placeable = measurable.measure(constraints)
layout(placeable.width, placeable.height) { placeable.place(0, 0) }
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 ad691ba..d383cec 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
@@ -251,8 +251,8 @@
private class LayoutNode(var layoutImpl: SceneTransitionLayoutImpl) :
Modifier.Node(), ApproachLayoutModifierNode {
- override fun isMeasurementApproachComplete(lookaheadSize: IntSize): Boolean {
- return layoutImpl.state.currentTransition == null
+ override fun isMeasurementApproachInProgress(lookaheadSize: IntSize): Boolean {
+ return layoutImpl.state.isTransitioning()
}
@ExperimentalComposeUiApi
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/modifiers/Size.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/modifiers/Size.kt
index bd36cb8..b392c67 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/modifiers/Size.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/modifiers/Size.kt
@@ -18,15 +18,17 @@
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.intermediateLayout
+import androidx.compose.ui.layout.approachLayout
import androidx.compose.ui.unit.Constraints
import com.android.compose.animation.scene.SceneTransitionLayoutState
@OptIn(ExperimentalComposeUiApi::class)
internal fun Modifier.noResizeDuringTransitions(layoutState: SceneTransitionLayoutState): Modifier {
- return intermediateLayout { measurable, constraints ->
+ return approachLayout(isMeasurementApproachInProgress = { layoutState.isTransitioning() }) {
+ measurable,
+ constraints ->
if (layoutState.currentTransition == null) {
- return@intermediateLayout measurable.measure(constraints).run {
+ return@approachLayout measurable.measure(constraints).run {
layout(width, height) { place(0, 0) }
}
}
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 b1d7055..92e1b2c 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
@@ -46,7 +46,7 @@
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.layout.intermediateLayout
+import androidx.compose.ui.layout.approachLayout
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertPositionInRootIsEqualTo
@@ -91,7 +91,9 @@
modifier
.offset(offset)
.element(key)
- .intermediateLayout { measurable, constraints ->
+ .approachLayout(
+ isMeasurementApproachInProgress = { layoutState.isTransitioning() }
+ ) { measurable, constraints ->
onLayout()
val placement = measurable.measure(constraints)
layout(placement.width, placement.height) {
@@ -525,7 +527,7 @@
// page should be composed.
HorizontalPager(
pagerState,
- outOfBoundsPageCount = 0,
+ beyondViewportPageCount = 0,
) { page ->
when (page) {
0 -> Box(Modifier.element(TestElements.Foo).fillMaxSize())
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt
index ac7717b..ce4c5275 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt
@@ -202,11 +202,11 @@
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
- fun data(): List<TestCase> =
- listOf(
- TestCase(NestedScrollSource.Drag),
- TestCase(NestedScrollSource.Fling),
- TestCase(NestedScrollSource.Wheel),
+ fun data(): List<TestCase> {
+ return listOf(
+ TestCase(NestedScrollSource.UserInput),
+ TestCase(NestedScrollSource.SideEffect),
)
+ }
}
}
diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md
index fb8a271..2f50bbd 100644
--- a/packages/SystemUI/docs/scene.md
+++ b/packages/SystemUI/docs/scene.md
@@ -62,7 +62,7 @@
NOTE: in case these instructions become stale and don't actually enable the
framework, please make sure `SceneContainerFlag.isEnabled` in the
-[`SceneContainerFlags.kt`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt)
+[`SceneContainerFlag.kt`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt)
file evalutes to `true`.
1. Set a collection of **aconfig flags** to `true` by running the following
@@ -74,10 +74,9 @@
$ adb shell device_config override systemui com.android.systemui.keyguard_wm_state_refactor true
$ adb shell device_config override systemui com.android.systemui.media_in_scene_container true
$ adb shell device_config override systemui com.android.systemui.migrate_clocks_to_blueprint true
- $ adb shell device_config override systemui com.android.systemui.notification_heads_up_refactor true
+ $ adb shell device_config override systemui com.android.systemui.notifications_heads_up_refactor true
$ adb shell device_config override systemui com.android.systemui.predictive_back_sysui true
$ adb shell device_config override systemui com.android.systemui.device_entry_udfps_refactor true
- $ adb shell device_config override systemui com.android.systemui.refactor_keyguard_dismiss_intent true
```
2. **Restart** System UI by issuing the following command:
```console
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 0f8f1a2..569116c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -24,28 +24,39 @@
import android.provider.Settings
import android.widget.RemoteViews
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository
import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository
import com.android.systemui.communal.data.repository.fakeCommunalMediaRepository
+import com.android.systemui.communal.data.repository.fakeCommunalRepository
import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository
import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.communal.domain.interactor.communalTutorialInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
+import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel.Companion.POPUP_AUTO_HIDE_TIMEOUT_MS
+import com.android.systemui.communal.ui.viewmodel.PopupType
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
@@ -62,6 +73,7 @@
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -93,6 +105,8 @@
private lateinit var mediaRepository: FakeCommunalMediaRepository
private lateinit var userRepository: FakeUserRepository
private lateinit var shadeTestUtil: ShadeTestUtil
+ private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
+ private lateinit var communalRepository: FakeCommunalRepository
private lateinit var underTest: CommunalViewModel
@@ -105,12 +119,14 @@
MockitoAnnotations.initMocks(this)
keyguardRepository = kosmos.fakeKeyguardRepository
+ keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
tutorialRepository = kosmos.fakeCommunalTutorialRepository
widgetRepository = kosmos.fakeCommunalWidgetRepository
smartspaceRepository = kosmos.fakeSmartspaceRepository
mediaRepository = kosmos.fakeCommunalMediaRepository
userRepository = kosmos.fakeUserRepository
shadeTestUtil = kosmos.shadeTestUtil
+ communalRepository = kosmos.fakeCommunalRepository
kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
mSetFlagsRule.enableFlags(FLAG_COMMUNAL_HUB)
@@ -124,6 +140,8 @@
underTest =
CommunalViewModel(
testScope,
+ context.resources,
+ kosmos.keyguardTransitionInteractor,
kosmos.communalInteractor,
kosmos.communalTutorialInteractor,
kosmos.shadeInteractor,
@@ -247,7 +265,7 @@
tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
val communalContent by collectLastValue(underTest.communalContent)
- val isPopupOnDismissCtaShowing by collectLastValue(underTest.isPopupOnDismissCtaShowing)
+ val currentPopup by collectLastValue(underTest.currentPopup)
assertThat(communalContent?.size).isEqualTo(1)
assertThat(communalContent?.get(0))
@@ -257,11 +275,11 @@
// hide CTA tile and show the popup
assertThat(communalContent).isEmpty()
- assertThat(isPopupOnDismissCtaShowing).isEqualTo(true)
+ assertThat(currentPopup).isEqualTo(PopupType.CtaTile)
// hide popup after time elapsed
advanceTimeBy(POPUP_AUTO_HIDE_TIMEOUT_MS)
- assertThat(isPopupOnDismissCtaShowing).isEqualTo(false)
+ assertThat(currentPopup).isNull()
}
@Test
@@ -269,14 +287,40 @@
testScope.runTest {
tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
- val isPopupOnDismissCtaShowing by collectLastValue(underTest.isPopupOnDismissCtaShowing)
+ val currentPopup by collectLastValue(underTest.currentPopup)
underTest.onDismissCtaTile()
- assertThat(isPopupOnDismissCtaShowing).isEqualTo(true)
+ assertThat(currentPopup).isEqualTo(PopupType.CtaTile)
// dismiss the popup directly
- underTest.onHidePopupAfterDismissCta()
- assertThat(isPopupOnDismissCtaShowing).isEqualTo(false)
+ underTest.onHidePopup()
+ assertThat(currentPopup).isNull()
+ }
+
+ @Test
+ fun customizeWidgetButton_showsThenHidesAfterTimeout() =
+ testScope.runTest {
+ tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
+ val currentPopup by collectLastValue(underTest.currentPopup)
+
+ assertThat(currentPopup).isNull()
+ underTest.onShowCustomizeWidgetButton()
+ assertThat(currentPopup).isEqualTo(PopupType.CustomizeWidgetButton)
+ advanceTimeBy(POPUP_AUTO_HIDE_TIMEOUT_MS)
+ assertThat(currentPopup).isNull()
+ }
+
+ @Test
+ fun customizeWidgetButton_onDismiss_hidesImmediately() =
+ testScope.runTest {
+ tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
+ val currentPopup by collectLastValue(underTest.currentPopup)
+
+ underTest.onShowCustomizeWidgetButton()
+ assertThat(currentPopup).isEqualTo(PopupType.CustomizeWidgetButton)
+
+ underTest.onHidePopup()
+ assertThat(currentPopup).isNull()
}
@Test
@@ -299,6 +343,129 @@
assertThat(underTest.canChangeScene()).isFalse()
}
+ @Test
+ fun touchesAllowed_shadeNotExpanded() =
+ testScope.runTest {
+ val touchesAllowed by collectLastValue(underTest.touchesAllowed)
+
+ // On keyguard without any shade expansion.
+ kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+ runCurrent()
+ assertThat(touchesAllowed).isTrue()
+ }
+
+ @Test
+ fun touchesAllowed_shadeExpanded() =
+ testScope.runTest {
+ val touchesAllowed by collectLastValue(underTest.touchesAllowed)
+
+ // On keyguard with shade fully expanded.
+ kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ shadeTestUtil.setLockscreenShadeExpansion(1f)
+ runCurrent()
+ assertThat(touchesAllowed).isFalse()
+ }
+
+ @Test
+ fun isFocusable_isFalse_whenTransitioningAwayFromGlanceableHub() =
+ testScope.runTest {
+ val isFocusable by collectLastValue(underTest.isFocusable)
+
+ // Shade not expanded.
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+ // On communal scene.
+ communalRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(CommunalScenes.Communal))
+ )
+ // Open bouncer.
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+
+ keyguardTransitionRepository.sendTransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ transitionState = TransitionState.RUNNING,
+ value = 0.5f,
+ )
+ assertThat(isFocusable).isEqualTo(false)
+
+ // Transitioned to bouncer.
+ keyguardTransitionRepository.sendTransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ transitionState = TransitionState.FINISHED,
+ value = 1f,
+ )
+ assertThat(isFocusable).isEqualTo(false)
+ }
+
+ @Test
+ fun isFocusable_isFalse_whenNotOnCommunalScene() =
+ testScope.runTest {
+ val isFocusable by collectLastValue(underTest.isFocusable)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GLANCEABLE_HUB,
+ testScope = testScope,
+ )
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+ // Transitioned away from communal scene.
+ communalRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(CommunalScenes.Blank))
+ )
+
+ assertThat(isFocusable).isEqualTo(false)
+ }
+
+ @Test
+ fun isFocusable_isTrue_whenIdleOnCommunal_andShadeNotExpanded() =
+ testScope.runTest {
+ val isFocusable by collectLastValue(underTest.isFocusable)
+
+ // On communal scene.
+ communalRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(CommunalScenes.Communal))
+ )
+ // Transitioned to Glanceable hub.
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GLANCEABLE_HUB,
+ testScope = testScope,
+ )
+ // Shade not expanded.
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+
+ assertThat(isFocusable).isEqualTo(true)
+ }
+
+ @Test
+ fun isFocusable_isFalse_whenQsIsExpanded() =
+ testScope.runTest {
+ val isFocusable by collectLastValue(underTest.isFocusable)
+
+ // On communal scene.
+ communalRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(CommunalScenes.Communal))
+ )
+ // Transitioned to Glanceable hub.
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GLANCEABLE_HUB,
+ testScope = testScope,
+ )
+ // Qs is expanded.
+ shadeTestUtil.setQsExpansion(1f)
+
+ assertThat(isFocusable).isEqualTo(false)
+ }
+
private suspend fun setIsMainUser(isMainUser: Boolean) {
whenever(user.isMain).thenReturn(isMainUser)
userRepository.setUserInfos(listOf(user))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index e9dc261..20beabb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -1063,6 +1063,25 @@
faceAuthenticateIsCalled()
}
+ @Test
+ fun retryFaceAuthAfterCancel() =
+ testScope.runTest {
+ initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
+ val isAuthRunning by collectLastValue(underTest.isAuthRunning)
+
+ underTest.requestAuthenticate(FaceAuthUiEvent.FACE_AUTH_CAMERA_AVAILABLE_CHANGED)
+ underTest.cancel()
+ clearInvocations(faceManager)
+ underTest.requestAuthenticate(FaceAuthUiEvent.FACE_AUTH_CAMERA_AVAILABLE_CHANGED)
+
+ advanceTimeBy(DeviceEntryFaceAuthRepositoryImpl.DEFAULT_CANCEL_SIGNAL_TIMEOUT)
+ runCurrent()
+
+ assertThat(isAuthRunning).isEqualTo(true)
+ faceAuthenticateIsCalled()
+ }
+
private suspend fun TestScope.testGatingCheckForFaceAuth(
gatingCheckModifier: suspend () -> Unit
) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index 11f9e1c..eef2337 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -17,6 +17,9 @@
import android.content.ComponentName
import android.content.Intent
+import android.os.RemoteException
+import android.platform.test.annotations.EnableFlags
+import android.service.dreams.Flags
import android.service.dreams.IDreamOverlay
import android.service.dreams.IDreamOverlayCallback
import android.service.dreams.IDreamOverlayClient
@@ -44,7 +47,9 @@
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.data.repository.fakeCommunalRepository
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalAvailable
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.complication.ComplicationLayoutEngine
@@ -57,12 +62,14 @@
import com.android.systemui.touch.TouchInsetManager
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -70,6 +77,9 @@
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.isNull
+import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -87,6 +97,8 @@
private lateinit var lifecycleRegistry: FakeLifecycleRegistry
+ lateinit var mCommunalInteractor: CommunalInteractor
+
private lateinit var mWindowParams: WindowManager.LayoutParams
@Mock lateinit var mDreamOverlayCallback: IDreamOverlayCallback
@@ -162,6 +174,9 @@
whenever(mComplicationComponent.getComplicationHostViewController())
.thenReturn(mComplicationHostViewController)
whenever(mLifecycleOwner.registry).thenReturn(lifecycleRegistry)
+
+ mCommunalInteractor = Mockito.spy(kosmos.communalInteractor)
+
whenever(mComplicationComponentFactory.create(any(), any(), any(), any()))
.thenReturn(mComplicationComponent)
whenever(mComplicationComponent.getVisibilityController())
@@ -192,7 +207,7 @@
mStateController,
mKeyguardUpdateMonitor,
mScrimManager,
- kosmos.communalInteractor,
+ mCommunalInteractor,
mSystemDialogsCloser,
mUiEventLogger,
mTouchInsetManager,
@@ -605,6 +620,57 @@
.isTrue()
}
+ @Test
+ @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT)
+ @kotlin.Throws(RemoteException::class)
+ fun testTransitionToGlanceableHub() =
+ testScope.runTest {
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+
+ verify(mDreamOverlayCallback).onRedirectWake(false)
+ clearInvocations(mDreamOverlayCallback)
+ kosmos.setCommunalAvailable(true)
+ mMainExecutor.runAllReady()
+ runCurrent()
+ verify(mDreamOverlayCallback).onRedirectWake(true)
+ client.onWakeRequested()
+ verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), isNull())
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT)
+ @Throws(RemoteException::class)
+ fun testRedirectExit() =
+ testScope.runTest {
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ // Set communal available, verify that overlay callback is informed.
+ kosmos.setCommunalAvailable(true)
+ mMainExecutor.runAllReady()
+ runCurrent()
+ verify(mDreamOverlayCallback).onRedirectWake(true)
+
+ clearInvocations(mDreamOverlayCallback)
+
+ // Set communal unavailable, verify that overlay callback is informed.
+ kosmos.setCommunalAvailable(false)
+ mMainExecutor.runAllReady()
+ runCurrent()
+ verify(mDreamOverlayCallback).onRedirectWake(false)
+ }
+
// Tests that the bouncer closes when DreamOverlayService is told that the dream is coming to
// the front.
@Test
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 d702330..360f284 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
@@ -33,6 +33,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.os.PowerManager
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -46,6 +47,7 @@
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -317,6 +319,51 @@
}
@Test
+ @DisableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
+ fun testTransitionToGone_onWakeUp_ifPowerButtonGestureDetectedInAod_fromGone() =
+ testScope.runTest {
+ powerInteractor.setAwakeForTest()
+ transitionRepository.sendTransitionSteps(
+ from = KeyguardState.AOD,
+ to = KeyguardState.GONE,
+ testScope,
+ )
+ runCurrent()
+
+ // Make sure we're GONE.
+ assertEquals(KeyguardState.GONE, kosmos.keyguardTransitionInteractor.getFinishedState())
+
+ // Start going to AOD on first button push
+ powerInteractor.onStartedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_MIN)
+ transitionRepository.sendTransitionSteps(
+ listOf(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ value = 0f
+ ),
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.RUNNING,
+ value = 0.1f
+ ),
+ ),
+ testScope = testScope,
+ )
+
+ // Detect a power gesture and then wake up.
+ reset(transitionRepository)
+ powerInteractor.onCameraLaunchGestureDetected()
+ powerInteractor.setAwakeForTest()
+ advanceTimeBy(100) // account for debouncing
+
+ assertThat(transitionRepository)
+ .startedTransition(from = KeyguardState.AOD, to = KeyguardState.GONE)
+ }
+
+ @Test
fun testTransitionToLockscreen_onWakeUpFromAod_dismissibleKeyguard_securitySwipe() =
testScope.runTest {
kosmos.fakeKeyguardRepository.setKeyguardShowing(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
similarity index 85%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
index 0a29821..3b6f6a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,20 +12,19 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *
*/
package com.android.systemui.keyguard.domain.interactor
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
-import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.util.BurnInHelperWrapper
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
@@ -33,7 +32,10 @@
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.domain.interactor.shadeLockscreenInteractor
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.argumentCaptor
@@ -50,15 +52,18 @@
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@ExperimentalCoroutinesApi
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class UdfpsKeyguardInteractorTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class UdfpsKeyguardInteractorTest(flags: FlagsParameterization?) : SysuiTestCase() {
val kosmos = testKosmos()
val testScope = kosmos.testScope
- val configRepository = kosmos.fakeConfigurationRepository
val keyguardRepository = kosmos.fakeKeyguardRepository
+ val shadeRepository = kosmos.fakeShadeRepository
+ val shadeTestUtil by lazy { kosmos.shadeTestUtil }
private val burnInProgress = 1f
private val burnInYOffset = 20
@@ -67,7 +72,6 @@
private lateinit var bouncerRepository: KeyguardBouncerRepository
private lateinit var fakeCommandQueue: FakeCommandQueue
private lateinit var burnInInteractor: BurnInInteractor
- private lateinit var shadeRepository: FakeShadeRepository
private lateinit var powerInteractor: PowerInteractor
@Mock private lateinit var burnInHelper: BurnInHelperWrapper
@@ -75,11 +79,22 @@
private lateinit var underTest: UdfpsKeyguardInteractor
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
bouncerRepository = FakeKeyguardBouncerRepository()
- shadeRepository = FakeShadeRepository()
fakeCommandQueue = FakeCommandQueue()
burnInInteractor =
BurnInInteractor(
@@ -93,10 +108,10 @@
underTest =
UdfpsKeyguardInteractor(
- configRepository,
burnInInteractor,
kosmos.keyguardInteractor,
- shadeRepository,
+ kosmos.shadeInteractor,
+ kosmos.shadeLockscreenInteractor,
dialogManager,
)
}
@@ -183,13 +198,13 @@
val qsProgress by collectLastValue(underTest.qsProgress)
assertThat(qsProgress).isEqualTo(0f)
- shadeRepository.setQsExpansion(.22f)
+ shadeTestUtil.setQsExpansion(.22f)
assertThat(qsProgress).isEqualTo(.44f)
- shadeRepository.setQsExpansion(.5f)
+ shadeTestUtil.setQsExpansion(.5f)
assertThat(qsProgress).isEqualTo(1f)
- shadeRepository.setQsExpansion(.7f)
+ shadeTestUtil.setQsExpansion(.7f)
assertThat(qsProgress).isEqualTo(1f)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelTest.kt
new file mode 100644
index 0000000..288dc48
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AlternateBouncerToOccludedTransitionViewModelTest : SysuiTestCase() {
+ val kosmos =
+ testKosmos().apply {
+ fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
+ }
+
+ private val testScope = kosmos.testScope
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val underTest by lazy { kosmos.alternateBouncerToOccludedTransitionViewModel }
+
+ @Test
+ fun deviceEntryParentViewDisappear() =
+ testScope.runTest {
+ val values by collectValues(underTest.deviceEntryParentViewAlpha)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.2f),
+ step(0.3f),
+ step(1f),
+ ),
+ testScope,
+ )
+
+ values.forEach { assertThat(it).isEqualTo(0f) }
+ }
+
+ private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.ALTERNATE_BOUNCER,
+ to = KeyguardState.OCCLUDED,
+ value = value,
+ transitionState = state,
+ ownerName = "AlternateBouncerToOccludedTransitionViewModelTest"
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index e3eca67..030aa24 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -19,24 +19,25 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.platform.test.flag.junit.FlagsParameterization
import android.view.View
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.communalRepository
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
import com.android.systemui.statusbar.phone.dozeParameters
import com.android.systemui.statusbar.phone.screenOffAnimationController
@@ -53,32 +54,50 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
+import com.android.systemui.Flags as AConfigFlags
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class KeyguardRootViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class KeyguardRootViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
- private val keyguardRepository = kosmos.fakeKeyguardRepository
- private val communalRepository = kosmos.communalRepository
- private val screenOffAnimationController = kosmos.screenOffAnimationController
- private val deviceEntryRepository = kosmos.fakeDeviceEntryRepository
- private val notificationsKeyguardInteractor = kosmos.notificationsKeyguardInteractor
- private val dozeParameters = kosmos.dozeParameters
- private val shadeRepository = kosmos.fakeShadeRepository
+ private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
+ private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+ private val communalRepository by lazy { kosmos.communalRepository }
+ private val screenOffAnimationController by lazy { kosmos.screenOffAnimationController }
+ private val deviceEntryRepository by lazy { kosmos.fakeDeviceEntryRepository }
+ private val notificationsKeyguardInteractor by lazy { kosmos.notificationsKeyguardInteractor }
+ private val dozeParameters by lazy { kosmos.dozeParameters }
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
private val underTest by lazy { kosmos.keyguardRootViewModel }
private val viewState = ViewStateAccessor()
+ // add to init block
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return parameterizeSceneContainerFlag()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setUp() {
- mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
mSetFlagsRule.enableFlags(FLAG_NEW_AOD_TRANSITION)
- mSetFlagsRule.disableFlags(
- AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
- AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
- )
+ if (!SceneContainerFlag.isEnabled) {
+ mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
+ mSetFlagsRule.disableFlags(
+ AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
+ AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
+ )
+ }
}
@Test
@@ -336,10 +355,10 @@
testScope,
)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
assertThat(alpha).isEqualTo(1f)
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
assertThat(alpha).isEqualTo(0f)
}
@@ -356,11 +375,11 @@
)
// Open the shade.
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setQsExpansion(1f)
assertThat(alpha).isEqualTo(0f)
// Close the shade, alpha returns to 1.
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
assertThat(alpha).isEqualTo(1f)
}
@@ -377,11 +396,11 @@
)
// Open the shade.
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setQsExpansion(1f)
assertThat(alpha).isEqualTo(0f)
// Close the shade, alpha is still 0 since we're not on the lockscreen.
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
assertThat(alpha).isEqualTo(0f)
}
@@ -400,7 +419,7 @@
assertThat(alpha).isEqualTo(0f)
// Try pulling down shade and ensure the value doesn't change
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
assertThat(alpha).isEqualTo(0f)
}
@@ -419,7 +438,7 @@
assertThat(alpha).isEqualTo(0f)
// Try pulling down shade and ensure the value doesn't change
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
assertThat(alpha).isEqualTo(0f)
}
@@ -438,7 +457,7 @@
assertThat(alpha).isEqualTo(0f)
// Try pulling down shade and ensure the value doesn't change
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
assertThat(alpha).isEqualTo(0f)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
index 4907359..ec2cb04 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
@@ -16,13 +16,15 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.authController
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
import com.android.systemui.keyguard.shared.model.ClockSize
@@ -40,15 +42,29 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class LockscreenContentViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class LockscreenContentViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos: Kosmos = testKosmos()
lateinit var underTest: LockscreenContentViewModel
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setup() {
with(kosmos) {
@@ -77,6 +93,7 @@
}
@Test
+ @DisableSceneContainer
fun clockSize_withLargeClock_true() =
with(kosmos) {
testScope.runTest {
@@ -87,6 +104,7 @@
}
@Test
+ @DisableSceneContainer
fun clockSize_withSmallClock_false() =
with(kosmos) {
testScope.runTest {
@@ -109,6 +127,7 @@
}
@Test
+ @DisableSceneContainer
fun areNotificationsVisible_withSmallClock_true() =
with(kosmos) {
testScope.runTest {
@@ -119,6 +138,7 @@
}
@Test
+ @DisableSceneContainer
fun areNotificationsVisible_withLargeClock_false() =
with(kosmos) {
testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 776f1a5..bc9d257 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -33,6 +33,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.shared.model.WakefulnessState
@@ -57,6 +58,7 @@
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
+@EnableSceneContainer
class LockscreenSceneViewModelTest : SysuiTestCase() {
companion object {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
index 769a54a..13d6411 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
@@ -58,13 +58,16 @@
import com.android.systemui.util.CarrierConfigTracker
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-@TestableLooper.RunWithLooper
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class InternetTileDataInteractorTest : SysuiTestCase() {
@@ -141,6 +144,7 @@
underTest =
InternetTileDataInteractor(
context,
+ testScope.coroutineContext,
testScope.backgroundScope,
airplaneModeRepository,
connectivityRepository,
@@ -433,8 +437,44 @@
.isEqualTo(expectedCd)
}
+ /**
+ * We expect a RuntimeException because [underTest] instantiates a SignalDrawable on the
+ * provided context, and so the SignalDrawable constructor attempts to instantiate a Handler()
+ * on the mentioned context. Since that context does not have a looper assigned to it, the
+ * handler instantiation will throw a RuntimeException.
+ *
+ * TODO(b/338068066): Robolectric behavior differs in that it does not throw the exception
+ * So either we should make Robolectric behvase similar to the device test, or change this
+ * test to look for a different signal than the exception, when run by Robolectric. For now
+ * we just assume the test is not Robolectric.
+ */
+ @Test(expected = java.lang.RuntimeException::class)
+ fun mobileDefault_usesNetworkNameAndIcon_throwsRunTimeException() =
+ testScope.runTest {
+ assumeFalse(isRobolectricTest());
+
+ collectLastValue(underTest.tileData(testUser, flowOf(DataUpdateTrigger.InitialRequest)))
+
+ connectivityRepository.setMobileConnected()
+ mobileConnectionsRepository.mobileIsDefault.value = true
+ mobileConnectionRepository.apply {
+ setAllLevels(3)
+ setAllRoaming(false)
+ networkName.value = NetworkNameModel.Default("test network")
+ }
+
+ runCurrent()
+ }
+
+ /**
+ * See [mobileDefault_usesNetworkNameAndIcon_throwsRunTimeException] for description of the
+ * problem this test solves. The solution here is to assign a looper to the context via
+ * RunWithLooper. In the production code, the solution is to use a Main CoroutineContext for
+ * creating the SignalDrawable.
+ */
+ @TestableLooper.RunWithLooper
@Test
- fun mobileDefault_usesNetworkNameAndIcon() =
+ fun mobileDefault_run_withLooper_usesNetworkNameAndIcon() =
testScope.runTest {
val latest by
collectLastValue(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index d2a458c..179ba42 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -35,6 +35,7 @@
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
+import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
@@ -78,6 +79,8 @@
private val sceneBackInteractor = kosmos.sceneBackInteractor
private val sceneContainerStartable = kosmos.sceneContainerStartable
+ private val mediaDataManager = mock<MediaDataManager>()
+
private lateinit var underTest: QuickSettingsSceneViewModel
@OptIn(ExperimentalCoroutinesApi::class)
@@ -97,6 +100,7 @@
footerActionsViewModelFactory = footerActionsViewModelFactory,
footerActionsController = footerActionsController,
sceneBackInteractor = sceneBackInteractor,
+ mediaDataManager = mediaDataManager,
)
}
@@ -230,4 +234,22 @@
verify(footerActionsController, times(1)).init()
}
+
+ @Test
+ fun hasMedia_mediaVisible() {
+ testScope.runTest {
+ whenever(mediaDataManager.hasAnyMediaOrRecommendation()).thenReturn(true)
+
+ assertThat(underTest.isMediaVisible()).isTrue()
+ }
+ }
+
+ @Test
+ fun doesNotHaveMedia_mediaNotVisible() {
+ testScope.runTest {
+ whenever(mediaDataManager.hasAnyMediaOrRecommendation()).thenReturn(false)
+
+ assertThat(underTest.isMediaVisible()).isFalse()
+ }
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index 2fb8212..f58e01f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.scene.data.repository.sceneContainerRepository
import com.android.systemui.scene.sceneContainerConfig
import com.android.systemui.scene.sceneKeys
+import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.testKosmos
@@ -39,7 +40,6 @@
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -54,19 +54,46 @@
private lateinit var underTest: SceneInteractor
- @Before
- fun setUp() {
- underTest = kosmos.sceneInteractor
- }
-
@Test
fun allSceneKeys() {
+ underTest = kosmos.sceneInteractor
assertThat(underTest.allSceneKeys()).isEqualTo(kosmos.sceneKeys)
}
@Test
+ fun changeScene_toUnknownScene_doesNothing() =
+ testScope.runTest {
+ val sceneKeys =
+ listOf(
+ Scenes.QuickSettings,
+ Scenes.Shade,
+ Scenes.Lockscreen,
+ Scenes.Gone,
+ Scenes.Communal,
+ )
+ val navigationDistances =
+ mapOf(
+ Scenes.Gone to 0,
+ Scenes.Lockscreen to 0,
+ Scenes.Communal to 1,
+ Scenes.Shade to 2,
+ Scenes.QuickSettings to 3,
+ )
+ kosmos.sceneContainerConfig =
+ SceneContainerConfig(sceneKeys, Scenes.Lockscreen, navigationDistances)
+ underTest = kosmos.sceneInteractor
+ val currentScene by collectLastValue(underTest.currentScene)
+ val previousScene = currentScene
+ assertThat(previousScene).isNotEqualTo(Scenes.Bouncer)
+ underTest.changeScene(Scenes.Bouncer, "reason")
+ assertThat(currentScene).isEqualTo(previousScene)
+ }
+
+ @Test
fun changeScene() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
+
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
@@ -77,6 +104,8 @@
@Test
fun changeScene_toGoneWhenUnl_doesNotThrow() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
+
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
@@ -91,11 +120,15 @@
@Test(expected = IllegalStateException::class)
fun changeScene_toGoneWhenStillLocked_throws() =
- testScope.runTest { underTest.changeScene(Scenes.Gone, "reason") }
+ testScope.runTest {
+ underTest = kosmos.sceneInteractor
+ underTest.changeScene(Scenes.Gone, "reason")
+ }
@Test
fun sceneChanged_inDataSource() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
@@ -107,6 +140,7 @@
@Test
fun transitionState() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val underTest = kosmos.sceneContainerRepository
val transitionState =
MutableStateFlow<ObservableTransitionState>(
@@ -143,6 +177,7 @@
@Test
fun transitioningTo() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Idle(underTest.currentScene.value)
@@ -179,6 +214,7 @@
@Test
fun isTransitionUserInputOngoing_idle_false() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Idle(Scenes.Shade)
@@ -193,6 +229,7 @@
@Test
fun isTransitionUserInputOngoing_transition_true() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Transition(
@@ -213,6 +250,7 @@
@Test
fun isTransitionUserInputOngoing_updateMidTransition_false() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Transition(
@@ -244,6 +282,7 @@
@Test
fun isTransitionUserInputOngoing_updateOnIdle_false() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val transitionState =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Transition(
@@ -268,6 +307,7 @@
@Test
fun isVisible() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
val isVisible by collectLastValue(underTest.isVisible)
assertThat(isVisible).isTrue()
@@ -281,6 +321,7 @@
@Test
fun isVisible_duringRemoteUserInteraction_forcedVisible() =
testScope.runTest {
+ underTest = kosmos.sceneInteractor
underTest.setVisible(false, "reason")
val isVisible by collectLastValue(underTest.isVisible)
assertThat(isVisible).isFalse()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index e160cfc..66f7416 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -155,7 +155,6 @@
mColorExtractor,
mDumpManager,
mKeyguardStateController,
- mKosmos.getScreenOffAnimationController(),
mAuthController,
mKosmos::getShadeInteractor,
mShadeWindowLogger,
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 a023033..3408e06 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
@@ -25,13 +25,12 @@
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX
import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
-import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.NotificationContainerBounds
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.flags.BrokenWithSceneContainer
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags
import com.android.systemui.flags.andSceneContainer
@@ -51,9 +50,8 @@
import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
-import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.mockLargeScreenHeaderHelper
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
@@ -116,8 +114,8 @@
get() = kosmos.keyguardRootViewModel
val keyguardTransitionRepository
get() = kosmos.fakeKeyguardTransitionRepository
- val shadeRepository
- get() = kosmos.shadeRepository
+ val shadeTestUtil
+ get() = kosmos.shadeTestUtil
val sharedNotificationContainerInteractor
get() = kosmos.sharedNotificationContainerInteractor
val largeScreenHeaderHelper
@@ -127,7 +125,6 @@
@Before
fun setUp() {
- assertThat(SceneContainerFlag.isEnabled).isEqualTo(SceneContainerFlag.isEnabled)
overrideResource(R.bool.config_use_split_notification_shade, false)
movementFlow = MutableStateFlow(BurnInModel())
whenever(aodBurnInViewModel.movement(any())).thenReturn(movementFlow)
@@ -234,7 +231,8 @@
}
@Test
- @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, FLAG_SCENE_CONTAINER)
+ @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
+ @DisableSceneContainer
fun validateMarginTopWithLargeScreenHeader_refactorFlagOff_usesResource() =
testScope.runTest {
val headerResourceHeight = 50
@@ -273,7 +271,7 @@
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
@EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
fun validateMarginTopWithLargeScreenHeader_refactorFlagOn_usesHelper() =
testScope.runTest {
@@ -313,7 +311,6 @@
}
@Test
- @BrokenWithSceneContainer(bugId = 333132830)
fun glanceableHubAlpha_lockscreenToHub() =
testScope.runTest {
val alpha by collectLastValue(underTest.glanceableHubAlpha)
@@ -357,7 +354,7 @@
// While state is GLANCEABLE_HUB, verify alpha is restored to full if glanceable hub is
// not fully visible.
- shadeRepository.setLockscreenShadeExpansion(0.1f)
+ shadeTestUtil.setLockscreenShadeExpansion(0.1f)
assertThat(alpha).isEqualTo(1f)
}
@@ -463,14 +460,13 @@
}
@Test
- @BrokenWithSceneContainer(bugId = 333132830)
fun isOnLockscreenWithoutShade() =
testScope.runTest {
val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade)
// First on AOD
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.LOCKSCREEN,
to = KeyguardState.OCCLUDED,
@@ -482,25 +478,24 @@
showLockscreen()
// While state is LOCKSCREEN, validate variations of both shade and qs expansion
- shadeRepository.setLockscreenShadeExpansion(0.1f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0.1f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setLockscreenShadeExpansion(0.1f)
- shadeRepository.setQsExpansion(0.1f)
+ shadeTestUtil.setLockscreenShadeExpansion(0.1f)
+ shadeTestUtil.setShadeAndQsExpansion(0.1f, .9f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(0.1f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(0.1f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
assertThat(isOnLockscreenWithoutShade).isTrue()
}
@Test
- @BrokenWithSceneContainer(bugId = 333132830)
fun isOnGlanceableHubWithoutShade() =
testScope.runTest {
val isOnGlanceableHubWithoutShade by
@@ -519,25 +514,25 @@
assertThat(isOnGlanceableHubWithoutShade).isTrue()
// While state is GLANCEABLE_HUB, validate variations of both shade and qs expansion
- shadeRepository.setLockscreenShadeExpansion(0.1f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0.1f)
assertThat(isOnGlanceableHubWithoutShade).isFalse()
- shadeRepository.setLockscreenShadeExpansion(0.1f)
- shadeRepository.setQsExpansion(0.1f)
+ shadeTestUtil.setLockscreenShadeExpansion(0.1f)
+ shadeTestUtil.setShadeAndQsExpansion(0.1f, .9f)
assertThat(isOnGlanceableHubWithoutShade).isFalse()
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(0.1f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(0.1f)
assertThat(isOnGlanceableHubWithoutShade).isFalse()
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
assertThat(isOnGlanceableHubWithoutShade).isTrue()
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun boundsOnLockscreenNotInSplitShade() =
testScope.runTest {
val bounds by collectLastValue(underTest.bounds)
@@ -558,7 +553,8 @@
}
@Test
- @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, FLAG_SCENE_CONTAINER)
+ @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
+ @DisableSceneContainer
fun boundsOnLockscreenInSplitShade_refactorFlagOff_usesLargeHeaderResource() =
testScope.runTest {
val bounds by collectLastValue(underTest.bounds)
@@ -593,7 +589,7 @@
@Test
@EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun boundsOnLockscreenInSplitShade_refactorFlagOn_usesLargeHeaderHelper() =
testScope.runTest {
val bounds by collectLastValue(underTest.bounds)
@@ -621,7 +617,7 @@
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun boundsOnShade() =
testScope.runTest {
val bounds by collectLastValue(underTest.bounds)
@@ -637,7 +633,7 @@
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun boundsOnQS() =
testScope.runTest {
val bounds by collectLastValue(underTest.bounds)
@@ -682,7 +678,6 @@
}
@Test
- @BrokenWithSceneContainer(bugId = 333132830)
fun maxNotificationsOnLockscreen_DoesNotUpdateWhenUserInteracting() =
testScope.runTest {
var notificationCount = 10
@@ -700,26 +695,25 @@
assertThat(maxNotifications).isEqualTo(10)
// Shade expanding... still 10
- shadeRepository.setLockscreenShadeExpansion(0.5f)
+ shadeTestUtil.setLockscreenShadeExpansion(0.5f)
assertThat(maxNotifications).isEqualTo(10)
notificationCount = 25
// When shade is expanding by user interaction
- shadeRepository.setLegacyLockscreenShadeTracking(true)
+ shadeTestUtil.setLockscreenShadeTracking(true)
// Should still be 10, since the user is interacting
assertThat(maxNotifications).isEqualTo(10)
- shadeRepository.setLegacyLockscreenShadeTracking(false)
- shadeRepository.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setLockscreenShadeTracking(false)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
// Stopped tracking, show 25
assertThat(maxNotifications).isEqualTo(25)
}
@Test
- @BrokenWithSceneContainer(bugId = 333132830)
fun maxNotificationsOnShade() =
testScope.runTest {
val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> 10 }
@@ -739,7 +733,7 @@
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun translationYUpdatesOnKeyguardForBurnIn() =
testScope.runTest {
val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -752,7 +746,7 @@
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun translationYUpdatesOnKeyguard() =
testScope.runTest {
val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -764,7 +758,7 @@
configurationRepository.onAnyConfigurationChange()
// legacy expansion means the user is swiping up, usually for the bouncer
- shadeRepository.setLegacyShadeExpansion(0.5f)
+ shadeTestUtil.setShadeExpansion(0.5f)
showLockscreen()
@@ -773,7 +767,7 @@
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun translationYDoesNotUpdateWhenShadeIsExpanded() =
testScope.runTest {
val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -786,7 +780,7 @@
// legacy expansion means the user is swiping up, usually for the bouncer but also for
// shade collapsing
- shadeRepository.setLegacyShadeExpansion(0.5f)
+ shadeTestUtil.setShadeExpansion(0.5f)
showLockscreenWithShadeExpanded()
@@ -794,7 +788,7 @@
}
@Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
+ @DisableSceneContainer
fun updateBounds_fromKeyguardRoot() =
testScope.runTest {
val bounds by collectLastValue(underTest.bounds)
@@ -806,7 +800,6 @@
}
@Test
- @BrokenWithSceneContainer(bugId = 333132830)
fun alphaOnFullQsExpansion() =
testScope.runTest {
val viewState = ViewStateAccessor()
@@ -815,13 +808,13 @@
showLockscreenWithQSExpanded()
// Alpha fades out as QS expands
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
assertThat(alpha).isWithin(0.01f).of(0.5f)
- shadeRepository.setQsExpansion(0.9f)
+ shadeTestUtil.setQsExpansion(0.9f)
assertThat(alpha).isWithin(0.01f).of(0.1f)
// Ensure that alpha is set back to 1f when QS is fully expanded
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setQsExpansion(1f)
assertThat(alpha).isEqualTo(1f)
}
@@ -856,7 +849,7 @@
assertThat(alpha).isEqualTo(0f)
// An attempt to override by the shade should be ignored
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
assertThat(alpha).isEqualTo(0f)
}
@@ -891,7 +884,7 @@
assertThat(alpha).isEqualTo(0f)
// An attempt to override by the shade should be ignored
- shadeRepository.setQsExpansion(0.5f)
+ shadeTestUtil.setQsExpansion(0.5f)
assertThat(alpha).isEqualTo(0f)
}
@@ -914,7 +907,6 @@
}
@Test
- @BrokenWithSceneContainer(bugId = 333132830)
fun shadeCollapseFadeIn() =
testScope.runTest {
val fadeIn by collectValues(underTest.shadeCollapseFadeIn)
@@ -961,8 +953,8 @@
}
private suspend fun TestScope.showLockscreen() {
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
runCurrent()
@@ -974,8 +966,8 @@
}
private suspend fun TestScope.showDream() {
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
runCurrent()
keyguardRepository.setDreaming(true)
runCurrent()
@@ -987,8 +979,8 @@
}
private suspend fun TestScope.showLockscreenWithShadeExpanded() {
- shadeRepository.setLockscreenShadeExpansion(1f)
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
+ shadeTestUtil.setLockscreenShadeExpansion(1f)
runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
runCurrent()
@@ -1000,8 +992,8 @@
}
private suspend fun TestScope.showLockscreenWithQSExpanded() {
- shadeRepository.setLockscreenShadeExpansion(0f)
- shadeRepository.setQsExpansion(1f)
+ shadeTestUtil.setLockscreenShadeExpansion(0f)
+ shadeTestUtil.setQsExpansion(1f)
runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/EventsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/EventsTest.java
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/EventsTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/EventsTest.java
index c69f5c8..87e1f86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/EventsTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/EventsTest.java
@@ -34,12 +34,15 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import java.util.Queue;
+import platform.test.runner.parameterized.Parameter;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
/**
* Parameterized unit test for Events.logEvent.
*
@@ -51,7 +54,7 @@
* either SysuiTestCase or SysUiBaseFragmentTest.
*
*/
-@RunWith(Parameterized.class)
+@RunWith(ParameterizedAndroidJunit4.class)
@SmallTest
public class EventsTest extends SysuiTestCase {
private FakeMetricsLogger mLegacyLogger;
@@ -66,23 +69,23 @@
}
// Parameters for calling writeEvent with arbitrary args.
- @Parameterized.Parameter
+ @Parameter
public int mTag;
- @Parameterized.Parameter(1)
+ @Parameter(1)
public Object[] mArgs;
// Expect returned string exactly matches.
- @Parameterized.Parameter(2)
+ @Parameter(2)
public String mExpectedMessage;
// Expect these MetricsLogger calls.
- @Parameterized.Parameter(3)
+ @Parameter(3)
public int[] mExpectedMetrics;
// Expect this UiEvent (use null if there isn't one).
- @Parameterized.Parameter(4)
+ @Parameter(4)
public UiEventLogger.UiEventEnum mUiEvent;
@Test
@@ -108,7 +111,10 @@
}
}
- @Parameterized.Parameters(name = "{index}: {2}")
+ /**
+ * Collection of parameters for the test.
+ */
+ @Parameters(name = "{index}: {2}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{Events.EVENT_SETTINGS_CLICK, null,
@@ -217,4 +223,3 @@
});
}
}
-
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/UtilTest.java
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/UtilTest.java
index 483dc0c..d6c63af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/UtilTest.java
@@ -19,13 +19,16 @@
import android.media.MediaMetadata;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@SmallTest
+@RunWith(AndroidJUnit4.class)
public class UtilTest extends SysuiTestCase {
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
deleted file mode 100644
index 96b4dae..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.mediaoutput.domain
-
-import android.media.AudioManager
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.testKosmos
-import com.android.systemui.volume.data.repository.audioRepository
-import com.android.systemui.volume.domain.interactor.audioModeInteractor
-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)
-@RunWithLooper(setAsMainLooper = true)
-class MediaOutputAvailabilityCriteriaTest : SysuiTestCase() {
-
- private val kosmos = testKosmos()
-
- private lateinit var underTest: MediaOutputAvailabilityCriteria
-
- @Before
- fun setup() {
- underTest =
- MediaOutputAvailabilityCriteria(
- kosmos.audioModeInteractor,
- )
- }
-
- @Test
- fun notInCall_isAvailable_true() {
- with(kosmos) {
- testScope.runTest {
- audioRepository.setMode(AudioManager.MODE_NORMAL)
-
- val isAvailable by collectLastValue(underTest.isAvailable())
- runCurrent()
-
- assertThat(isAvailable).isTrue()
- }
- }
- }
-
- @Test
- fun inCall_isAvailable_false() {
- with(kosmos) {
- testScope.runTest {
- audioRepository.setMode(AudioManager.MODE_IN_CALL)
-
- val isAvailable by collectLastValue(underTest.isAvailable())
- runCurrent()
-
- assertThat(isAvailable).isFalse()
- }
- }
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
index b5c5809..64c9429 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
@@ -28,6 +28,7 @@
import com.android.systemui.volume.localMediaController
import com.android.systemui.volume.mediaControllerRepository
import com.android.systemui.volume.mediaOutputInteractor
+import com.android.systemui.volume.panel.shared.model.filterData
import com.android.systemui.volume.remoteMediaController
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -67,7 +68,8 @@
fun playbackInfo_returnsPlaybackInfo() {
with(kosmos) {
testScope.runTest {
- val session by collectLastValue(mediaOutputInteractor.defaultActiveMediaSession)
+ val session by
+ collectLastValue(mediaOutputInteractor.defaultActiveMediaSession.filterData())
runCurrent()
val info by collectLastValue(underTest.playbackInfo(session!!))
runCurrent()
@@ -81,7 +83,8 @@
fun playbackState_returnsPlaybackState() {
with(kosmos) {
testScope.runTest {
- val session by collectLastValue(mediaOutputInteractor.defaultActiveMediaSession)
+ val session by
+ collectLastValue(mediaOutputInteractor.defaultActiveMediaSession.filterData())
runCurrent()
val state by collectLastValue(underTest.playbackState(session!!))
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
index 30524d9..49f82d4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
@@ -30,6 +30,8 @@
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
+import com.android.systemui.volume.domain.interactor.audioOutputInteractor
import com.android.systemui.volume.localMediaController
import com.android.systemui.volume.localMediaRepository
import com.android.systemui.volume.mediaControllerRepository
@@ -64,6 +66,8 @@
testScope.backgroundScope,
mediaOutputActionsInteractor,
mediaDeviceSessionInteractor,
+ audioOutputInteractor,
+ audioModeInteractor,
mediaOutputInteractor,
uiEventLogger,
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
index 910f71e..4e06855 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModelTest.kt
@@ -16,22 +16,26 @@
package com.android.systemui.volume.panel.ui.viewmodel
+import android.content.Intent
+import android.content.applicationContext
import android.content.res.Configuration
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.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.policy.fakeConfigurationController
import com.android.systemui.testKosmos
import com.android.systemui.volume.panel.componentByKey
import com.android.systemui.volume.panel.componentsLayoutManager
import com.android.systemui.volume.panel.criteriaByKey
-import com.android.systemui.volume.panel.dagger.factory.KosmosVolumePanelComponentFactory
import com.android.systemui.volume.panel.mockVolumePanelUiComponentProvider
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import com.android.systemui.volume.panel.ui.layout.DefaultComponentsLayoutManager
import com.android.systemui.volume.panel.unavailableCriteria
+import com.android.systemui.volume.panel.volumePanelViewModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
@@ -51,66 +55,49 @@
private lateinit var underTest: VolumePanelViewModel
- private fun initUnderTest() {
- underTest =
- VolumePanelViewModel(
- testableResources.resources,
- KosmosVolumePanelComponentFactory(kosmos),
- kosmos.fakeConfigurationController,
+ @Test
+ fun dismissingPanel_changesVisibility() = test {
+ testScope.runTest {
+ assertThat(underTest.volumePanelState.value.isVisible).isTrue()
+
+ underTest.dismissPanel()
+ runCurrent()
+
+ assertThat(underTest.volumePanelState.value.isVisible).isFalse()
+ }
+ }
+
+ @Test
+ fun orientationChanges_panelOrientationChanges() = test {
+ testScope.runTest {
+ val volumePanelState by collectLastValue(underTest.volumePanelState)
+ testableResources.overrideConfiguration(
+ Configuration().apply { orientation = Configuration.ORIENTATION_PORTRAIT }
)
- }
+ assertThat(volumePanelState!!.orientation).isEqualTo(Configuration.ORIENTATION_PORTRAIT)
- @Test
- fun dismissingPanel_changesVisibility() {
- with(kosmos) {
- testScope.runTest {
- initUnderTest()
- assertThat(underTest.volumePanelState.value.isVisible).isTrue()
+ fakeConfigurationController.onConfigurationChanged(
+ Configuration().apply { orientation = Configuration.ORIENTATION_LANDSCAPE }
+ )
+ runCurrent()
- underTest.dismissPanel()
- runCurrent()
-
- assertThat(underTest.volumePanelState.value.isVisible).isFalse()
- }
+ assertThat(volumePanelState!!.orientation)
+ .isEqualTo(Configuration.ORIENTATION_LANDSCAPE)
}
}
@Test
- fun orientationChanges_panelOrientationChanges() {
- with(kosmos) {
- testScope.runTest {
- initUnderTest()
- val volumePanelState by collectLastValue(underTest.volumePanelState)
- testableResources.overrideConfiguration(
- Configuration().apply { orientation = Configuration.ORIENTATION_PORTRAIT }
+ fun components_areReturned() =
+ test({
+ componentByKey =
+ mapOf(
+ COMPONENT_1 to mockVolumePanelUiComponentProvider,
+ COMPONENT_2 to mockVolumePanelUiComponentProvider,
+ BOTTOM_BAR to mockVolumePanelUiComponentProvider,
)
- assertThat(volumePanelState!!.orientation)
- .isEqualTo(Configuration.ORIENTATION_PORTRAIT)
-
- fakeConfigurationController.onConfigurationChanged(
- Configuration().apply { orientation = Configuration.ORIENTATION_LANDSCAPE }
- )
- runCurrent()
-
- assertThat(volumePanelState!!.orientation)
- .isEqualTo(Configuration.ORIENTATION_LANDSCAPE)
- }
- }
- }
-
- @Test
- fun components_areReturned() {
- with(kosmos) {
+ criteriaByKey = mapOf(COMPONENT_2 to unavailableCriteria)
+ }) {
testScope.runTest {
- componentByKey =
- mapOf(
- COMPONENT_1 to mockVolumePanelUiComponentProvider,
- COMPONENT_2 to mockVolumePanelUiComponentProvider,
- BOTTOM_BAR to mockVolumePanelUiComponentProvider,
- )
- criteriaByKey = mapOf(COMPONENT_2 to unavailableCriteria)
- initUnderTest()
-
val componentsLayout by collectLastValue(underTest.componentsLayout)
runCurrent()
@@ -123,11 +110,45 @@
assertThat(componentsLayout!!.bottomBarComponent.isVisible).isTrue()
}
}
+
+ @Test
+ fun dismissPanel_dismissesPanel() = test {
+ testScope.runTest {
+ val volumePanelState by collectLastValue(underTest.volumePanelState)
+ underTest.dismissPanel()
+ runCurrent()
+
+ assertThat(volumePanelState!!.isVisible).isFalse()
+ }
}
+ @Test
+ fun dismissBroadcast_dismissesPanel() = test {
+ testScope.runTest {
+ runCurrent() // run the flows to let allow the receiver to be registered
+ val volumePanelState by collectLastValue(underTest.volumePanelState)
+ broadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ applicationContext,
+ Intent(DISMISS_ACTION),
+ )
+ runCurrent()
+
+ assertThat(volumePanelState!!.isVisible).isFalse()
+ }
+ }
+
+ private fun test(setup: Kosmos.() -> Unit = {}, test: Kosmos.() -> Unit) =
+ with(kosmos) {
+ setup()
+ underTest = volumePanelViewModel
+ test()
+ }
+
private companion object {
const val BOTTOM_BAR: VolumePanelComponentKey = "test_bottom_bar"
const val COMPONENT_1: VolumePanelComponentKey = "test_component:1"
const val COMPONENT_2: VolumePanelComponentKey = "test_component:2"
+
+ const val DISMISS_ACTION = "com.android.systemui.action.DISMISS_VOLUME_PANEL_DIALOG"
}
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
index 3b6b5a0..2a8f1b5 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
@@ -66,6 +66,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
+ android:importantForAccessibility="noHideDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
@@ -127,4 +128,4 @@
</androidx.constraintlayout.motion.widget.MotionLayout>
-</com.android.keyguard.KeyguardPasswordView>
\ No newline at end of file
+</com.android.keyguard.KeyguardPasswordView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index 5aac653..76f6f59 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -31,6 +31,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
+ android:importantForAccessibility="noHideDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml
index 6780e57..5879c11 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml
@@ -67,6 +67,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
+ android:importantForAccessibility="noHideDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
@@ -107,4 +108,4 @@
</androidx.constraintlayout.motion.widget.MotionLayout>
-</com.android.keyguard.KeyguardPatternView>
\ No newline at end of file
+</com.android.keyguard.KeyguardPatternView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
index d991581..3f7b028 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
@@ -35,6 +35,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
+ android:importantForAccessibility="noHideDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml
index 6c79d5a..b464fb3 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml
@@ -74,6 +74,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
+ android:importantForAccessibility="noHideDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
@@ -241,4 +242,4 @@
</androidx.constraintlayout.motion.widget.MotionLayout>
-</com.android.keyguard.KeyguardPINView>
\ No newline at end of file
+</com.android.keyguard.KeyguardPINView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index f3cd9e4..2158073 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -32,6 +32,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
+ android:importantForAccessibility="noHideDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/packages/SystemUI/res-product/values-or/strings.xml b/packages/SystemUI/res-product/values-or/strings.xml
index 5d9345b..a89dd7b 100644
--- a/packages/SystemUI/res-product/values-or/strings.xml
+++ b/packages/SystemUI/res-product/values-or/strings.xml
@@ -30,9 +30,9 @@
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ଆପଣ ଫୋନ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଫୋନ୍କୁ ରିସେଟ୍ କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ଆପଣ ଟାବ୍ଲେଟ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଟାବ୍ଲେଟ୍ଟି ରିସେଟ୍ କରିଦିଆଯିବ, ଫଳରେ ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ଆପଣ ଫୋନ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଫୋନ୍ଟି ରିସେଟ୍ କରିଦିଆଯିବ, ଫଳରେ ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ଆପଣ ଟାବ୍ଲେଟ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଉପଯୋଗକର୍ତ୍ତା ପ୍ରୋଫାଇଲ୍କୁ କାଢ଼ିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ଆପଣ ଫୋନ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଉପଯୋଗକର୍ତ୍ତା ପ୍ରୋଫାଇଲ୍କୁ କାଢ଼ିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
- <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ଆପଣ ଟାବ୍ଲେଟ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ଆପଣ ଟାବଲେଟକୁ ଅନଲକ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଭୁଲ ପ୍ରୟାସ ପରେ, ଏହି ୟୁଜର ପ୍ରୋଫାଇଲ୍କୁ କାଢ଼ି ଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ୟୁଜର ଡାଟା ଡିଲିଟ ହୋଇଯିବ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ଆପଣ ଫୋନକୁ ଅନଲକ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଭୁଲ ପ୍ରୟାସ ପରେ, ଏହି ୟୁଜର ପ୍ରୋଫାଇଲକୁ କାଢ଼ି ଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ୟୁଜର ଡାଟା ଡିଲିଟ ହୋଇଯିବ।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ଆପଣ ଟାବଲେଟକୁ ଅନଲକ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ୟୁଜରଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ ହୋଇଯିବ।"</string>
<string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ଆପଣ ଫୋନ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ୍ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
<string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ଆପଣ ଟାବ୍ଲେଟ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ୱାର୍କ ପ୍ରୋଫାଇଲ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
<string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ଆପଣ ଫୋନ୍କୁ ଅନ୍ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ୱାର୍କ ପ୍ରୋଫାଇଲ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
diff --git a/packages/SystemUI/res/drawable/ic_satellite_connected_0.xml b/packages/SystemUI/res/drawable/ic_satellite_connected_0.xml
index 045c19e..65d6e28 100644
--- a/packages/SystemUI/res/drawable/ic_satellite_connected_0.xml
+++ b/packages/SystemUI/res/drawable/ic_satellite_connected_0.xml
@@ -14,36 +14,20 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="16.0"
+ android:viewportHeight="16.0">
<path
- android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z"
+ android:pathData="M15.632,8H14.902C14.707,8 14.553,8.155 14.543,8.35C14.367,11.692 11.693,14.417 8.356,14.552C8.158,14.56 8,14.712 8,14.909V15.552C8,15.84 8.172,16.009 8.377,16C12.493,15.808 15.808,12.494 16,8.378C16.009,8.172 15.837,8 15.632,8Z"
+ android:fillAlpha="0.18"
android:fillColor="#fff"/>
<path
- android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z"
+ android:pathData="M12.643,8C12.932,8 13.105,8.175 13.09,8.382C12.903,10.892 10.892,12.903 8.382,13.09C8.175,13.105 8,12.93 8,12.723V11.993C8,11.798 8.153,11.648 8.347,11.63C10.089,11.467 11.546,10.092 11.645,8.362C11.657,8.163 11.807,8 12.006,8L12.643,8Z"
+ android:fillAlpha="0.18"
android:fillColor="#fff"/>
<path
- android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M11,22.48V21.48C11,21.21 11.22,21 11.49,20.99C16.63,20.8 20.75,16.62 20.99,11.48C21,11.21 21.21,11 21.48,11H22.48C22.76,11 23,11.24 22.99,11.52C22.72,17.73 17.73,22.73 11.52,22.99C11.24,23 11,22.77 11,22.48Z"
- android:fillAlpha="0.3"
- android:fillColor="#fff"/>
- <path
- android:pathData="M11,18.98V17.98C11,17.71 11.21,17.51 11.48,17.49C14.69,17.26 17.33,14.7 17.49,11.49C17.5,11.22 17.71,11.01 17.98,11.01H18.79C19.26,11.01 19.5,11.25 19.48,11.53C19.22,15.8 15.79,19.23 11.52,19.49C11.24,19.51 11,19.27 11,18.99V18.98Z"
- android:fillAlpha="0.3"
+ android:pathData="M7.743,10.057L6.14,8.451L5.205,9.386L6.105,10.266C6.684,10.832 6.69,11.76 6.119,12.333L5.065,13.391C4.78,13.676 4.407,13.818 4.035,13.818C3.662,13.818 3.289,13.676 3.004,13.391L0.425,10.807C-0.136,10.245 -0.143,9.338 0.41,8.768L1.404,7.716C1.69,7.421 2.07,7.273 2.45,7.273C2.817,7.273 3.184,7.411 3.467,7.688L4.425,8.624L5.369,7.68L1.712,4.026C1.57,3.884 1.57,3.654 1.712,3.512L3.513,1.711C3.655,1.57 3.885,1.57 4.027,1.711L7.684,5.366L8.608,4.442L7.701,3.534C7.14,2.972 7.134,2.065 7.686,1.495L8.68,0.443C8.966,0.148 9.346,0 9.726,0C10.093,0 10.46,0.138 10.743,0.415L13.381,2.992C13.959,3.557 13.965,4.488 13.394,5.061L12.341,6.118C12.056,6.403 11.684,6.545 11.311,6.545C10.938,6.545 10.565,6.403 10.281,6.118L9.379,5.214L8.456,6.137L10.059,7.743C10.2,7.885 10.2,8.115 10.058,8.257L8.257,10.057C8.115,10.199 7.885,10.199 7.743,10.057ZM10.412,4.182L11.053,4.83C11.195,4.973 11.427,4.974 11.569,4.831L12.104,4.294C12.247,4.151 12.245,3.919 12.101,3.777L11.451,3.142L10.412,4.182ZM8.99,2.744L9.645,3.406L10.671,2.379L9.989,1.713C9.844,1.571 9.61,1.576 9.471,1.724L8.984,2.239C8.85,2.381 8.852,2.604 8.99,2.744ZM3.395,9.653L2.713,8.986C2.568,8.844 2.334,8.849 2.194,8.997L1.708,9.512C1.574,9.654 1.576,9.878 1.714,10.017L2.369,10.679L3.395,9.653ZM4.825,11.051L4.176,10.416L3.136,11.455L3.777,12.103C3.919,12.247 4.151,12.247 4.293,12.104L4.828,11.567C4.971,11.424 4.969,11.192 4.825,11.051Z"
android:fillColor="#fff"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_satellite_connected_1.xml b/packages/SystemUI/res/drawable/ic_satellite_connected_1.xml
index 5e012ab..0399b81 100644
--- a/packages/SystemUI/res/drawable/ic_satellite_connected_1.xml
+++ b/packages/SystemUI/res/drawable/ic_satellite_connected_1.xml
@@ -16,34 +16,18 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="16.0"
+ android:viewportHeight="16.0">
<path
- android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z"
+ android:pathData="M15.632,8H14.902C14.707,8 14.553,8.155 14.543,8.35C14.367,11.692 11.693,14.417 8.356,14.552C8.158,14.56 8,14.712 8,14.909V15.552C8,15.84 8.172,16.009 8.377,16C12.493,15.808 15.808,12.494 16,8.378C16.009,8.172 15.837,8 15.632,8Z"
+ android:fillAlpha="0.18"
android:fillColor="#fff"/>
<path
- android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z"
+ android:pathData="M12.643,8C12.932,8 13.105,8.175 13.09,8.382C12.903,10.892 10.892,12.903 8.382,13.09C8.175,13.105 8,12.93 8,12.723V11.993C8,11.798 8.153,11.648 8.347,11.63C10.089,11.467 11.546,10.092 11.645,8.362C11.657,8.163 11.807,8 12.006,8L12.643,8Z"
android:fillColor="#fff"/>
<path
- android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M11,22.48V21.48C11,21.21 11.22,21 11.49,20.99C16.63,20.8 20.75,16.62 20.99,11.48C21,11.21 21.21,11 21.48,11H22.48C22.76,11 23,11.24 22.99,11.52C22.72,17.73 17.73,22.73 11.52,22.99C11.24,23 11,22.77 11,22.48Z"
- android:fillAlpha="0.3"
- android:fillColor="#fff"/>
- <path
- android:pathData="M11,18.98V17.98C11,17.71 11.21,17.51 11.48,17.49C14.69,17.26 17.33,14.7 17.49,11.49C17.5,11.22 17.71,11.01 17.98,11.01H18.79C19.26,11.01 19.5,11.25 19.48,11.53C19.22,15.8 15.79,19.23 11.52,19.49C11.24,19.51 11,19.27 11,18.99V18.98Z"
+ android:pathData="M7.743,10.057L6.14,8.451L5.205,9.386L6.105,10.266C6.684,10.832 6.69,11.76 6.119,12.333L5.065,13.391C4.78,13.676 4.407,13.818 4.035,13.818C3.662,13.818 3.289,13.676 3.004,13.391L0.425,10.807C-0.136,10.245 -0.143,9.338 0.41,8.768L1.404,7.716C1.69,7.421 2.07,7.273 2.45,7.273C2.817,7.273 3.184,7.411 3.467,7.688L4.425,8.624L5.369,7.68L1.712,4.026C1.57,3.884 1.57,3.654 1.712,3.512L3.513,1.711C3.655,1.57 3.885,1.57 4.027,1.711L7.684,5.366L8.608,4.442L7.701,3.534C7.14,2.972 7.134,2.065 7.686,1.495L8.68,0.443C8.966,0.148 9.346,0 9.726,0C10.093,0 10.46,0.138 10.743,0.415L13.381,2.992C13.959,3.557 13.965,4.488 13.394,5.061L12.341,6.118C12.056,6.403 11.684,6.545 11.311,6.545C10.938,6.545 10.565,6.403 10.281,6.118L9.379,5.214L8.456,6.137L10.059,7.743C10.2,7.885 10.2,8.115 10.058,8.257L8.257,10.057C8.115,10.199 7.885,10.199 7.743,10.057ZM10.412,4.182L11.053,4.83C11.195,4.973 11.427,4.974 11.569,4.831L12.104,4.294C12.247,4.151 12.245,3.919 12.101,3.777L11.451,3.142L10.412,4.182ZM8.99,2.744L9.645,3.406L10.671,2.379L9.989,1.713C9.844,1.571 9.61,1.576 9.471,1.724L8.984,2.239C8.85,2.381 8.852,2.604 8.99,2.744ZM3.395,9.653L2.713,8.986C2.568,8.844 2.334,8.849 2.194,8.997L1.708,9.512C1.574,9.654 1.576,9.878 1.714,10.017L2.369,10.679L3.395,9.653ZM4.825,11.051L4.176,10.416L3.136,11.455L3.777,12.103C3.919,12.247 4.151,12.247 4.293,12.104L4.828,11.567C4.971,11.424 4.969,11.192 4.825,11.051Z"
android:fillColor="#fff"/>
</vector>
-
diff --git a/packages/SystemUI/res/drawable/ic_satellite_connected_2.xml b/packages/SystemUI/res/drawable/ic_satellite_connected_2.xml
index d8a9a70..b0acbdc 100644
--- a/packages/SystemUI/res/drawable/ic_satellite_connected_2.xml
+++ b/packages/SystemUI/res/drawable/ic_satellite_connected_2.xml
@@ -16,32 +16,17 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="16.0"
+ android:viewportHeight="16.0">
<path
- android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z"
+ android:pathData="M15.632,8H14.902C14.707,8 14.553,8.155 14.543,8.35C14.367,11.692 11.693,14.417 8.356,14.552C8.158,14.56 8,14.712 8,14.909V15.552C8,15.84 8.172,16.009 8.377,16C12.493,15.808 15.808,12.494 16,8.378C16.009,8.172 15.837,8 15.632,8Z"
android:fillColor="#fff"/>
<path
- android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z"
+ android:pathData="M12.643,8C12.932,8 13.105,8.175 13.09,8.382C12.903,10.892 10.892,12.903 8.382,13.09C8.175,13.105 8,12.93 8,12.723V11.993C8,11.798 8.153,11.648 8.347,11.63C10.089,11.467 11.546,10.092 11.645,8.362C11.657,8.163 11.807,8 12.006,8L12.643,8Z"
android:fillColor="#fff"/>
<path
- android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M11,22.48V21.48C11,21.21 11.22,21 11.49,20.99C16.63,20.8 20.75,16.62 20.99,11.48C21,11.21 21.21,11 21.48,11H22.48C22.76,11 23,11.24 22.99,11.52C22.72,17.73 17.73,22.73 11.52,22.99C11.24,23 11,22.77 11,22.48Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M11,18.98V17.98C11,17.71 11.21,17.51 11.48,17.49C14.69,17.26 17.33,14.7 17.49,11.49C17.5,11.22 17.71,11.01 17.98,11.01H18.79C19.26,11.01 19.5,11.25 19.48,11.53C19.22,15.8 15.79,19.23 11.52,19.49C11.24,19.51 11,19.27 11,18.99V18.98Z"
+ android:pathData="M7.743,10.057L6.14,8.451L5.205,9.386L6.105,10.266C6.684,10.832 6.69,11.76 6.119,12.333L5.065,13.391C4.78,13.676 4.407,13.818 4.035,13.818C3.662,13.818 3.289,13.676 3.004,13.391L0.425,10.807C-0.136,10.245 -0.143,9.338 0.41,8.768L1.404,7.716C1.69,7.421 2.07,7.273 2.45,7.273C2.817,7.273 3.184,7.411 3.467,7.688L4.425,8.624L5.369,7.68L1.712,4.026C1.57,3.884 1.57,3.654 1.712,3.512L3.513,1.711C3.655,1.57 3.885,1.57 4.027,1.711L7.684,5.366L8.608,4.442L7.701,3.534C7.14,2.972 7.134,2.065 7.686,1.495L8.68,0.443C8.966,0.148 9.346,0 9.726,0C10.093,0 10.46,0.138 10.743,0.415L13.381,2.992C13.959,3.557 13.965,4.488 13.394,5.061L12.341,6.118C12.056,6.403 11.684,6.545 11.311,6.545C10.938,6.545 10.565,6.403 10.281,6.118L9.379,5.214L8.456,6.137L10.059,7.743C10.2,7.885 10.2,8.115 10.058,8.257L8.257,10.057C8.115,10.199 7.885,10.199 7.743,10.057ZM10.412,4.182L11.053,4.83C11.195,4.973 11.427,4.974 11.569,4.831L12.104,4.294C12.247,4.151 12.245,3.919 12.101,3.777L11.451,3.142L10.412,4.182ZM8.99,2.744L9.645,3.406L10.671,2.379L9.989,1.713C9.844,1.571 9.61,1.576 9.471,1.724L8.984,2.239C8.85,2.381 8.852,2.604 8.99,2.744ZM3.395,9.653L2.713,8.986C2.568,8.844 2.334,8.849 2.194,8.997L1.708,9.512C1.574,9.654 1.576,9.878 1.714,10.017L2.369,10.679L3.395,9.653ZM4.825,11.051L4.176,10.416L3.136,11.455L3.777,12.103C3.919,12.247 4.151,12.247 4.293,12.104L4.828,11.567C4.971,11.424 4.969,11.192 4.825,11.051Z"
android:fillColor="#fff"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_satellite_not_connected.xml b/packages/SystemUI/res/drawable/ic_satellite_not_connected.xml
index a80d3b4..2cab043 100644
--- a/packages/SystemUI/res/drawable/ic_satellite_not_connected.xml
+++ b/packages/SystemUI/res/drawable/ic_satellite_not_connected.xml
@@ -16,28 +16,11 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:alpha="0.3"
- >
+ android:width="14dp"
+ android:height="14dp"
+ android:viewportWidth="14.0"
+ android:viewportHeight="14.0">
<path
- android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z"
- android:fillColor="#fff"/>
- <path
- android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z"
+ android:pathData="M7.743,10.057L6.14,8.451L5.205,9.386L6.105,10.266C6.684,10.832 6.69,11.76 6.119,12.333L5.065,13.391C4.78,13.676 4.407,13.818 4.035,13.818C3.662,13.818 3.289,13.676 3.004,13.391L0.425,10.807C-0.136,10.245 -0.143,9.338 0.41,8.768L1.404,7.716C1.69,7.421 2.07,7.273 2.45,7.273C2.817,7.273 3.184,7.411 3.467,7.688L4.425,8.624L5.369,7.68L1.712,4.026C1.57,3.884 1.57,3.654 1.712,3.512L3.513,1.711C3.655,1.57 3.885,1.57 4.027,1.711L7.684,5.366L8.608,4.442L7.701,3.534C7.14,2.972 7.134,2.065 7.686,1.495L8.68,0.443C8.966,0.148 9.346,0 9.726,0C10.093,0 10.46,0.138 10.743,0.415L13.381,2.992C13.959,3.557 13.965,4.488 13.394,5.061L12.341,6.118C12.056,6.403 11.684,6.545 11.311,6.545C10.938,6.545 10.565,6.403 10.281,6.118L9.379,5.214L8.456,6.137L10.059,7.743C10.2,7.885 10.2,8.115 10.058,8.257L8.257,10.057C8.115,10.199 7.885,10.199 7.743,10.057ZM10.412,4.182L11.053,4.83C11.195,4.973 11.427,4.974 11.569,4.831L12.104,4.294C12.247,4.151 12.245,3.919 12.101,3.777L11.451,3.142L10.412,4.182ZM8.99,2.744L9.645,3.406L10.671,2.379L9.989,1.713C9.844,1.571 9.61,1.576 9.471,1.724L8.984,2.239C8.85,2.381 8.852,2.604 8.99,2.744ZM3.395,9.653L2.713,8.986C2.568,8.844 2.334,8.849 2.194,8.997L1.708,9.512C1.574,9.654 1.576,9.878 1.714,10.017L2.369,10.679L3.395,9.653ZM4.825,11.051L4.176,10.416L3.136,11.455L3.777,12.103C3.919,12.247 4.151,12.247 4.293,12.104L4.828,11.567C4.971,11.424 4.969,11.192 4.825,11.051Z"
android:fillColor="#fff"/>
</vector>
diff --git a/packages/SystemUI/res/layout-land/auth_credential_password_pin_content_view.xml b/packages/SystemUI/res/layout-land/auth_credential_password_pin_content_view.xml
index 1517f83..f1b0795 100644
--- a/packages/SystemUI/res/layout-land/auth_credential_password_pin_content_view.xml
+++ b/packages/SystemUI/res/layout-land/auth_credential_password_pin_content_view.xml
@@ -97,7 +97,7 @@
<Button
android:id="@+id/emergencyCallButton"
- style="@style/AuthCredentialEmergencyButtonStyle"
+ style="@style/AuthNonBioCredentialEmergencyButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
diff --git a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
index dd0c584..bbf70b6 100644
--- a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
+++ b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
@@ -99,7 +99,7 @@
<Button
android:id="@+id/emergencyCallButton"
- style="@style/AuthCredentialEmergencyButtonStyle"
+ style="@style/AuthNonBioCredentialEmergencyButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="35dp"
diff --git a/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml
index dabfe9d..f644584f 100644
--- a/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml
+++ b/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml
@@ -19,12 +19,9 @@
<View
android:id="@+id/panel"
+ style="@style/AuthCredentialPanelStyle"
android:layout_width="0dp"
android:layout_height="0dp"
- android:background="?androidprv:attr/materialColorSurfaceBright"
- android:clickable="true"
- android:clipToOutline="true"
- android:importantForAccessibility="no"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
android:visibility="visible"
@@ -177,7 +174,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
- android:accessibilityLiveRegion="polite"
+ android:accessibilityLiveRegion="assertive"
android:fadingEdge="horizontal"
android:gravity="center_horizontal"
android:scrollHorizontally="true"
diff --git a/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml
index 240abab..46b8e46 100644
--- a/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml
+++ b/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml
@@ -19,13 +19,9 @@
<View
android:id="@+id/panel"
+ style="@style/AuthCredentialPanelStyle"
android:layout_width="0dp"
android:layout_height="0dp"
- android:background="?androidprv:attr/materialColorSurfaceBright"
- android:clickable="true"
- android:clipToOutline="true"
- android:importantForAccessibility="no"
- android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/rightGuideline"
app:layout_constraintStart_toStartOf="@+id/leftGuideline"
@@ -156,7 +152,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
- android:accessibilityLiveRegion="polite"
+ android:accessibilityLiveRegion="assertive"
android:fadingEdge="horizontal"
android:gravity="center_horizontal"
android:scrollHorizontally="true"
diff --git a/packages/SystemUI/res/layout/auth_container_view.xml b/packages/SystemUI/res/layout/auth_container_view.xml
index 2bd2e64..2a1ce1f 100644
--- a/packages/SystemUI/res/layout/auth_container_view.xml
+++ b/packages/SystemUI/res/layout/auth_container_view.xml
@@ -15,6 +15,7 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -29,7 +30,7 @@
android:id="@+id/panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?android:attr/colorBackgroundFloating"
+ android:background="?androidprv:attr/materialColorSurfaceContainer"
android:elevation="@dimen/biometric_dialog_elevation"/>
<ScrollView
diff --git a/packages/SystemUI/res/layout/auth_credential_password_pin_content_view.xml b/packages/SystemUI/res/layout/auth_credential_password_pin_content_view.xml
index 9f4fcb3..32fef39 100644
--- a/packages/SystemUI/res/layout/auth_credential_password_pin_content_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_password_pin_content_view.xml
@@ -98,7 +98,7 @@
<Button
android:id="@+id/emergencyCallButton"
- style="@style/AuthCredentialEmergencyButtonStyle"
+ style="@style/AuthNonBioCredentialEmergencyButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
diff --git a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
index baeb94e..8a60787 100644
--- a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
@@ -94,7 +94,7 @@
<Button
android:id="@+id/emergencyCallButton"
- style="@style/AuthCredentialEmergencyButtonStyle"
+ style="@style/AuthNonBioCredentialEmergencyButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
diff --git a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
index 8e3cf4d..d51fe58 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
@@ -2,7 +2,6 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/biometric_prompt_constraint_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -19,13 +18,9 @@
<View
android:id="@+id/panel"
+ style="@style/AuthCredentialPanelStyle"
android:layout_width="0dp"
android:layout_height="0dp"
- android:background="?androidprv:attr/materialColorSurfaceBright"
- android:clickable="true"
- android:clipToOutline="true"
- android:importantForAccessibility="no"
- android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/rightGuideline"
app:layout_constraintStart_toStartOf="@id/leftGuideline"
@@ -47,7 +42,7 @@
android:layout_height="wrap_content"
android:fillViewport="true"
android:fadeScrollbars="false"
- android:paddingBottom="36dp"
+ android:paddingBottom="24dp"
android:paddingHorizontal="24dp"
android:paddingTop="24dp"
app:layout_constrainedHeight="true"
@@ -155,7 +150,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
- android:accessibilityLiveRegion="polite"
+ android:accessibilityLiveRegion="assertive"
android:fadingEdge="horizontal"
android:gravity="center_horizontal"
android:scrollHorizontally="true"
diff --git a/packages/SystemUI/res/layout/screenshot_shelf.xml b/packages/SystemUI/res/layout/screenshot_shelf.xml
index 79b82bf..7adfa6c 100644
--- a/packages/SystemUI/res/layout/screenshot_shelf.xml
+++ b/packages/SystemUI/res/layout/screenshot_shelf.xml
@@ -20,133 +20,138 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <FrameLayout
- android:id="@+id/actions_container_background"
- android:visibility="gone"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:elevation="4dp"
- android:background="@drawable/shelf_action_chip_container_background"
- android:layout_marginHorizontal="@dimen/overlay_action_container_margin_horizontal"
- android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline"
- >
- <HorizontalScrollView
- android:id="@+id/actions_container"
- android:layout_width="wrap_content"
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/screenshot_static"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <FrameLayout
+ android:id="@+id/actions_container_background"
+ android:visibility="gone"
android:layout_height="wrap_content"
- android:layout_marginVertical="@dimen/overlay_action_container_padding_vertical"
- android:layout_marginHorizontal="@dimen/overlay_action_chip_margin_start"
- android:background="@drawable/shelf_action_container_clipping_shape"
- android:clipToOutline="true"
- android:scrollbars="none">
- <LinearLayout
- android:id="@+id/screenshot_actions"
+ android:layout_width="wrap_content"
+ android:elevation="4dp"
+ android:background="@drawable/shelf_action_chip_container_background"
+ android:layout_marginHorizontal="@dimen/overlay_action_container_margin_horizontal"
+ android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
+ >
+ <HorizontalScrollView
+ android:id="@+id/actions_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:showDividers="middle"
- android:divider="@drawable/shelf_action_chip_divider"
- android:animateLayoutChanges="true"
- />
- </HorizontalScrollView>
- </FrameLayout>
- <View
- android:id="@+id/screenshot_preview_border"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
- android:layout_marginTop="@dimen/overlay_border_width_neg"
- android:layout_marginEnd="@dimen/overlay_border_width_neg"
- android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin"
- android:elevation="4dp"
- android:background="@drawable/overlay_border"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="@id/screenshot_preview"
- app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
- app:layout_constraintBottom_toTopOf="@id/actions_container_background"/>
- <ImageView
- android:id="@+id/screenshot_preview"
- android:layout_width="@dimen/overlay_x_scale"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/overlay_border_width"
- android:layout_marginBottom="@dimen/overlay_border_width"
- android:layout_gravity="center"
- android:elevation="4dp"
- android:contentDescription="@string/screenshot_edit_description"
- android:scaleType="fitEnd"
- android:background="@drawable/overlay_preview_background"
- android:adjustViewBounds="true"
- android:clickable="true"
- app:layout_constraintStart_toStartOf="@id/screenshot_preview_border"
- app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"/>
- <ImageView
- android:id="@+id/screenshot_badge"
- android:layout_width="56dp"
- android:layout_height="56dp"
- android:visibility="gone"
- android:elevation="5dp"
- app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"
- app:layout_constraintEnd_toEndOf="@id/screenshot_preview_border"/>
- <FrameLayout
- android:id="@+id/screenshot_dismiss_button"
- android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
- android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
- android:elevation="7dp"
- android:visibility="gone"
- app:layout_constraintStart_toEndOf="@id/screenshot_preview"
- app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
- app:layout_constraintTop_toTopOf="@id/screenshot_preview"
- app:layout_constraintBottom_toTopOf="@id/screenshot_preview"
- android:contentDescription="@string/screenshot_dismiss_description">
+ android:layout_marginVertical="@dimen/overlay_action_container_padding_vertical"
+ android:layout_marginHorizontal="@dimen/overlay_action_chip_margin_start"
+ android:background="@drawable/shelf_action_container_clipping_shape"
+ android:clipToOutline="true"
+ android:scrollbars="none">
+ <LinearLayout
+ android:id="@+id/screenshot_actions"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:showDividers="middle"
+ android:divider="@drawable/shelf_action_chip_divider"
+ android:animateLayoutChanges="true"
+ />
+ </HorizontalScrollView>
+ </FrameLayout>
+ <View
+ android:id="@+id/screenshot_preview_border"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
+ android:layout_marginTop="@dimen/overlay_border_width_neg"
+ android:layout_marginEnd="@dimen/overlay_border_width_neg"
+ android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin"
+ android:elevation="4dp"
+ android:background="@drawable/overlay_border"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="@id/screenshot_preview"
+ app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
+ app:layout_constraintBottom_toTopOf="@id/actions_container_background"/>
<ImageView
- android:id="@+id/screenshot_dismiss_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_margin="@dimen/overlay_dismiss_button_margin"
- android:background="@drawable/circular_background"
- android:backgroundTint="?androidprv:attr/materialColorPrimary"
- android:tint="?androidprv:attr/materialColorOnPrimary"
- android:padding="4dp"
- android:src="@drawable/ic_close"/>
- </FrameLayout>
- <ImageView
- android:id="@+id/screenshot_scrollable_preview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scaleType="matrix"
- android:visibility="gone"
- app:layout_constraintStart_toStartOf="@id/screenshot_preview"
- app:layout_constraintTop_toTopOf="@id/screenshot_preview"
- android:elevation="7dp"/>
+ android:id="@+id/screenshot_preview"
+ android:layout_width="@dimen/overlay_x_scale"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/overlay_border_width"
+ android:layout_marginBottom="@dimen/overlay_border_width"
+ android:layout_gravity="center"
+ android:elevation="4dp"
+ android:contentDescription="@string/screenshot_edit_description"
+ android:scaleType="fitEnd"
+ android:background="@drawable/overlay_preview_background"
+ android:adjustViewBounds="true"
+ android:clickable="true"
+ app:layout_constraintStart_toStartOf="@id/screenshot_preview_border"
+ app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"/>
+ <ImageView
+ android:id="@+id/screenshot_badge"
+ android:layout_width="56dp"
+ android:layout_height="56dp"
+ android:visibility="gone"
+ android:elevation="5dp"
+ app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"
+ app:layout_constraintEnd_toEndOf="@id/screenshot_preview_border"/>
+ <FrameLayout
+ android:id="@+id/screenshot_dismiss_button"
+ android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
+ android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
+ android:elevation="7dp"
+ android:visibility="gone"
+ app:layout_constraintStart_toEndOf="@id/screenshot_preview"
+ app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
+ app:layout_constraintTop_toTopOf="@id/screenshot_preview"
+ app:layout_constraintBottom_toTopOf="@id/screenshot_preview"
+ android:contentDescription="@string/screenshot_dismiss_description">
+ <ImageView
+ android:id="@+id/screenshot_dismiss_image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="@dimen/overlay_dismiss_button_margin"
+ android:background="@drawable/circular_background"
+ android:backgroundTint="?androidprv:attr/materialColorPrimary"
+ android:tint="?androidprv:attr/materialColorOnPrimary"
+ android:padding="4dp"
+ android:src="@drawable/ic_close"/>
+ </FrameLayout>
+ <ImageView
+ android:id="@+id/screenshot_scrollable_preview"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="matrix"
+ android:visibility="gone"
+ app:layout_constraintStart_toStartOf="@id/screenshot_preview"
+ app:layout_constraintTop_toTopOf="@id/screenshot_preview"
+ android:elevation="7dp"/>
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- app:layout_constraintGuide_end="0dp" />
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/guideline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ app:layout_constraintGuide_end="0dp" />
- <FrameLayout
- android:id="@+id/screenshot_message_container"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="@dimen/overlay_action_container_margin_horizontal"
- android:layout_marginTop="4dp"
- android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom"
- android:paddingHorizontal="@dimen/overlay_action_container_padding_end"
- android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
- android:elevation="4dp"
- android:background="@drawable/action_chip_container_background"
- android:visibility="gone"
- app:layout_constraintTop_toBottomOf="@id/guideline"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintWidth_max="450dp"
- app:layout_constraintHorizontal_bias="0">
- <include layout="@layout/screenshot_work_profile_first_run" />
- <include layout="@layout/screenshot_detection_notice" />
- </FrameLayout>
+ <FrameLayout
+ android:id="@+id/screenshot_message_container"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="@dimen/overlay_action_container_margin_horizontal"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom"
+ android:paddingHorizontal="@dimen/overlay_action_container_padding_end"
+ android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
+ android:elevation="4dp"
+ android:background="@drawable/action_chip_container_background"
+ android:visibility="gone"
+ app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintWidth_max="450dp"
+ app:layout_constraintHorizontal_bias="0">
+ <include layout="@layout/screenshot_work_profile_first_run" />
+ <include layout="@layout/screenshot_detection_notice" />
+ </FrameLayout>
+ </androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/screenshot_flash"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index f35de05..dc9c4f1 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -52,7 +52,6 @@
android:paddingRight="0dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
- android:clickable="true"
android:layout_width="@dimen/volume_row_slider_height"
android:layout_height="match_parent"
android:layout_gravity="center"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 63c6132..3861c98 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Gehoortoestelle"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Bind nuwe toestel saam"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nuwe toestel saam te bind"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kon nie voorafstelling opdateer nie"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokkeer toestelmikrofoon?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokkeer toestelkamera?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblokkeer toestelkamera en mikrofoon?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Hervat werkapps?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Hervat"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Maak legstukke op sluitskerm toe"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Pasmaak legstukke"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Legstukke op sluitskerm"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Wissel gebruiker"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aftrekkieslys"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliet, swak verbinding"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goeie toestand"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding is beskikbaar"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pret vir party mense, maar nie vir almal nie"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Stelsel-UI-ontvanger gee jou ekstra maniere om die Android-gebruikerkoppelvlak in te stel en te pasmaak. Hierdie eksperimentele kenmerke kan in toekomstige uitreikings verander, breek of verdwyn. Gaan versigtig voort."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 1c80547..9f9d3c5 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"የመስማት ችሎታ መሣሪያ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"አዲስ መሣሪያ ያጣምሩ"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"አዲስ መሣሪያ ለማጣመር ጠቅ ያድርጉ"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ቅድመ-ቅምጥን ማዘመን አልተቻለም"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"የመሣሪያ ማይክሮፎን እገዳ ይነሳ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"የመሣሪያ ካሜራ እገዳ ይነሳ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"የመሣሪያ ካሜራ እና ማይክሮፎን እገዳ ይነሳ?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ሳተላይት፣ ደካማ ግንኙነት"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ሳተላይት፣ ጥሩ ግንኙነት"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ሳተላይት፣ ግንኙነት አለ"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ከሳተላይት ጋር ተገናኝቷል"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ከሳተላይት ጋር አልተገናኘም"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"የስራ መገለጫ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ለአንዳንዶች አስደሳች ቢሆንም ለሁሉም አይደለም"</string>
<string name="tuner_warning" msgid="1861736288458481650">"የስርዓት በይነገጽ መቃኛ የAndroid ተጠቃሚ በይነገጹን የሚነካኩበት እና የሚያበጁበት ተጨማሪ መንገዶች ይሰጠዎታል። እነዚህ የሙከራ ባህሪዎች ወደፊት በሚኖሩ ልቀቶች ላይ ሊለወጡ፣ ሊሰበሩ ወይም ሊጠፉ ይችላሉ። ከጥንቃቄ ጋር ወደፊት ይቀጥሉ።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index c92a32b..1897228 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سماعات الأذن الطبية"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"إقران جهاز جديد"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"انقر لإقران جهاز جديد"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"تعذَّر تعديل الإعداد المسبق"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"هل تريد إزالة حظر ميكروفون الجهاز؟"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"هل تريد إزالة حظر كاميرا الجهاز؟"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"هل تريد إزالة حظر الكاميرا والميكروفون؟"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"أتريد إعادة تفعيل تطبيقات العمل؟"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"إعادة التفعيل"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"إغلاق التطبيقات المصغّرة على شاشة القفل"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"تخصيص التطبيقات المصغَّرة"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"التطبيقات المصغّرة على شاشة القفل"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تبديل المستخدم"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"القائمة المنسدلة"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"قمر صناعي، الاتصال ضعيف"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"قمر صناعي، الاتصال جيد"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"قمر صناعي، الاتصال متوفّر"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"تم الاتصال بالقمر الصناعي"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"لم يتم الاتصال بالقمر الصناعي"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ملف العمل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"متعة للبعض وليس للجميع"</string>
<string name="tuner_warning" msgid="1861736288458481650">"توفر لك أداة ضبط واجهة مستخدم النظام طرقًا إضافية لتعديل واجهة مستخدم Android وتخصيصها. ويمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index f1291a0..ab19d56 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"শুনাৰ ডিভাইচ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইচ পেয়াৰ কৰিবলৈ ক্লিক কৰক"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"প্ৰিছেট আপডে’ট কৰিব পৰা নগ’ল"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইচৰ মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইচৰ কেমেৰা অৱৰোধৰ পৰা আঁতৰাবনে?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ডিভাইচৰ কেমেৰা আৰু মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"উপগ্ৰহ, বেয়া সংযোগ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"উপগ্ৰহ, ভাল সংযোগ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"উপগ্ৰহ, সংযোগ উপলব্ধ"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"উপগ্ৰহৰ সৈতে সংযোগ কৰা হৈছে"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"উপগ্ৰহৰ সৈতে সংযোগ কৰা হোৱা নাই"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছুমানৰ বাবে আমোদজনক হয় কিন্তু সকলোৰে বাবে নহয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tunerএ আপোনাক Android ব্যৱহাৰকাৰী ইণ্টাৰফেইচ সলনি কৰিবলৈ আৰু নিজৰ উপযোগিতা অনুসৰি ব্যৱহাৰ কৰিবলৈ অতিৰিক্ত সুবিধা প্ৰদান কৰে। এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index b12d822..62164a5 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Eşitmə cihazları"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yeni cihaz birləşdirin"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz birləşdirmək üçün klikləyin"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hazır ayar güncəllənmədi"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonu blokdan çıxarılsın?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerası blokdan çıxarılsın?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Cihaz kamerası və mikrofonu blokdan çıxarılsın?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"İş tətbiqi üzrə pauza bitsin?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Pauzanı bitirin"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Kilid ekranında vidcetləri bağlayın"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Vidcetləri fərdiləşdirin"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Kilid ekranındakı vidcetlər"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aşağı çəkilən menyu"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Peyk, bağlantı zəifdir"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Peyk, bağlantı yaxşıdır"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Peyk, bağlantı var"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Hamı üçün deyil, bəziləri üçün əyləncəli"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android istifadəçi interfeysini dəyişdirmək və fərdiləşdirmək üçün Sizə ekstra yollar təklif edir."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 221d16c..392ca53 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni aparati"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Upari novi uređaj"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili nov uređaj"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje zadatih podešavanja nije uspelo"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite da odblokirate mikrofon uređaja?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite da odblokirate kameru uređaja?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite da odblokirate kameru i mikrofon uređaja?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, veza je loša"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, veza je dobra"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Povezano sa satelitom"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nije povezano sa satelitom"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tjuner za korisnički interfejs sistema vam pruža dodatne načine za podešavanje i prilagođavanje Android korisničkog interfejsa. Ove eksperimentalne funkcije mogu da se promene, otkažu ili nestanu u budućim izdanjima. Budite oprezni."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index d1c4a98..9977857 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слыхавыя апараты"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Спалучыць новую прыладу"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Націсніце, каб спалучыць новую прыладу"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не ўдалося абнавіць набор налад"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблакіраваць мікрафон прылады?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблакіраваць камеру прылады?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Разблакіраваць камеру і мікрафон прылады?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спадарожнікавая сувязь, дрэннае падключэнне"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спадарожнікавая сувязь, добрае падключэнне"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спадарожнікавая сувязь, падключэнне даступнае"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Працоўны профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Цікава для некаторых, але не для ўсіх"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Наладка сістэмнага інтэрфейсу карыстальніка дае вам дадатковыя спосабы наладжвання і дапасоўвання карыстальніцкага інтэрфейсу Android. Гэтыя эксперыментальныя функцыі могуць змяніцца, перастаць працаваць або знікнуць у будучых версіях. Карыстайцеся з асцярожнасцю."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 62d3fed..5b97cb4 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слухови апарати"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Сдвояване на ново устройство"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за сдвояване на ново устройство"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Предварително зададените настройки не бяха актуализирани"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се отблокира ли микрофонът на устройството?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се отблокира ли камерата на устройството?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Да се отблокират ли камерата и микрофонът на устройството?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Отмяна на паузата за служ. прил.?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Отмяна на паузата"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Затваряне на приспособленията на заключения екран"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Персонализиране на приспособленията"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Приспособления на заключения екран"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Превключване между потребителите"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падащо меню"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Сателит, лоша връзка"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, добра връзка"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, налице е връзка"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Установена е връзка със сателит"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Не е установена връзка със сателит"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Потребителски профил в Work"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забавно – но не за всички"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тунерът на системния потребителски интерфейс ви предоставя допълнителни възможности за прецизиране и персонализиране на практическата работа с Android. Тези експериментални функции може да се променят, повредят или да изчезнат в бъдещите версии. Действайте внимателно."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 81e3fc4..322b723 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"হিয়ারিং ডিভাইস"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"নতুন ডিভাইস পেয়ার করুন"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইস পেয়ার করতে ক্লিক করুন"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"প্রিসেট আপডেট করা যায়নি"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইসের মাইক্রোফোন আনব্লক করতে চান?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইসের ক্যামেরা আনব্লক করতে চান?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ডিভাইসের ক্যামেরা এবং মাইক্রোফোন আনব্লক করতে চান?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"স্যাটেলাইট, খারাপ কানেকশন"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"স্যাটেলাইট, ভালো কানেকশন"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"স্যাটেলাইট, কানেকশন উপলভ্য আছে"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কাজের প্রোফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছু ব্যক্তির জন্য মজাদার কিন্তু সকলের জন্য নয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"এই পরীক্ষামূলক বৈশিষ্ট্যগুলি ভবিষ্যতের সংস্করণগুলির মধ্যে পরিবর্তিত, বিভাজিত এবং অদৃশ্য হয়ে যেতে পারে৷ সাবধানতার সাথে এগিয়ে যান৷ সিস্টেম UI টিউনার আপনাকে Android ব্যবহারকারী ইন্টারফেসের সূক্ষ্ম সমন্বয় এবং কাস্টমাইজ করার অতিরিক্ত উপায়গুলি প্রদান করে৷"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 7d66851..63340d7 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -235,8 +235,8 @@
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obavještenja sa sjenčenjem."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
<string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i lokacija za obavještenja."</string>
- <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Zaključavanje ekrana"</string>
- <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
+ <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Zaključani ekran"</string>
+ <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključani ekran radnog profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"potpuna tišina"</string>
<string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"samo alarmi"</string>
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni aparati"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uparite novi uređaj"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da uparite novi uređaj"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje zadane postavke nije uspjelo"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokirati mikrofon uređaja?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokirati kameru uređaja?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblokirati kameru i mikrofon uređaja?"</string>
@@ -643,7 +642,7 @@
<string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Ažuriranje"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da koristite"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema prilikom preuzimanja vaših kartica. Pokušajte ponovo kasnije"</string>
- <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključavanja ekrana"</string>
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključanog ekrana"</string>
<string name="qr_code_scanner_title" msgid="1938155688725760702">"Skener QR koda"</string>
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ažuriranje"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Radni profil"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba veza"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Radni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Podešavač za korisnički interfejs sistema vam omogućava dodatne načine da podesite i prilagodite Androidov interfejs. Ove eksperimentalne funkcije se u budućim verzijama mogu mijenjati, kvariti ili nestati. Budite oprezni."</string>
@@ -775,7 +778,7 @@
<string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvaranje liste aplikacija"</string>
<string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvaranje postavki"</string>
<string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvaranje Asistenta"</string>
- <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključani ekran"</string>
<string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string>
<string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
<string name="system_multitasking_rhs" msgid="8714224917276297810">"Korištenje podijeljenog ekrana s trenutnom aplikacijom na desnoj strani"</string>
@@ -1275,8 +1278,8 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređite na radni profil"</string>
<string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalirajte poslovnu aplikaciju za telefon"</string>
<string name="call_from_work_profile_close" msgid="5830072964434474143">"Otkaži"</string>
- <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključavanje ekrana"</string>
- <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da prilagodite zaključavanje ekrana"</string>
+ <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključani ekran"</string>
+ <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da prilagodite zaključani ekran"</string>
<string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi mreža nije dostupna"</string>
<string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
<string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 87af353..341dca5 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Audiòfons"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincula un dispositiu nou"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fes clic per vincular un dispositiu nou"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"No s\'ha pogut actualitzar el valor predefinit"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vols desbloquejar el micròfon del dispositiu?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vols desbloquejar la càmera del dispositiu?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vols desbloquejar la càmera i el micròfon del dispositiu?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satèl·lit, connexió deficient"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satèl·lit, bona connexió"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satèl·lit, connexió disponible"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de treball"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversió per a uns quants, però no per a tothom"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El Personalitzador d\'interfície d\'usuari presenta opcions addicionals per canviar i personalitzar la interfície d\'usuari d\'Android. És possible que aquestes funcions experimentals canviïn, deixin de funcionar o desapareguin en versions futures. Continua amb precaució."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 102768f..0598097 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Naslouchátka"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Spárovat nové zařízení"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zařízení"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Předvolbu nelze aktualizovat"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokovat mikrofon zařízení?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokovat fotoaparát zařízení?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Odblokovat fotoaparát a mikrofon zařízení?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, špatné připojení"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobré připojení"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, připojení je k dispozici"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Připojeno k satelitu"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nepřipojeno k satelitu"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovní profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zábava, která není pro každého"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nástroj na ladění uživatelského rozhraní systému vám nabízí další způsoby, jak si vyladit a přizpůsobit uživatelské rozhraní Android. Tyto experimentální funkce mohou v dalších verzích chybět, nefungovat nebo být změněny. Postupujte proto prosím opatrně."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index d3138ab..bee3563 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Høreapparater"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Par ny enhed"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik for at parre en ny enhed"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Forindstillingen kunne ikke opdateres"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du fjerne blokeringen af enhedens mikrofon?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du fjerne blokeringen af enhedens kamera?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vil du fjerne blokeringen af enhedens kamera og mikrofon?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit – dårlig forbindelse"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit – god forbindelse"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit – forbindelsen er tilgængelig"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbejdsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Sjovt for nogle, men ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner giver dig flere muligheder for at justere og tilpasse Android-brugerfladen. Disse eksperimentelle funktioner kan ændres, gå i stykker eller forsvinde i fremtidige udgivelser. Vær forsigtig, hvis du fortsætter."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 03d04a6..e424363 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hörgeräte"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Neues Gerät koppeln"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicken, um neues Gerät zu koppeln"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Voreinstellung konnte nicht aktualisiert werden"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Blockierung des Gerätemikrofons aufheben?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Blockierung der Gerätekamera aufheben?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Blockierung von Gerätekamera und Gerätemikrofon aufheben?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit, Verbindung schlecht"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, Verbindung gut"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, Verbindung verfügbar"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Mit Satellit verbunden"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nicht mit Satellit verbunden"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbeitsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Für einige ein Vergnügen, aber nicht für alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Mit System UI Tuner erhältst du zusätzliche Möglichkeiten, die Android-Benutzeroberfläche anzupassen. Achtung: Diese Testfunktionen können sich ändern, abstürzen oder in zukünftigen Versionen verschwinden."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 89092ad..f8e0b53 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Συσκευές ακοής"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Σύζευξη νέας συσκευής"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Κάντε κλικ για σύζευξη νέας συσκευής"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Δεν ήταν δυνατή η ενημέρωση της προεπιλογής"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Κατάργηση αποκλεισμού μικροφώνου συσκευής;"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Κατάργηση αποκλεισμού κάμερας συσκευής;"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Κατάργηση αποκλεισμού κάμερας και μικροφώνου συσκευής;"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Δορυφορική, κακή σύνδεση"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Δορυφορική, καλή σύνδεση"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Δορυφορική, διαθέσιμη σύνδεση"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Συνδέθηκε σε δορυφόρο"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Δεν συνδέθηκε σε δορυφόρο"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Προφίλ εργασίας"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Διασκέδαση για ορισμένους, αλλά όχι για όλους"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Το System UI Tuner σάς προσφέρει επιπλέον τρόπους για να τροποποιήσετε και να προσαρμόσετε τη διεπαφή χρήστη Android. Αυτές οι πειραματικές λειτουργίες ενδέχεται να τροποποιηθούν, να παρουσιάσουν σφάλματα ή να καταργηθούν σε μελλοντικές εκδόσεις. Συνεχίστε με προσοχή."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 459de64..5a18245 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Unpause work apps?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Unpause"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customise widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 4879850..8b71d4b 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -654,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connected to satellite"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Not connected to satellite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 459de64..5a18245 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Unpause work apps?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Unpause"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customise widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 459de64..5a18245 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Unpause work apps?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Unpause"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customise widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index a2340bd..f32b774 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -654,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connected to satellite"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Not connected to satellite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 202bd93..552f31f 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular dispositivo nuevo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para vincular un dispositivo nuevo"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"No se pudo actualizar el ajuste predeterminado"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Quieres desbloquear el micrófono del dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Quieres desbloquear la cámara del dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Quieres desbloquear la cámara y el micrófono del dispositivo?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexión inestable"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión para algunos, pero no para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El sintonizador de IU del sistema te brinda más formas para editar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, dejar de funcionar o no incluirse en futuras versiones. Procede con precaución."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 88fab2d..10f480e 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Audífonos"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Emparejar nuevo dispositivo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para emparejar un nuevo dispositivo"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"No se ha podido actualizar el preajuste"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Desbloquear el micrófono del dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Desbloquear la cámara del dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Desbloquear la cámara y el micrófono del dispositivo?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, mala conexión"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 1b4cea7..0f98ce68 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuuldeseadmed"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uue seadme sidumine"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Uue seadme sidumiseks klõpsake"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Eelseadistust ei saanud värskendada"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kas tühistada seadme mikrofoni blokeerimine?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kas tühistada seadme kaamera blokeerimine?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kas tühistada seadme kaamera ja mikrofoni blokeerimine?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Kas lõpetada töörakenduste peatamine?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Lõpeta peatamine"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Lukustuskuva vidinate sulgemine"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Kohanda vidinaid"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Lukustuskuva vidinad"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kasutaja vahetamine"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rippmenüü"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliit, kehv ühendus"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliit, hea ühendus"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliit, ühendus on saadaval"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Tööprofiil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kõik ei pruugi sellest rõõmu tunda"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Süsteemi kasutajaliidese tuuner pakub täiendavaid võimalusi Androidi kasutajaliidese muutmiseks ja kohandamiseks. Need katselised funktsioonid võivad muutuda, rikki minna või tulevastest versioonidest kaduda. Olge jätkamisel ettevaatlik."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index b69ef30..393aa97 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Entzumen-gailuak"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parekatu beste gailu bat"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Egin klik beste gailu bat parekatzeko"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ezin izan da eguneratu aurrezarpena"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Gailuaren mikrofonoa desblokeatu nahi duzu?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Gailuaren kamera desblokeatu nahi duzu?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Gailuaren kamera eta mikrofonoa desblokeatu nahi dituzu?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelitea, konexio ahula"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelitea, konexio ona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelitea, konexioa erabilgarri"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Laneko profila"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dibertsioa batzuentzat, baina ez guztientzat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemaren erabiltzaile-interfazearen konfiguratzaileak Android erabiltzaile-interfazea moldatzeko eta pertsonalizatzeko modu gehiago eskaintzen dizkizu. Baliteke eginbide esperimental horiek hurrengo kaleratzeetan aldatuta, etenda edo desagertuta egotea. Kontuz erabili."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 94fb12f..10ff0db 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سمعک"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"جفت کردن دستگاه جدید"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"برای جفت کردن دستگاه جدید، کلیک کنید"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"پیشتنظیم بهروزرسانی نشد"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"میکروفون دستگاه لغو انسداد شود؟"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"دوربین دستگاه لغو انسداد شود؟"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"دوربین و میکروفون دستگاه لغو انسداد شود؟"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ماهواره، اتصال ضعیف است"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ماهواره، اتصال خوب است"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ماهواره، اتصال دردسترس است"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"به ماهواره متصل هستید"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"به ماهواره متصل نیستید"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"نمایه کاری"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"برای بعضی افراد سرگرمکننده است اما نه برای همه"</string>
<string name="tuner_warning" msgid="1861736288458481650">"«تنظیمکننده واسط کاربری سیستم» روشهای بیشتری برای تنظیم دقیق و سفارشی کردن واسط کاربری Android در اختیار شما قرار میدهد. ممکن است این ویژگیهای آزمایشی تغییر کنند، خراب شوند یا در نسخههای آینده جود نداشته باشند. با احتیاط ادامه دهید."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index a7754b0..bc761e7 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuulolaitteet"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Muodosta uusi laitepari"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Muodosta uusi laitepari klikkaamalla"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Esiasetusta ei voitu muuttaa"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kumotaanko laitteen mikrofonin esto?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kumotaanko laitteen kameran esto?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kumotaanko laitteen kameran ja mikrofonin esto?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliitti, huono yhteys"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliitti, hyvä yhteys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliitti, yhteys saatavilla"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Yhteys satelliittiin"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Ei yhteyttä satelliittiin"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Työprofiili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Ei sovellu kaikkien käyttöön"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner antaa lisämahdollisuuksia Android-käyttöliittymän muokkaamiseen. Nämä kokeelliset ominaisuudet voivat muuttua, lakata toimimasta tai kadota milloin tahansa. Jatka omalla vastuullasi."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 5bacaaa..f039c83 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquez ici pour associer un nouvel appareil"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossible de mettre à jour le préréglage"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le microphone de l\'appareil?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer l\'appareil photo de l\'appareil?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le microphone?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Réactiver les applis pros?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Réactiver"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fermer les widgets sur l\'écran de verrouillage"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Personnaliser les widgets"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets sur l\'écran de verrouillage"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Connexion satellite faible"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite accessible"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connecté au satellite"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Non connecté au satellite"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur d\'Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a4a039f1..0df8988 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquer pour associer un nouvel appareil"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossible de mettre à jour les préréglages"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le micro de l\'appareil ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer la caméra de l\'appareil ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le micro de l\'appareil ?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Mauvaise connexion satellite"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite disponible"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index e2b1e53..4682c02 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular un dispositivo novo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic para vincular un novo dispositivo"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Non se puido actualizar a configuración predeterminada"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Queres desbloquear o micrófono do dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Queres desbloquear a cámara do dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Queres desbloquear a cámara e o micrófono do dispositivo?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, mala conexión"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión dispoñible"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de traballo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión só para algúns"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O configurador da IU do sistema ofréceche formas adicionais de modificar e personalizar a interface de usuario de Android. Estas funcións experimentais poden cambiar, interromperse ou desaparecer en futuras versións. Continúa con precaución."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 2883cc5..0e03bcf 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"સાંભળવામાં મદદ આપતા ડિવાઇસ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"નવા ડિવાઇસ સાથે જોડાણ કરવા માટે ક્લિક કરો"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"પ્રીસેટ અપડેટ કરી શક્યા નથી"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ડિવાઇસના માઇક્રોફોનને અનબ્લૉક કરીએ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ડિવાઇસના કૅમેરાને અનબ્લૉક કરીએ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ડિવાઇસના કૅમેરા અને માઇક્રોફોનને અનબ્લૉક કરીએ?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ઑફિસની થોભાવેલી ઍપ ચાલુ કરીએ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ફરી ચાલુ કરો"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"લૉક સ્ક્રીન પર વિજેટ બંધ કરો"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"વિજેટ કસ્ટમાઇઝ કરો"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"લૉક સ્ક્રીન પર વિજેટ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"વપરાશકર્તા સ્વિચ કરો"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"પુલડાઉન મેનૂ"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"સૅટલાઇટ, નબળું કનેક્શન"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"સૅટલાઇટ, સારું કનેક્શન"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"સૅટલાઇટ, કનેક્શન ઉપલબ્ધ છે"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"સૅટલાઇટ સાથે કનેક્ટેડ છે"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"સૅટલાઇટ સાથે કનેક્ટેડ નથી"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ઑફિસની પ્રોફાઇલ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"કેટલાક માટે મજા પરંતુ બધા માટે નહીં"</string>
<string name="tuner_warning" msgid="1861736288458481650">"સિસ્ટમ UI ટ્યૂનર તમને Android વપરાશકર્તા ઇન્ટરફેસને ટ્વીક અને કસ્ટમાઇઝ કરવાની વધારાની રીતો આપે છે. ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f30957d..2186143 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"कान की मशीनें"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नया डिवाइस जोड़ें"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नया डिवाइस जोड़ने के लिए क्लिक करें"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रीसेट अपडेट नहीं किया जा सका"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आपको डिवाइस का माइक्रोफ़ोन अनब्लॉक करना है?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आपको डिवाइस का कैमरा अनब्लॉक करना है?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"क्या आप डिवाइस का कैमरा और माइक्रोफ़ोन अनब्लॉक करना चाहते हैं?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"वर्क ऐप्लिकेशन चालू करने हैं?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"चालू करें"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लॉक स्क्रीन पर विजेट बंद करें"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"विजेट अपनी पसंद के मुताबिक बनाएं"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लॉक स्क्रीन पर विजेट"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"उपयोगकर्ता बदलें"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेन्यू"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"सैटलाइट कनेक्शन खराब है"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सैटलाइट कनेक्शन अच्छा है"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सैटलाइट कनेक्शन उपलब्ध है"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"सैटलाइट सिग्नल से कनेक्ट है"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"सैटलाइट सिग्नल से कनेक्ट नहीं है"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"वर्क प्रोफ़ाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index bada67e..f5b9ca5 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni uređaji"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uparivanje novog uređaja"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili novi uređaj"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje unaprijed definiranih postavki nije uspjelo"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite li deblokirati mikrofon uređaja?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite li deblokirati kameru uređaja?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite li deblokirati kameru i mikrofon uređaja?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba veza"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Ugađanje korisničkog sučelja sustava pruža vam dodatne načine za prilagodbu korisničkog sučelja Androida. Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d216fa4..32dcdfd 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hallókészülékek"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Új eszköz párosítása"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kattintson új eszköz párosításához"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nem sikerült frissíteni a beállításkészletet"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Feloldja az eszköz mikrofonjának letiltását?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Feloldja az eszköz kamerájának letiltását?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Feloldja az eszköz kamerájának és mikrofonjának letiltását?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Feloldja a munkahelyi appokat?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Szüneteltetés feloldása"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"A lezárási képernyőn lévő modulok bezárása"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Modulok személyre szabása"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Modulok a lezárási képernyőn"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Felhasználóváltás"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"lehúzható menü"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Műhold, gyenge kapcsolat"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Műhold, jó kapcsolat"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Műhold, van rendelkezésre álló kapcsolat"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Műholdhoz csatlakozik"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nem csatlakozik műholdhoz"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Munkaprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Egyeseknek tetszik, másoknak nem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 034ac1a..ec090dd 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Լսողական սարքեր"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Նոր սարքի զուգակցում"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Սեղմեք՝ նոր սարք զուգակցելու համար"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Չհաջողվեց թարմացնել կարգավորումների հավաքածուն"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Արգելահանե՞լ սարքի խոսափողը"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Արգելահանե՞լ սարքի տեսախցիկը"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Արգելահանե՞լ սարքի տեսախցիկը և խոսափողը"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Արբանյակային թույլ կապ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Արբանյակային լավ կապ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Հասանելի է արբանյակային կապ"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Աշխատանքային պրոֆիլ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Զվարճանք մեկ՝ որոշակի մարդու համար"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Համակարգի ՕՄ-ի կարգավորիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index d428ef8..2e36d21 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Alat bantu dengar"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sambungkan perangkat baru"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menyambungkan perangkat baru"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tidak dapat memperbarui preset"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Berhenti memblokir mikrofon perangkat?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Berhenti memblokir kamera perangkat?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Berhenti memblokir kamera dan mikrofon perangkat?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Batalkan jeda aplikasi kerja?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Batalkan jeda"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tutup widget di layar kunci"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Sesuaikan widget"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget di layar kunci"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pulldown"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, koneksi buruk"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, koneksi baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, koneksi tersedia"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Terhubung ke satelit"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Tidak terhubung ke satelit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Tidak semua orang menganggapnya baik"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penyetel Antarmuka Pengguna Sistem memberikan cara tambahan untuk mengubah dan menyesuaikan antarmuka pengguna Android. Fitur eksperimental ini dapat berubah, rusak, atau menghilang dalam rilis di masa mendatang. Lanjutkan dengan hati-hati."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 4b97299..2087907 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Heyrnartæki"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Para nýtt tæki"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Smelltu til að para nýtt tæki"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tókst ekki að uppfæra forstillingu"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Opna fyrir hljóðnema tækisins?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Opna fyrir myndavél tækisins?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Opna fyrir myndavél og hljóðnema tækisins?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Gervihnöttur, léleg tenging"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Gervihnöttur, góð tenging"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Gervihnöttur, tenging tiltæk"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Vinnusnið"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Þetta er ekki allra"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Fínstillingar kerfisviðmóts gera þér kleift að fínstilla og sérsníða notendaviðmót Android. Þessir tilraunaeiginleikar geta breyst, bilað eða horfið í síðari útgáfum. Gakktu því hægt um gleðinnar dyr."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 30bdfae..5931e6a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Protesi uditive"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Accoppia nuovo dispositivo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic per accoppiare un nuovo dispositivo"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossibile aggiornare preset"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vuoi sbloccare il microfono del dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vuoi sbloccare la fotocamera del dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vuoi sbloccare la fotocamera e il microfono del dispositivo?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellitare, connessione debole"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitare, connessione buona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitare, connessione disponibile"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connessione satellitare"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Nessuna connessione satellitare"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profilo di lavoro"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Il divertimento riservato a pochi eletti"</string>
<string name="tuner_warning" msgid="1861736288458481650">"L\'Ottimizzatore UI di sistema mette a disposizione altri metodi per modificare e personalizzare l\'interfaccia utente di Android. Queste funzioni sperimentali potrebbero cambiare, interrompersi o scomparire nelle versioni successive. Procedi con cautela."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bc1d91f..8c2ccbf 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -302,7 +302,7 @@
<string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"אין רשתות Wi-Fi זמינות"</string>
<string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"בתהליך הפעלה…"</string>
<string name="quick_settings_cast_title" msgid="2279220930629235211">"הפעלת Cast למסך"</string>
- <string name="quick_settings_casting" msgid="1435880708719268055">"מתבצעת העברה (cast)"</string>
+ <string name="quick_settings_casting" msgid="1435880708719268055">"מופעל Cast"</string>
<string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"מכשיר ללא שם"</string>
<string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"אין מכשירים זמינים"</string>
<string name="quick_settings_cast_no_network" msgid="3863016850468559522">"אין חיבור ל-Wi-Fi או לאתרנט"</string>
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"מכשירי שמיעה"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"התאמה של מכשיר חדש"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"צריך ללחוץ כדי להתאים מכשיר חדש"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"לא ניתן לעדכן את ההגדרה הקבועה מראש"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"לבטל את חסימת המיקרופון של המכשיר?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"לבטל את חסימת המצלמה של המכשיר?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"לבטל את חסימת המצלמה והמיקרופון של המכשיר?"</string>
@@ -476,25 +475,25 @@
<string name="user_remove_user_title" msgid="9124124694835811874">"להסיר את המשתמש?"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"כל האפליקציות והנתונים של המשתמש הזה יימחקו."</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"הסרה"</string>
- <string name="media_projection_dialog_title" msgid="3316063622495360646">"להתחיל להקליט או להעביר (cast) באמצעות <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_dialog_warning" msgid="1303664408388363598">"לאפליקציית <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> תהיה גישה לכל המידע הגלוי במסך שלך ולכל תוכן שמופעל במכשיר שלך בזמן הקלטה או העברה (cast). המידע הזה כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
- <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"להתחיל להקליט או להעביר (cast)?"</string>
- <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"לשירות שמספק את הפונקציה הזו תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או העברה (cast) – כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"להתחיל להקליט או להפעיל Cast דרך <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
+ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"לאפליקציית <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> תהיה גישה לכל המידע הגלוי במסך שלך ולכל תוכן שמופעל במכשיר שלך בזמן הקלטה או הפעלת Cast. המידע הזה כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
+ <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"להתחיל הקלטה או הפעלת Cast?"</string>
+ <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"לשירות שמספק את הפונקציה הזו תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או הפעלת Cast – כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
<string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"כל המסך"</string>
<string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"אפליקציה אחת"</string>
<string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"שיתוף או הקלטה של אפליקציה"</string>
- <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"להתחיל להקליט או להעביר (cast) באמצעות <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"בזמן שיתוף, הקלטה או העברה (cast) תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
- <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
+ <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"להתחיל להקליט או להפעיל Cast דרך <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
+ <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"בזמן שיתוף, הקלטה או הפעלת Cast תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
+ <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"בזמן שיתוף, הקלטה או הפעלת Cast של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"התחלה"</string>
<string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> השביתה את האפשרות הזו"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"להפעיל Cast?"</string>
- <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"בזמן העברה (cast), תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
+ <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"בזמן הפעלת Cast, תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"בזמן Cast מאפליקציה, תהיה ל-Android גישה לכל מה שמופיע באפליקציה ולכל מדיה שפועלת בה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"הפעלת Cast"</string>
<string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"להתחיל את השיתוף?"</string>
- <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"בזמן שיתוף, הקלטה או העברה (cast) תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
- <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
+ <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"בזמן שיתוף, הקלטה או הפעלת Cast תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
+ <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"בזמן שיתוף, הקלטה או הפעלת Cast של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"התחלה"</string>
<string name="media_projection_task_switcher_text" msgid="590885489897412359">"השיתוף מושהה כשמחליפים אפליקציות"</string>
<string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"שיתוף של האפליקציה הזו במקום"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"לוויין, חיבור באיכות ירודה"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"לוויין, חיבור באיכות טובה"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"לוויין, יש חיבור זמין"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"יש חיבור ללוויין"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"אין חיבור ללוויין"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"פרופיל עבודה"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"מהנה בשביל חלק מהאנשים, אבל לא בשביל כולם"</string>
<string name="tuner_warning" msgid="1861736288458481650">"התכונה System UI Tuner מספקת לך דרכים נוספות להתאים אישית את ממשק המשתמש של Android. התכונות הניסיוניות האלה עשויות להשתנות, לא לעבוד כראוי או להיעלם בגרסאות עתידיות. יש להמשיך בזהירות."</string>
@@ -1084,8 +1085,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"משהו השתבש. יש לנסות שוב."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"בטעינה"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"טאבלט"</string>
- <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"העברה (cast) של מדיה"</string>
- <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"מתבצעת העברה (cast) של <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"הפעלת Cast של מדיה"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"מופעל Cast של <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"לא פעיל, יש לבדוק את האפליקציה"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"לא נמצא"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"הפקד לא זמין"</string>
@@ -1104,7 +1105,7 @@
<string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(מנותק)"</string>
<string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"לא ניתן להחליף. צריך להקיש כדי לנסות שוב."</string>
<string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"חיבור מכשיר"</string>
- <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"כדי להעביר (cast) את הסשן הזה, צריך לפתוח את האפליקציה."</string>
+ <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"כדי להפעיל Cast של הסשן הזה, צריך לפתוח את האפליקציה."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"אפליקציה לא ידועה"</string>
<string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"עצירת ההעברה (casting)"</string>
<string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"מכשירים זמינים לפלט אודיו."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b587f40..54f9c86 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"補聴器"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"新しいデバイスとペア設定"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"クリックすると、新しいデバイスをペア設定できます"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"プリセットを更新できませんでした"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"デバイスのマイクのブロックを解除しますか?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"デバイスのカメラのブロックを解除しますか?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"デバイスのカメラとマイクのブロックを解除しますか?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"仕事用アプリの停止解除"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"停止解除"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ロック画面のウィジェットを閉じる"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ウィジェットのカスタマイズ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ロック画面のウィジェット"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ユーザーを切り替える"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"プルダウン メニュー"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛生、接続不安定"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛生、接続状態良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛生、接続利用可能"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"衛星に接続済み"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"衛星に未接続"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"仕事用プロファイル"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"一部の方のみお楽しみいただける限定公開ツール"</string>
<string name="tuner_warning" msgid="1861736288458481650">"システムUI調整ツールでは、Androidユーザーインターフェースの調整やカスタマイズを行えます。これらの試験運用機能は今後のリリースで変更となったり、中止となったり、削除されたりする可能性がありますのでご注意ください。"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index ff11d85..9c814b4 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"სმენის აპარატები"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ახალი მოწყობილობის დაწყვილება"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"დააწკაპუნეთ ახალი მოწყობილობის დასაწყვილებლად"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"წინასწარ დაყენებული პარამეტრების განახლება ვერ მოხერხდა"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"გსურთ მოწყობილობის მიკროფონის განბლოკვა?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"გსურთ მოწყობილობის კამერის განბლოკვა?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"გსურთ მოწყობილობის კამერის და მიკროფონის განბლოკვა?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"კვლავ გააქტიურდეს სამსახურის აპები?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"გააქტიურება"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ჩაკეტილ ეკრანზე ვიჯეტების დახურვა"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ვიჯეტების მორგება"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ვიჯეტები ჩაკეტილ ეკრანზე"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"მომხმარებლის გადართვა"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ჩამოშლადი მენიუ"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"სუსტი სატელიტური კავშირი"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"კარგი სატელიტური კავშირი"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ხელმისაწვდომია სატელიტური კავშირი"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"სამსახურის პროფილი"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ზოგისთვის გასართობია, მაგრამ არა ყველასთვის"</string>
<string name="tuner_warning" msgid="1861736288458481650">"სისტემის UI ტუნერი გაძლევთ დამატებით გზებს Android-ის სამომხმარებლო ინტერფეისის პარამეტრების დაყენებისთვის. ეს ექსპერიმენტული მახასიათებლები შეიძლება შეიცვალოს, შეწყდეს ან გაქრეს მომავალ ვერსიებში. სიფრთხილით გააგრძელეთ."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 995a796..5fe1a2c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Есту құрылғылары"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Жаңа құрылғыны жұптау"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңа құрылғыны жұптау үшін басыңыз."</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Параметрлер жинағын жаңарту мүмкін болмады."</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Құрылғы микрофонын блоктан шығару керек пе?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Құрылғы камерасын блоктан шығару керек пе?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Құрылғы камерасы мен микрофонын блоктан шығару керек пе?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Жұмыс қолданбаларын қайта қосасыз ба?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Қайта қосу"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Құлыптаулы экранда виджеттерді жабу"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Виджеттерді бейімдеу"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Құлыптаулы экрандағы виджеттер"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Пайдаланушыны ауыстыру"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ашылмалы мәзір"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Жерсерік, байланыс нашар."</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Жерсерік, байланыс жақсы."</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Жерсерік, байланыс бар."</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Жерсерік сигналына қосылғансыз."</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Жерсерік сигналына қосылмағансыз."</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жұмыс профилі"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Кейбіреулерге қызық, бірақ барлығына емес"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Жүйелік пайдаланушылық интерфейс тюнері Android пайдаланушылық интерфейсін реттеудің қосымша жолдарын береді. Бұл эксперименттік мүмкіндіктер болашақ шығарылымдарда өзгеруі, бұзылуы немесе жоғалуы мүмкін. Сақтықпен жалғастырыңыз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index adcd3d6..91292a1 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ឧបករណ៍ជំនួយការស្ដាប់"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ផ្គូផ្គងឧបករណ៍ថ្មី"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ចុច ដើម្បីផ្គូផ្គងឧបករណ៍ថ្មី"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"មិនអាចប្ដូរការកំណត់ជាមុនបានទេ"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ឈប់ទប់ស្កាត់មីក្រូហ្វូនរបស់ឧបករណ៍ឬ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ឈប់ទប់ស្កាត់កាមេរ៉ារបស់ឧបករណ៍ឬ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ឈប់ទប់ស្កាត់កាមេរ៉ា និងមីក្រូហ្វូនរបស់ឧបករណ៍ឬ?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ឈប់ផ្អាកកម្មវិធីការងារឬ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ឈប់ផ្អាក"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"បិទធាតុក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ប្ដូរធាតុក្រាហ្វិកតាមបំណង"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ធាតុក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរអ្នកប្រើ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ម៉ឺនុយទាញចុះ"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ផ្កាយរណប ការតភ្ជាប់ខ្សោយ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ផ្កាយរណប មានការតភ្ជាប់ល្អ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ផ្កាយរណប អាចតភ្ជាប់បាន"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"បានភ្ជាប់ទៅផ្កាយរណប"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"មិនបានភ្ជាប់ទៅផ្កាយរណប"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"កម្រងព័ត៌មានការងារ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ល្អសម្រាប់អ្នកប្រើមួយចំនួន តែមិនសម្រាប់គ្រប់គ្នាទេ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"កម្មវិធីសម្រួល UI ប្រព័ន្ធផ្តល់ជូនអ្នកនូវមធ្យោបាយបន្ថែមទៀតដើម្បីកែសម្រួល និងប្តូរចំណុចប្រទាក់អ្នកប្រើ Android តាមបំណង។ លក្ខណៈពិសេសសាកល្បងនេះអាចនឹងផ្លាស់ប្តូរ បំបែក ឬបាត់បង់បន្ទាប់ពីការចេញផ្សាយនាពេលអនាគត។ សូមបន្តដោយប្រុងប្រយ័ត្ន។"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index ca22ba1..0d4449a 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ಹಿಯರಿಂಗ್ ಸಾಧನಗಳು"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ಹೊಸ ಸಾಧನವನ್ನು ಪೇರ್ ಮಾಡಿ"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ಪ್ರಿಸೆಟ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ಸಾಧನದ ಕ್ಯಾಮರಾ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ಸಾಧನದ ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಅನ್ಬ್ಲಾಕ್ ಮಾಡಬೇಕೇ?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ಕೆಲಸದ ಆ್ಯಪ್ ವಿರಾಮ ರದ್ದುಮಾಡಬೇಕೇ"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ವಿರಾಮವನ್ನು ರದ್ದುಗೊಳಿಸಿ"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳನ್ನು ಮುಚ್ಚಿರಿ"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ವಿಜೆಟ್ಗಳನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳು"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ಪುಲ್ಡೌನ್ ಮೆನು"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಕಳಪೆಯಾಗಿದೆ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಉತ್ತಮವಾಗಿದೆ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಲಭ್ಯವಿದೆ"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ಸ್ಯಾಟಲೈಟ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ಸ್ಯಾಟಲೈಟ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿಲ್ಲ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ಕೆಲವರಿಗೆ ಮೋಜು ಆಗಿದೆ ಎಲ್ಲರಿಗೆ ಇಲ್ಲ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್ ನಿಮಗೆ Android ಬಳಕೆದಾರ ಅಂತರಸಂಪರ್ಕವನ್ನು ಸರಿಪಡಿಸಲು ಮತ್ತು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಹೆಚ್ಚುವರಿ ಮಾರ್ಗಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು ಭವಿಷ್ಯದ ಬಿಡುಗಡೆಗಳಲ್ಲಿ ಬದಲಾಗಬಹುದು, ವಿರಾಮವಾಗಬಹುದು ಅಥವಾ ಕಾಣಿಸಿಕೊಳ್ಳದಿರಬಹುದು. ಎಚ್ಚರಿಕೆಯಿಂದ ಮುಂದುವರಿಯಿರಿ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4e7c4d0..2d9058e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"청각 보조 기기"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"새 기기와 페어링"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"새 기기와 페어링하려면 클릭하세요"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"사전 설정을 업데이트할 수 없음"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"기기 마이크를 차단 해제하시겠습니까?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"기기 카메라를 차단 해제하시겠습니까?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"기기 카메라 및 마이크를 차단 해제하시겠습니까?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"위성, 연결 상태 나쁨"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"위성, 연결 상태 양호"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"위성, 연결 가능"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"직장 프로필"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"마음에 들지 않을 수도 있음"</string>
<string name="tuner_warning" msgid="1861736288458481650">"시스템 UI 튜너를 사용하면 Android 사용자 인터페이스를 변경 및 맞춤설정할 수 있습니다. 이러한 실험실 기능은 향후 출시 버전에서는 변경되거나 다운되거나 사라질 수 있습니다. 신중하게 진행하시기 바랍니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 1d005fb..1767c076 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Угуу аппараттары"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Жаңы түзмөк кошуу"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңы түзмөк кошуу үчүн басыңыз"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Алдын ала коюлган параметрлер жаңыртылган жок"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Түзмөктүн микрофонун бөгөттөн чыгарасызбы?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Түзмөктүн камерасын бөгөттөн чыгарасызбы?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Түзмөктүн камерасы менен микрофону бөгөттөн чыгарылсынбы?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спутник, байланыш начар"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутник, байланыш жакшы"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спутник, байланыш бар"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жумуш профили"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Баарына эле жага бербейт"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android колдонуучу интерфейсин жөнгө салып жана ыңгайлаштыруунун кошумча ыкмаларын сунуштайт. Бул сынамык функциялар кийинки чыгарылыштарда өзгөрүлүп, бузулуп же жоголуп кетиши мүмкүн. Абайлап колдонуңуз."</string>
diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml
index a0e721e..2769bea 100644
--- a/packages/SystemUI/res/values-land/styles.xml
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -14,12 +14,13 @@
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
<item name="android:layout_width">360dp</item>
</style>
- <style name="AuthCredentialHeaderStyle">
+ <style name="AuthNonBioCredentialHeaderStyle">
<item name="android:paddingStart">48dp</item>
<item name="android:paddingEnd">24dp</item>
<item name="android:paddingTop">48dp</item>
@@ -27,7 +28,7 @@
<item name="android:gravity">top|left</item>
</style>
- <style name="AuthCredentialPatternContainerStyle">
+ <style name="AuthNonBioCredentialPatternContainerStyle">
<item name="android:gravity">center</item>
<item name="android:maxHeight">@dimen/biometric_auth_pattern_view_max_size</item>
<item name="android:maxWidth">@dimen/biometric_auth_pattern_view_max_size</item>
@@ -38,22 +39,25 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:textSize">36dp</item>
<item name="android:focusable">true</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index f95bb8e..dc596bf 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ອຸປະກອນຊ່ວຍຟັງ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ຄລິກເພື່ອຈັບຄູ່ອຸປະກອນໃໝ່"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ບໍ່ສາມາດອັບເດດການຕັ້ງຄ່າລ່ວງໜ້າໄດ້"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ປົດບລັອກໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ປົດບລັອກກ້ອງຖ່າຍຮູບອຸປະກອນບໍ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ຍົກເລີກການບລັອກກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ຍົກເລີກການຢຸດຊົ່ວຄາວແອັບບ່ອນເຮັດວຽກບໍ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"ຍົກເລີກການຢຸດຊົ່ວຄາວ"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ປິດວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ປັບແຕ່ງວິດເຈັດ"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ສະຫຼັບຜູ້ໃຊ້"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ເມນູແບບດຶງລົງ"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ດາວທຽມ, ການເຊື່ອມຕໍ່ບໍ່ດີ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ດາວທຽມ, ການເຊື່ອມຕໍ່ດີ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ດາວທຽມ, ການເຊື່ອມຕໍ່ທີ່ພ້ອມນຳໃຊ້"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ເຊື່ອມຕໍ່ຫາດາວທຽມແລ້ວ"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ບໍ່ໄດ້ເຊື່ອມຕໍ່ຫາດາວທຽມ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 040294f..e6703ce 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Klausos įrenginiai"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Susieti naują įrenginį"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Spustelėkite, kad susietumėte naują įrenginį"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Išankstinių nustatymų atnaujinti nepavyko"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Panaikinti įrenginio mikrofono blokavimą?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Panaikinti įrenginio fotoaparato blokavimą?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Panaikinti įrenginio fotoaparato ir mikrofono blokavimą?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Atš. darbo progr. pristabd.?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Atšaukti pristabdymą"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Uždaryti valdiklius užrakinimo ekrane"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Tinkinti valdiklius"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Valdikliai užrakinimo ekrane"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Perjungti naudotoją"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"išplečiamasis meniu"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Palydovas, prastas ryšys"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Palydovas, geras ryšys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Palydovas, pasiekiamas ryšys"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Prisijungta prie palydovo"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Neprisijungta prie palydovo"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darbo profilis"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Smagu, bet ne visada"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemos naudotojo sąsajos derinimo priemonė suteikia papildomų galimybių pagerinti ir tinkinti „Android“ naudotojo sąsają. Šios eksperimentinės funkcijos gali pasikeisti, nutrūkti ar išnykti iš būsimų laidų. Tęskite atsargiai."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index da58f33..9a2a292 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dzirdes aparāti"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Savienojiet pārī jaunu ierīci"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Noklikšķiniet, lai savienotu pārī jaunu ierīci"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nevarēja atjaunināt pirmsiestatījumu"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vai atbloķēt ierīces mikrofonu?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vai vēlaties atbloķēt ierīces kameru?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vai atbloķēt ierīces kameru un mikrofonu?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelīts, vājš savienojums"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelīts, labs savienojums"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelīts, ir pieejams savienojums"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darba profils"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Jautri dažiem, bet ne visiem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistēmas saskarnes regulators sniedz papildu veidus, kā mainīt un pielāgot Android lietotāja saskarni. Nākamajās versijās šīs eksperimentālās funkcijas var tikt mainītas, bojātas vai to darbība var tikt pārtraukta. Turpinot esiet uzmanīgs."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 2faf243..552e5e5 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слушни апарати"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Спари нов уред"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за да спарите нов уред"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не можеше да се ажурира зададената вредност"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се одблокира пристапот до микрофонот на уредот?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се одблокира пристапот до камерата на уредот?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Да се одблокира пристапот до камерата и микрофонот на уредот?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Слаба сателитска врска"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Добра сателитска врска"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Достапна е сателитска врска"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Работен профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за некои, но не за сите"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Адаптерот на УИ на системот ви дава дополнителни начини за дотерување и приспособување на корисничкиот интерфејс на Android. Овие експериментални функции можеби ќе се изменат, расипат или ќе исчезнат во следните изданија. Продолжете со претпазливост."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 2fd4411..c3fdf84 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"കേൾവിക്കുള്ള ഉപകരണങ്ങൾ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"പുതിയ ഉപകരണം ജോടിയാക്കുക"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"പുതിയ ഉപകരണം ജോടിയാക്കാൻ ക്ലിക്ക് ചെയ്യുക"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"പ്രീസെറ്റ് അപ്ഡേറ്റ് ചെയ്യാനായില്ല"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ഉപകരണ മൈക്രോഫോൺ അൺബ്ലോക്ക് ചെയ്യണോ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ഉപകരണ ക്യാമറ അൺബ്ലോക്ക് ചെയ്യണോ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ഉപകരണ ക്യാമറയോ മൈക്രോഫോണോ അൺബ്ലോക്ക് ചെയ്യണോ?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"വർക്ക് ആപ്പുകൾ പുനരാരംഭിക്കണോ?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"പുനരാരംഭിക്കുക"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ അടയ്ക്കുക"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"വിജറ്റുകൾ ഇഷ്ടാനുസൃതമാക്കുക"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ഉപയോക്താവ് മാറുക"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"പുൾഡൗൺ മെനു"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"സാറ്റലൈറ്റ്, മോശം കണക്ഷൻ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"സാറ്റലൈറ്റ്, മികച്ച കണക്ഷൻ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"സാറ്റലൈറ്റ്, കണക്ഷൻ ലഭ്യമാണ്"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"സാറ്റലൈറ്റുമായി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"സാറ്റലൈറ്റുമായി കണക്റ്റ് ചെയ്തിട്ടില്ല"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ചിലർക്ക് വിനോദം, എന്നാൽ എല്ലാവർക്കുമില്ല"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ഉപയോക്തൃ ഇന്റർഫേസ് ആവശ്യമുള്ള രീതിയിൽ മാറ്റുന്നതിനും ഇഷ്ടാനുസൃതമാക്കുന്നതിനും സിസ്റ്റം UI ട്യൂണർ നിങ്ങൾക്ക് അധിക വഴികൾ നൽകുന്നു. ഭാവി റിലീസുകളിൽ ഈ പരീക്ഷണാത്മക ഫീച്ചറുകൾ മാറ്റുകയോ നിർത്തുകയോ അപ്രത്യക്ഷമാവുകയോ ചെയ്തേക്കാം. ശ്രദ്ധയോടെ മുന്നോട്ടുപോകുക."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 94cdf4c..428ceff 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Сонсголын төхөөрөмжүүд"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Шинэ төхөөрөмж хослуулах"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Шинэ төхөөрөмж хослуулахын тулд товшино уу"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Урьдчилсан тохируулгыг шинэчилж чадсангүй"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Төхөөрөмжийн микрофоныг блокоос гаргах уу?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Төхөөрөмжийн камерыг блокоос гаргах уу?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Төхөөрөмжийн камер болон микрофоныг блокоос гаргах уу?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Хиймэл дагуул, холболт муу байна"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хиймэл дагуул, холболт сайн байна"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Хиймэл дагуул, холболт боломжтой"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Хиймэл дагуулд холбогдсон"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Хиймэл дагуулд холбогдоогүй"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Системийн UI Tохируулагч нь Android хэрэглэгчийн интерфэйсийг тааруулах, өөрчлөх нэмэлт аргыг зааж өгөх болно. Эдгээр туршилтын тохиргоо нь цаашид өөрчлөгдөх, эвдрэх, алга болох магадлалтай. Үйлдлийг болгоомжтой хийнэ үү."</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index dd53db5..f597876 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"श्रवणयंत्रे"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नवीन डिव्हाइस पेअर करा"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नवीन डिव्हाइस पेअर करण्यासाठी क्लिक करा"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रीसेट अपडेट करता आले नाही"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिव्हाइसचा मायक्रोफोन अनब्लॉक करायचा आहे का?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिव्हाइसचा कॅमेरा अनब्लॉक करायचा आहे का?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"डिव्हाइसचा कॅमेरा आणि मायक्रोफोन अनब्लॉक करायचा आहे का?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"वर्क ॲप्स पुन्हा सुरू करायची?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"पुन्हा सुरू करा"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लॉक स्क्रीनवरील विजेट बंद करा"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"विजेट कस्टमाइझ करा"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लॉक स्क्रीनवरील विजेट"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"वापरकर्ता स्विच करा"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनू"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"सॅटेलाइट, खराब कनेक्शन"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सॅटेलाइट, चांगले कनेक्शन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सॅटेलाइट, कनेक्शन उपलब्ध"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"उपग्रहाशी जोडलेले आहे"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"उपग्रहाशी जोडलेले नाही"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाईल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"सर्वांसाठी नाही तर काहींसाठी मजेदार असू शकते"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्याला Android यूझर इंटरफेस ट्विक आणि कस्टमाइझ करण्याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्यातील रिलीज मध्ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 6b858a4..9e3117d 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Peranti pendengaran"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Gandingkan peranti baharu"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menggandingkan peranti baharu"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tidak dapat mengemaskinikan pratetapan"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Nyahsekat mikrofon peranti?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Nyahsekat kamera peranti?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Nyahsekat kamera dan mikrofon peranti?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Nyahjeda apl kerja?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Nyahjeda"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tutup widget pada skrin kunci"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Sesuaikan widget"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget pada skrin kunci"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu tarik turun"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, sambungan yang lemah"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, sambungan yang baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, sambungan tersedia"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Disambungkan kepada satelit"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Tidak disambungkan kepada satelit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Menarik untuk sesetengah orang tetapi bukan untuk semua"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penala UI Sistem memberi anda cara tambahan untuk mengolah dan menyesuaikan antara muka Android. Ciri eksperimen ini boleh berubah, rosak atau hilang dalam keluaran masa hadapan. Teruskan dengan berhati-hati."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 2472d1f..86345a8 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"နားကြားကိရိယာ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"စက်အသစ်တွဲချိတ်ရန်"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"စက်အသစ် တွဲချိတ်ရန် နှိပ်ပါ"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"အသင့်သုံးကို အပ်ဒိတ်လုပ်၍မရပါ"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"စက်၏မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"စက်၏ကင်မရာကို ပြန်ဖွင့်မလား။"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"စက်၏ကင်မရာနှင့် မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု မကောင်းပါ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ကောင်းသည်"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ရနိုင်သည်"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"အလုပ် ပရိုဖိုင်"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"အချို့သူများ အတွက် ပျော်စရာ ဖြစ်ပေမဲ့ အားလုံး အတွက် မဟုတ်ပါ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"စနစ် UI Tuner က သင့်အတွက် Android အသုံးပြုသူ အင်တာဖေ့စ်ကို ပြောင်းရန်နှင့် စိတ်ကြိုက်ပြုလုပ်ရန် နည်းလမ်း အပိုများကို သင့်အတွက် စီစဉ်ပေးသည်။ အနာဂတ်ဗားရှင်းများတွင် ဤစမ်းသပ်အင်္ဂါရပ်များမှာ ပြောင်းလဲ၊ ပျက်စီး သို့မဟုတ် ပျောက်ကွယ်သွားနိုင်သည်။ သတိဖြင့် ရှေ့ဆက်ပါ။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5bc2fe5..4c68dda 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Høreapparater"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Koble til en ny enhet"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klikk for å koble til en ny enhet"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kunne ikke oppdatere forhåndsinnstillingen"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du oppheve blokkeringen av enhetsmikrofonen?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du oppheve blokkeringen av enhetskameraet?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vil du oppheve blokkeringen av enhetskameraet og -mikrofonen?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellitt – dårlig tilkobling"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitt – god tilkobling"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitt – tilkobling tilgjengelig"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work-profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Gøy for noen – ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Med System UI Tuner har du flere måter å justere og tilpasse Android-brukergrensesnittet på. Disse eksperimentelle funksjonene kan endres, avbrytes eller fjernes i fremtidige utgivelser. Fortsett med forbehold."</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index f52466c..400fed0 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"हियरिङ डिभाइसहरू"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नयाँ डिभाइस कनेक्ट गर्नुहोस्"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नयाँ डिभाइसमा कनेक्ट गर्न क्लिक गर्नुहोस्"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रिसेट अपडेट गर्न सकिएन"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिभाइसको माइक्रोफोन अनब्लक गर्ने हो?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिभाइसको क्यामेरा अनब्लक गर्ने हो?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"डिभाइसको क्यामेरा र माइक्रोफोन अनब्लक गर्ने हो?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"कामसम्बन्धी एपहरू अनपज गर्ने हो?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"अनपज गर्नुहोस्"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लक स्क्रिनमा भएका विजेटहरू बन्द गर्नुहोस्"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"विजेटहरू कस्टमाइज गर्नुहोस्"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लक स्क्रिनमा भएका विजेटहरू"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"प्रयोगकर्ता फेर्नुहोस्"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनु"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"स्याटलाइट, खराब कनेक्सन"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"स्याटलाइट, राम्रो कनेक्सन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"स्याटलाइट, कनेक्सन उपलब्ध छ"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस आफू अनुकूल गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 7a37aa0..8dcfe9c 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hoortoestellen"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Nieuw apparaat koppelen"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nieuw apparaat te koppelen"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kan voorinstelling niet updaten"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Microfoon van apparaat niet meer blokkeren?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Apparaatcamera niet meer blokkeren?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Blokkeren van apparaatcamera en -microfoon opheffen?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Werk-apps hervatten?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Hervatten"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Widgets op het vergrendelscherm sluiten"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Widgets aanpassen"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets op het vergrendelscherm"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Gebruiker wijzigen"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pull-downmenu"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliet, slechte verbinding"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goede verbinding"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding beschikbaar"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Verbonden met satelliet"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Niet verbonden met satelliet"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Leuk voor sommige gebruikers, maar niet voor iedereen"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Met Systeem-UI-tuner beschikt u over extra manieren om de Android-gebruikersinterface aan te passen. Deze experimentele functies kunnen veranderen, vastlopen of verdwijnen in toekomstige releases. Ga voorzichtig verder."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 7e8ee6f..e164c3d 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ହିଅରିଂ ଡିଭାଇସଗୁଡ଼ିକ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ନୂଆ ଡିଭାଇସ ପେୟାର କର"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ନୂଆ ଡିଭାଇସ ପେୟାର କରିବାକୁ କ୍ଲିକ କରନ୍ତୁ"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ପ୍ରିସେଟକୁ ଅପଡେଟ କରାଯାଇପାରିଲା ନାହିଁ"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ କରିବେ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ଡିଭାଇସର କେମେରାକୁ ଅନବ୍ଲକ କରିବେ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ଡିଭାଇସର କ୍ୟାମେରା ଏବଂ ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ୍ କରିବେ?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ସାଟେଲାଇଟ, ଦୁର୍ବଳ କନେକ୍ସନ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ସାଟେଲାଇଟ, ଭଲ କନେକ୍ସନ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ସାଟେଲାଇଟ, କନେକ୍ସନ ଉପଲବ୍ଧ"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ସେଟେଲାଇଟ ସହ କନେକ୍ଟ ହୋଇଛନ୍ତି"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ସେଟେଲାଇଟ ସହ କନେକ୍ଟ ହୋଇନାହାଁନ୍ତି"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ୟୁଜର୍ ଇଣ୍ଟରଫେସ୍ ବଦଳାଇବାକୁ ତଥା ନିଜ ପସନ୍ଦ ଅନୁଯାୟୀ କରିବାକୁ ସିଷ୍ଟମ୍ UI ଟ୍ୟୁନର୍ ଆପଣଙ୍କୁ ଅତିରିକ୍ତ ଉପାୟ ପ୍ରଦାନ କରେ। ଏହି ପରୀକ୍ଷାମୂଳକ ସୁବିଧାମାନ ବଦଳିପାରେ, ଭାଙ୍ଗିପାରେ କିମ୍ବା ଭବିଷ୍ୟତର ରିଲିଜ୍ଗୁଡ଼ିକରେ ନଦେଖାଯାଇପାରେ। ସତର୍କତାର ସହ ଆଗକୁ ବଢ଼ନ୍ତୁ।"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index df823cf..4e43e17 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"\'ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ\' \'ਤੇ ਕਲਿੱਕ ਕਰੋ"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ਪ੍ਰੀਸੈੱਟ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਖਰਾਬ ਹੈ"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਵਧੀਆ ਹੈ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਉਪਲਬਧ ਹੈ"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"ਸੈਟੇਲਾਈਟ ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ਸੈਟੇਲਾਈਟ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਹੈ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ਕੁਝ ਵਾਸਤੇ ਤਾਂ ਮਜ਼ੇਦਾਰ ਹੈ ਲੇਕਿਨ ਸਾਰਿਆਂ ਵਾਸਤੇ ਨਹੀਂ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਵਰਤੋਂਕਾਰ ਇੰਟਰਫ਼ੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f6468af..f57fe29 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Urządzenia słuchowe"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sparuj nowe urządzenie"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknij, aby sparować nowe urządzenie"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nie udało się zaktualizować gotowego ustawienia"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokować mikrofon urządzenia?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokować aparat urządzenia?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Odblokować aparat i mikrofon urządzenia?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Cofnąć wstrzymanie aplikacji służbowych?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Cofnij wstrzymanie"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zamknij widżety na ekranie blokady"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Dostosuj widżety"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widżety na ekranie blokady"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelita – połączenie słabe"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelita – połączenie dobre"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelita – połączenie dostępne"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil służbowy"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dobra zabawa, ale nie dla każdego"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kalibrator System UI udostępnia dodatkowe sposoby dostrajania i dostosowywania interfejsu Androida. Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index a1c72dc..91b7a29 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparelhos auditivos"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parear novo dispositivo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Desbloquear a câmera e o microfone do dispositivo?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexão ruim"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index eadb5e54..41d092a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sincronizar novo dispositivo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para sincronizar um novo dispositivo"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmara do dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Quer desbloquear a câmara e o microfone?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, ligação fraca"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa ligação"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, ligação disponível"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Ligação de satélite estabelecida"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Não tem uma ligação de satélite estabelecida"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O Sintonizador da interface do sistema disponibiliza-lhe formas adicionais ajustar e personalizar a interface do utilizador do Android. Estas funcionalidades experimentais podem ser alteradas, deixar de funcionar ou desaparecer em versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index a1c72dc..91b7a29 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparelhos auditivos"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parear novo dispositivo"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Desbloquear a câmera e o microfone do dispositivo?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexão ruim"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index e53b4a4..7ccaa5a 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparate auditive"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Asociază un nou dispozitiv"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Dă clic pentru a asocia un nou dispozitiv"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nu s-a putut actualiza presetarea"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblochezi microfonul dispozitivului?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblochezi camera dispozitivului?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblochezi camera și microfonul dispozitivului?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, conexiune slabă"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, conexiune bună"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, conexiune disponibilă"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil de serviciu"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Distractiv pentru unii, dar nu pentru toată lumea"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner oferă modalități suplimentare de a ajusta și a personaliza interfața de utilizare Android. Aceste funcții experimentale pot să se schimbe, să se blocheze sau să dispară din versiunile viitoare. Continuă cu prudență."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8f6d7a8..fad12e4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слуховые аппараты"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Подключить новое устройство"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Нажмите, чтобы подключить новое устройство"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не удалось обновить набор настроек."</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблокировать микрофон устройства?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблокировать камеру устройства?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Разблокировать камеру и микрофон устройства?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Включить рабочие приложения?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Включить"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Закрыть виджеты на заблокированном экране"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Настроить виджеты"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Виджеты на заблокированном экране"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Сменить пользователя."</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"раскрывающееся меню"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спутниковая связь, плохое качество соединения"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутниковая связь, хорошее качество соединения"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступно соединение по спутниковой связи"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Рабочий профиль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Внимание!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner позволяет настраивать интерфейс устройства Android по вашему вкусу. В будущем эта экспериментальная функция может измениться, перестать работать или исчезнуть."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index afb5755..0473cd6 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ශ්රවණ උපාංග"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"නව උපාංගය යුගල කරන්න"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"නව උපාංගය යුගල කිරීමට ක්ලික් කරන්න"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"පෙර සැකසීම යාවත්කාලීන කළ නොහැකි විය"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"උපාංග මයික්රෆෝනය අවහිර කිරීම ඉවත් කරන්නද?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"උපාංග කැමරාව අවහිර කිරීම ඉවත් කරන්නද?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"උපාංග කැමරාව සහ මයික්රෆෝනය අවහිර කිරීම ඉවත් කරන්නද?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"කාර්ය යෙදුම් විරාම නොකරන්න ද?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"විරාම නොකරන්න"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"අගුළු තිරයෙහි විජට් වසන්න"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"විජට්ටු අභිරුචි කරන්න"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"අගුළු තිරයෙහි විජට්"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"පරිශීලක මාරුව"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"නිපතන මෙනුව"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"චන්ද්රිකාව, දුර්වල සම්බන්ධතාවය"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"චන්ද්රිකාව, හොඳ සම්බන්ධතාවයක්"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"චන්ද්රිකාව, සම්බන්ධතාවය තිබේ"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"කාර්යාල පැතිකඩ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"සමහරක් දේවල් වලට විනෝදයි, නමුත් සියල්ලටම නොවේ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"පද්ධති UI සුසරකය ඔබට Android පරිශීලක අතුරු මුහුණත වෙනස් කිරීමට හෝ අභිරුචිකරණය කිරීමට අමතර ක්රම ලබා දේ. මෙම පර්යේෂණාත්මක අංග ඉදිරි නිකුත් වීම් වල වෙනස් වීමට, වැඩ නොකිරීමට, හෝ නැතිවීමට හැක. ප්රවේශමෙන් ඉදිරියට යන්න."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 453dd44..9d71dbd 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Načúvacie zariadenia"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Párovanie nového zariadenia"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zariadenie"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Predvoľbu sa nepodarilo aktualizovať"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Chcete odblokovať mikrofón zariadenia?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Chcete odblokovať kameru zariadenia?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Chcete odblokovať fotoaparát a mikrofón zariadenia?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Zrušiť pozast. prac. aplikácií?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Zrušiť pozastavenie"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zavrieť miniaplikácie na uzamknutej obrazovke"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Prispôsobiť miniaplikácie"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Miniaplikácie na uzamknutej obrazovke"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Prepnutie používateľa"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbaľovacia ponuka"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slabá kvalita pripojenia"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobrá kvalita pripojenia"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, pripojenie je k dispozícii"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovný profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pri používaní tuneru postupujte opatrne"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tuner používateľského rozhrania systému poskytujte ďalšie spôsoby ladenia a prispôsobenia používateľského rozhrania Android. Tieto experimentálne funkcie sa môžu v budúcich verziách zmeniť, ich poskytovanie môže byť prerušené alebo môžu byť odstránené. Pokračujte opatrne."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 27c376a..d41de93 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni pripomočki"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Seznanitev nove naprave"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite za seznanitev nove naprave"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Prednastavljenih vrednosti ni bilo mogoče posodobiti"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite odblokirati mikrofon v napravi?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite odblokirati fotoaparat v napravi?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite odblokirati fotoaparat in mikrofon v napravi?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Želite znova aktivirati delovne aplikacije?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Znova aktiviraj"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zapiranje pripomočkov na zaklenjenem zaslonu"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Prilagajanje pripomočkov"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Pripomočki na zaklenjenem zaslonu"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"spustni meni"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba povezava"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra povezava"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, povezava je na voljo"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Povezana s satelitom je vzpostavljena"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Povezana s satelitom ni vzpostavljena"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Delovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabavno za nekatere, a ne za vse"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Uglaševalnik uporabniškega vmesnika sistema vam omogoča dodatne načine za spreminjanje in prilagajanje uporabniškega vmesnika Android. Te poskusne funkcije lahko v prihodnjih izdajah kadar koli izginejo, se spremenijo ali pokvarijo. Bodite previdni."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 071eda7..068a1a2 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Pajisjet e dëgjimit"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Çifto pajisje të re"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliko për të çiftuar një pajisje të re"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Paravendosja nuk mund të përditësohej"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Të zhbllokohet mikrofoni i pajisjes?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Të zhbllokohet kamera e pajisjes?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Të zhbllokohen kamera dhe mikrofoni i pajisjes?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Sateliti. Lidhje e dobët"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sateliti. Lidhje e mirë"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sateliti. Ofrohet lidhje"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profili i punës"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Argëtim për disa, por jo për të gjithë!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit të jep mënyra shtesë për të tërhequr dhe personalizuar ndërfaqen Android të përdoruesit. Këto funksione eksperimentale mund të ndryshojnë, prishen ose zhduken në versionet e ardhshme. Vazhdo me kujdes."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 233e516..0d33e32 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слушни апарати"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Упари нови уређај"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликните да бисте упарили нов уређај"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ажурирање задатих подешавања није успело"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Желите да одблокирате микрофон уређаја?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Желите да одблокирате камеру уређаја?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Желите да одблокирате камеру и микрофон уређаја?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Сателит, веза је лоша"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, веза је добра"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, веза је доступна"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Повезано са сателитом"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Није повезано са сателитом"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Пословни профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за неке, али не за све"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тјунер за кориснички интерфејс система вам пружа додатне начине за подешавање и прилагођавање Android корисничког интерфејса. Ове експерименталне функције могу да се промене, откажу или нестану у будућим издањима. Будите опрезни."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 579f526..36cf284 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hörhjälpmedel"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parkoppla en ny enhet"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicka för att parkoppla en ny enhet"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Det gick inte att uppdatera förinställningen"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vill du återaktivera enhetens mikrofon?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vill du återaktivera enhetens kamera?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vill du återaktivera enhetens kamera och mikrofon?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit, dålig anslutning"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, bra anslutning"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, anslutning tillgänglig"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Jobbprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kul för vissa, inte för alla"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Du kan använda inställningarna för systemgränssnitt för att justera användargränssnittet i Android. Dessa experimentfunktioner kan när som helst ändras, sluta fungera eller försvinna. Använd med försiktighet."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index bc7b016..34207f7 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Vifaa vya kusikilizia"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Unganisha kifaa kipya"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Bofya ili uunganishe kifaa kipya"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Imeshindwa kusasisha mipangilio iliyowekwa mapema"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Ungependa kuwacha kuzuia maikrofoni ya kifaa?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Ungependa kuacha kuzuia kamera ya kifaa?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Ungependa kuwacha kuzuia kamera na maikrofoni ya kifaa?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Setilaiti, muunganisho hafifu"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Setilaiti, muunganisho thabiti"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Setilaiti, muunganisho unapatikana"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Umeunganisha kwenye setilaiti"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Hujaunganisha kwenye setilaiti"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Wasifu wa kazini"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
diff --git a/packages/SystemUI/res/values-sw600dp-land/styles.xml b/packages/SystemUI/res/values-sw600dp-land/styles.xml
index 5ca2b43..0d46cbc 100644
--- a/packages/SystemUI/res/values-sw600dp-land/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/styles.xml
@@ -14,24 +14,28 @@
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-port/styles.xml b/packages/SystemUI/res/values-sw600dp-port/styles.xml
index 41d931d..3add566 100644
--- a/packages/SystemUI/res/values-sw600dp-port/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp-port/styles.xml
@@ -14,9 +14,10 @@
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <style name="AuthCredentialHeaderStyle">
+ <style name="AuthNonBioCredentialHeaderStyle">
<item name="android:paddingStart">120dp</item>
<item name="android:paddingEnd">120dp</item>
<item name="android:paddingTop">80dp</item>
@@ -25,10 +26,11 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/styles.xml b/packages/SystemUI/res/values-sw720dp-land/styles.xml
index d9406d3..7cdd07b 100644
--- a/packages/SystemUI/res/values-sw720dp-land/styles.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/styles.xml
@@ -14,25 +14,29 @@
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-port/styles.xml b/packages/SystemUI/res/values-sw720dp-port/styles.xml
index 41d931d..3add566 100644
--- a/packages/SystemUI/res/values-sw720dp-port/styles.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/styles.xml
@@ -14,9 +14,10 @@
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <style name="AuthCredentialHeaderStyle">
+ <style name="AuthNonBioCredentialHeaderStyle">
<item name="android:paddingStart">120dp</item>
<item name="android:paddingEnd">120dp</item>
<item name="android:paddingTop">80dp</item>
@@ -25,10 +26,11 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">36sp</item>
<item name="android:focusable">true</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index b2c83dc..3586172 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"செவித்துணைக் கருவிகள்"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"புதிய சாதனத்தை இணை"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"புதிய சாதனத்தை இணைக்க கிளிக் செய்யலாம்"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"முன்னமைவைப் புதுப்பிக்க முடியவில்லை"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"சாதனத்தின் மைக்ரோஃபோனுக்கான தடுப்பை நீக்கவா?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"சாதனத்தின் கேமராவுக்கான தடுப்பை நீக்கவா?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"சாதனத்தின் கேமராவுக்கும் மைக்ரோஃபோனுக்குமான தடுப்பை நீக்கவா?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"சாட்டிலைட், மோசமான இணைப்பு"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"சாட்டிலைட், நிலையான இணைப்பு"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"சாட்டிலைட், இணைப்பு கிடைக்கிறது"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"சாட்டிலைட்டுடன் இணைக்கப்பட்டுள்ளது"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"சாட்டிலைட்டுடன் இணைக்கப்படவில்லை"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"பணிக் கணக்கு"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"சில வேடிக்கையாக இருந்தாலும் கவனம் தேவை"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner, Android பயனர் இடைமுகத்தை மாற்றவும் தனிப்பயனாக்கவும் கூடுதல் வழிகளை வழங்குகிறது. இந்தப் பரிசோதனைக்குரிய அம்சங்கள் எதிர்கால வெளியீடுகளில் மாற்றப்படலாம், இடைநிறுத்தப்படலாம் அல்லது தோன்றாமல் போகலாம். கவனத்துடன் தொடரவும்."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 5cd1341..2d76896 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"వినికిడి పరికరం"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"కొత్త పరికరాన్ని పెయిర్ చేయడానికి క్లిక్ చేయండి"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ప్రీసెట్ను అప్డేట్ చేయడం సాధ్యపడలేదు"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"పరికరం మైక్రోఫోన్ను అన్బ్లాక్ చేయమంటారా?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"పరికరంలోని కెమెరాను అన్బ్లాక్ చేయమంటారా?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"పరికరంలోని కెమెరా, మైక్రోఫోన్లను అన్బ్లాక్ చేయమంటారా?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"వర్క్ యాప్స్ అన్పాజ్ చేయాలా?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"అన్పాజ్ చేయండి"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"లాక్ స్క్రీన్లో విడ్జెట్లను మూసివేయండి"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"విడ్జెట్లను అనుకూలంగా మార్చండి"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"లాక్ స్క్రీన్లో విడ్జెట్లు"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"వినియోగదారుని మార్చు"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"పుల్డౌన్ మెనూ"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"శాటిలైట్, కనెక్షన్ సరిగా లేదు"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"శాటిలైట్, కనెక్షన్ బాగుంది"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"శాటిలైట్, కనెక్షన్ అందుబాటులో ఉంది"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"శాటిలైట్కు కనెక్ట్ చేయబడింది"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"శాటిలైట్కు కనెక్ట్ కాలేదు"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ఆఫీస్ ప్రొఫైల్"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"కొందరికి సరదాగా ఉంటుంది కానీ అందరికీ అలాగే ఉండదు"</string>
<string name="tuner_warning" msgid="1861736288458481650">"సిస్టమ్ UI ట్యూనర్ Android వినియోగదారు ఇంటర్ఫేస్ను మెరుగుపరచడానికి మరియు అనుకూలంగా మార్చడానికి మీకు మరిన్ని మార్గాలను అందిస్తుంది. ఈ ప్రయోగాత్మక లక్షణాలు భవిష్యత్తు విడుదలల్లో మార్పుకు లోనవ్వచ్చు, తాత్కాలికంగా లేదా పూర్తిగా నిలిపివేయవచ్చు. జాగ్రత్తగా కొనసాగండి."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 544844d..7157e26 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"เครื่องช่วยฟัง"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"จับคู่อุปกรณ์ใหม่"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"คลิกเพื่อจับคู่อุปกรณ์ใหม่"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ไม่สามารถอัปเดตค่าที่กำหนดล่วงหน้า"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"เลิกบล็อกไมโครโฟนของอุปกรณ์ใช่ไหม"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"เลิกบล็อกกล้องของอุปกรณ์ใช่ไหม"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"เลิกบล็อกกล้องและไมโครโฟนของอุปกรณ์ใช่ไหม"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ดาวเทียม, การเชื่อมต่อไม่ดี"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ดาวเทียม, การเชื่อมต่อดี"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ดาวเทียม, การเชื่อมต่อที่พร้อมใช้งาน"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"เชื่อมต่อกับดาวเทียมแล้ว"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"ยังไม่ได้เชื่อมต่อกับดาวเทียม"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"โปรไฟล์งาน"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 13e4bf8..51782a3 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Mga hearing device"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Magpares ng bagong device"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"I-click para magpares ng bagong device"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hindi ma-update ang preset"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"I-unblock ang mikropono ng device?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"I-unblock ang camera ng device?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"I-unblock ang camera at mikropono ng device?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, mahina ang koneksyon"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, malakas ang koneksyon"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, may koneksyon"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profile sa trabaho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Masaya para sa ilan ngunit hindi para sa lahat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nagbibigay sa iyo ang Tuner ng System UI ng mga karagdagang paraan upang baguhin at i-customize ang user interface ng Android. Ang mga pang-eksperimentong feature na ito ay maaaring magbago, masira o mawala sa mga pagpapalabas sa hinaharap. Magpatuloy nang may pag-iingat."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 30b6ce4..bf85818 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"İşitme cihazları"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yeni cihaz eşle"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz eşlemek için tıklayın"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hazır ayar güncellenemedi"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonunun engellemesi kaldırılsın mı?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerasının engellemesi kaldırılsın mı?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Cihaz kamerası ile mikrofonunun engellemesi kaldırılsın mı?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Uydu, bağlantı zayıf"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Uydu, bağlantı güçlü"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Uydu, bağlantı mevcut"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Bazıları için eğlenceliyken diğerleri için olmayabilir"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistem Kullanıcı Arayüzü Ayarlayıcı, Android kullanıcı arayüzünde değişiklikler yapmanız ve arayüzü özelleştirmeniz için ekstra yollar sağlar. Bu deneysel özellikler değişebilir, bozulabilir veya gelecekteki sürümlerde yer almayabilir. Dikkatli bir şekilde devam edin."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index e1d768e..71f1fb6 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слухові апарати"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Підключити новий пристрій"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Натисніть, щоб підключити новий пристрій"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не вдалось оновити набір налаштувань"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Надати доступ до мікрофона?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Надати доступ до камери пристрою?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Надати доступ до камери й мікрофона?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Погане з’єднання із супутником"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хороше з’єднання із супутником"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступне з’єднання із супутником"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Робочий профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Це цікаво, але будьте обачні"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner пропонує нові способи налаштувати та персоналізувати інтерфейс користувача Android. Ці експериментальні функції можуть змінюватися, не працювати чи зникати в майбутніх версіях. Будьте обачні."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 16b40bf..0b79b1c 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سماعت کے آلات"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"نئے آلے کا جوڑا بنائیں"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"نئے آلے کا جوڑا بنانے کے لیے کلک کریں"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"پہلے سے ترتیب شدہ کو اپ ڈیٹ نہیں کیا جا سکا"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"آلے کا مائیکروفون غیر مسدود کریں؟"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"آلے کا کیمرا غیر مسدود کریں؟"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"آلے کا کیمرا اور مائیکروفون غیر مسدود کریں؟"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"ورک ایپس کو غیر موقوف کریں؟"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"غیر موقوف کریں"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"مقفل اسکرین پر ویجٹس بند کریں"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"ویجیٹس کو حسب ضرورت بنائیں"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"مقفل اسکرین پر ویجیٹس"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"صارف سوئچ کریں"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"پل ڈاؤن مینیو"</string>
@@ -656,6 +654,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"سیٹلائٹ، کنکشن خراب ہے"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"سیٹلائٹ، کنکشن اچھا ہے"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"سیٹلائٹ، کنکشن دستیاب ہے"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"دفتری پروفائل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"کچھ کیلئے دلچسپ لیکن سبھی کیلئے نہیں"</string>
<string name="tuner_warning" msgid="1861736288458481650">"سسٹم UI ٹیونر Android صارف انٹر فیس میں ردوبدل کرنے اور اسے حسب ضرورت بنانے کیلئے آپ کو اضافی طریقے دیتا ہے۔ یہ تجرباتی خصوصیات مستقبل کی ریلیزز میں تبدیل ہو سکتی، رک سکتی یا غائب ہو سکتی ہیں۔ احتیاط کے ساتھ آگے بڑھیں۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 76694df..78def5d 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Eshitish qurilmalari"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yangi qurilmani ulash"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yangi qurilmani ulash uchun bosing"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Andoza yangilanmadi"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Qurilma mikrofoni blokdan chiqarilsinmi?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Qurilma kamerasi blokdan chiqarilsinmi?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Qurilma kamerasi va mikrofoni blokdan chiqarilsinmi?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Sputnik, aloqa sifati past"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sputnik, aloqa sifati yaxshi"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sputnik, aloqa mavjud"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Sputnikka ulangan"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Sputnikka ulanmagan"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ish profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diqqat!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner yordamida siz Android foydalanuvchi interfeysini tuzatish va o‘zingizga moslashtirishingiz mumkin. Ushbu tajribaviy funksiyalar o‘zgarishi, buzilishi yoki keyingi versiyalarda olib tashlanishi mumkin. Ehtiyot bo‘lib davom eting."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 41066f9..e50dd2f 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Thiết bị trợ thính"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Ghép nối thiết bị mới"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Nhấp để ghép nối thiết bị mới"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Không cập nhật được giá trị đặt trước"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Bỏ chặn micrô của thiết bị?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Bỏ chặn camera của thiết bị?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Bỏ chặn máy ảnh và micrô của thiết bị?"</string>
@@ -656,6 +655,10 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Kết nối vệ tinh kém"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Kết nối vệ tinh tốt"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Hiện có kết nối vệ tinh"</string>
+ <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+ <skip />
+ <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+ <skip />
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Hồ sơ công việc"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Thú vị đối với một số người nhưng không phải tất cả"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Bộ điều hướng giao diện người dùng hệ thống cung cấp thêm cho bạn những cách chỉnh sửa và tùy chỉnh giao diện người dùng Android. Những tính năng thử nghiệm này có thể thay đổi, hỏng hoặc biến mất trong các phiên bản tương lai. Hãy thận trọng khi tiếp tục."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 60a46d60..b0740a5 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -268,7 +268,7 @@
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"点按即可连接设备或断开设备连接"</string>
<string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"与新设备配对"</string>
<string name="see_all_bluetooth_devices" msgid="1761596816620200433">"查看全部"</string>
- <string name="turn_on_bluetooth" msgid="5681370462180289071">"使用蓝牙"</string>
+ <string name="turn_on_bluetooth" msgid="5681370462180289071">"启用蓝牙"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已连接"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音频分享"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已保存"</string>
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助听装置"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"与新设备配对"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"点击即可与新设备配对"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"无法更新预设"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解锁设备麦克风吗?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解锁设备摄像头吗?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要解锁设备摄像头和麦克风吗?"</string>
@@ -656,6 +655,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"卫星,连接质量不佳"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"卫星,连接质量良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"卫星,可连接"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"已连接到卫星"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"未连接到卫星"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作资料"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"并不适合所有用户"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系统界面调节工具可让您以更多方式调整及定制 Android 界面。在日后推出的版本中,这些实验性功能可能会变更、失效或消失。操作时请务必谨慎。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 995129e..94dd480 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助聽器"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"配對新裝置"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"㩒一下就可以配對新裝置"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"無法更新預設"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解除封鎖裝置相機嗎?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要解除封鎖裝置相機和麥克風嗎?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"要取消暫停工作應用程式嗎?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"取消暫停"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"關閉上鎖畫面上的小工具"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"自訂小工具"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"上鎖畫面上的小工具"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛星,連線質素唔好"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線質素好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可以連線"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"已連上衛星"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"未連上衛星"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作設定檔"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"這只是測試版本,並不包含完整功能"</string>
<string name="tuner_warning" msgid="1861736288458481650">"使用者介面調諧器讓你以更多方法修改和自訂 Android 使用者介面。但請小心,這些實驗功能可能會在日後發佈時更改、分拆或消失。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d18f828..d072c77 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助聽器"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"配對新裝置"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"按一下即可配對新裝置"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"無法更新預設設定"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解除封鎖裝置相機嗎?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要將裝置的相機和麥克風解除封鎖嗎?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"要解除工作應用程式的暫停狀態嗎?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"取消暫停"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"關閉螢幕鎖定畫面上的小工具"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"自訂小工具"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"螢幕鎖定畫面上的小工具"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛星,連線品質不佳"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線品質良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可連線"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"已連上衛星"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"未連上衛星"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作資料夾"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"有趣與否,見仁見智"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系統使用者介面調整精靈可讓你透過其他方式,調整及自訂 Android 使用者介面。這些實驗性功能隨著版本更新可能會變更、損壞或消失,執行時請務必謹慎。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a5caa3d..6c746d3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -371,8 +371,7 @@
<string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Izinsizakuzwa"</string>
<string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Bhangqa idivayisi entsha"</string>
<string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Chofoza ukuze ubhangqe idivayisi entsha"</string>
- <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
- <skip />
+ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ayikwazanga ukubuyekeza ukusetha ngaphambilini"</string>
<string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vulela imakrofoni yedivayisi?"</string>
<string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vulela ikhamera yedivayisi?"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vulela ikhamera yedivayisi nemakrofoni?"</string>
@@ -458,8 +457,7 @@
<string name="work_mode_off_title" msgid="5794818421357835873">"Susa ukumisa ama-app omsebenzi?"</string>
<string name="work_mode_turn_on" msgid="907813741770247267">"Qhubekisa"</string>
<string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Vala amawijethi ekukhiyeni isikrini"</string>
- <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
- <skip />
+ <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Yenza ngokwezifiso amawijethi"</string>
<string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Amawijethi ekukhiyeni isikrini"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Shintsha umsebenzisi"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"imenyu yokudonsela phansi"</string>
@@ -656,6 +654,8 @@
<string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Isathelayithi, uxhumano olungalungile"</string>
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Isethelayithi, uxhumano oluhle"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Isethelayithi, uxhumano luyatholakala"</string>
+ <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Ixhunywe esethelayithini"</string>
+ <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Ayixhunyiwe esethelayithini"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Iphrofayela yomsebenzi"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kuyajabulisa kwabanye kodwa hhayi bonke"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Isishuni se-UI sesistimu sikunika izindlela ezingeziwe zokuhlobisa nokwenza ngezifiso isixhumanisi sokubona se-Android. Lezi zici zesilingo zingashintsha, zephuke, noma zinyamalale ekukhishweni kwangakusasa. Qhubeka ngokuqaphela."</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 19273ec..6bfd088 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -461,10 +461,11 @@
This name is in the ComponentName flattened format (package/class) -->
<string name="config_screenshotEditor" translatable="false"></string>
- <!-- ComponentName for the file browsing app that the system would expect to be used in work
- profile. The icon for this app will be shown to the user when informing them that a
- screenshot has been saved to work profile. If blank, a default icon will be shown. -->
- <string name="config_sceenshotWorkProfileFilesApp" translatable="false"></string>
+ <!-- ComponentName for the file browsing app that the system would expect to be used for
+ screenshots. The icon for this app will be shown to the user when informing them that a
+ screenshot has been saved to a different profile (e.g. work profile). If blank, a default
+ icon will be shown. -->
+ <string name="config_screenshotFilesApp" translatable="false"></string>
<!-- The component name of the screenshot editing activity that provides the App Clips flow.
The App Clips flow includes taking a screenshot, showing user screenshot cropping activity
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1b2362d..a7a6d5b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -616,7 +616,7 @@
<dimen name="volume_panel_slice_vertical_padding">8dp</dimen>
<dimen name="volume_panel_slice_horizontal_padding">24dp</dimen>
- <dimen name="volume_panel_corner_radius">28dp</dimen>
+ <dimen name="bottom_sheet_corner_radius">28dp</dimen>
<!-- Size of each item in the ringer selector drawer. -->
<dimen name="volume_ringer_drawer_item_size">42dp</dimen>
@@ -1094,9 +1094,9 @@
<dimen name="remote_input_history_extra_height">60dp</dimen>
<!-- Biometric Dialog values -->
- <dimen name="biometric_dialog_face_icon_size">54dp</dimen>
- <dimen name="biometric_dialog_fingerprint_icon_width">80dp</dimen>
- <dimen name="biometric_dialog_fingerprint_icon_height">80dp</dimen>
+ <dimen name="biometric_dialog_face_icon_size">68dp</dimen>
+ <dimen name="biometric_dialog_fingerprint_icon_width">100dp</dimen>
+ <dimen name="biometric_dialog_fingerprint_icon_height">100dp</dimen>
<dimen name="biometric_dialog_button_negative_max_width">160dp</dimen>
<dimen name="biometric_dialog_button_positive_max_width">136dp</dimen>
<dimen name="biometric_dialog_corner_size">28dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b8e78a4..dcdd4f0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -257,6 +257,8 @@
<string name="screenshot_right_boundary_pct">Right boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>
<!-- Notification displayed when a screenshot is saved in a work profile. [CHAR LIMIT=NONE] -->
<string name="screenshot_work_profile_notification">Saved in <xliff:g id="app" example="Files">%1$s</xliff:g> in the work profile</string>
+ <!-- Notification displayed when a screenshot is saved in the private profile. [CHAR LIMIT=NONE] -->
+ <string name="screenshot_private_profile_notification">Saved in <xliff:g id="app" example="Files">%1$s</xliff:g> in the private profile</string>
<!-- Default name referring to the app on the device that lets the user browse stored files. [CHAR LIMIT=NONE] -->
<string name="screenshot_default_files_app_name">Files</string>
<!-- A notice shown to the user to indicate that an app has detected the screenshot that the user has just taken. [CHAR LIMIT=75] -->
@@ -1182,6 +1184,8 @@
<string name="accessibility_action_label_edit_widgets">Customize widgets</string>
<!-- Accessibility content description for communal hub. [CHAR LIMIT=NONE] -->
<string name="accessibility_content_description_for_communal_hub">Widgets on lock screen</string>
+ <!-- Label for accessibility action to select a widget in edit mode. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_label_select_widget">select widget</string>
<!-- Related to user switcher --><skip/>
@@ -1630,12 +1634,15 @@
<!-- Hint for accessibility. A stream name is a parameter. For example: double tap to unmute media [CHAR_LIMIT=NONE] -->
<string name="volume_panel_hint_unmute">unmute %s</string>
- <!-- Title with application label for media output settings. [CHAR LIMIT=20] -->
+ <!-- Title with application label for media output settings when there is media playing. [CHAR LIMIT=20] -->
<string name="media_output_label_title">Playing <xliff:g id="label" example="Music Player">%s</xliff:g> on</string>
<!-- Title for media output settings without media is playing. [CHAR LIMIT=20] -->
<string name="media_output_title_without_playing">Audio will play on</string>
+ <!-- Title for media output settings when there is an ongoing call in progress. [CHAR LIMIT=20] -->
+ <string name="media_output_title_ongoing_call">Calling on</string>
+
<!-- Name of special SystemUI debug settings -->
<string name="system_ui_tuner">System UI Tuner</string>
@@ -1719,9 +1726,7 @@
<string name="accessibility_status_bar_satellite_available">Satellite, connection available</string>
<!-- Text displayed indicating that the user is connected to a satellite signal. -->
- <string name="satellite_connected_carrier_text">Connected to satellite</string>
- <!-- Text displayed indicating that the user is not connected to a satellite signal. -->
- <string name="satellite_not_connected_carrier_text">Not connected to satellite</string>
+ <string name="satellite_connected_carrier_text">Satellite SOS</string>
<!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] -->
<string name="accessibility_managed_profile">Work profile</string>
@@ -2261,6 +2266,9 @@
<!-- Accessibility description when QS tile is to be added, indicating the destination position [CHAR LIMIT=NONE] -->
<string name="accessibility_qs_edit_tile_add_to_position">Add to position <xliff:g id="position" example="5">%1$d</xliff:g></string>
+ <!-- Accessibility description when QS tile would be added or moved, but the current position is not valid for adding or moving to [CHAR LIMIT=NONE] -->
+ <string name="accessibilit_qs_edit_tile_add_move_invalid_position">Position invalid.</string>
+
<!-- Accessibility description indicating the currently selected tile's position. Only used for tiles that are currently in use [CHAR LIMIT=NONE] -->
<string name="accessibility_qs_edit_position">Position <xliff:g id="position" example="5">%1$d</xliff:g></string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3d57111..69de45e 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -175,27 +175,28 @@
</style>
<style name="TextAppearance.AuthCredential.OldTitle">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:paddingTop">12dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">24sp</item>
</style>
<style name="TextAppearance.AuthCredential.OldSubtitle">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">16sp</item>
</style>
<style name="TextAppearance.AuthCredential.OldDescription">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">14sp</item>
</style>
<style name="TextAppearance.AuthCredential.LogoDescription" parent="TextAppearance.Material3.LabelLarge" >
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:ellipsize">marquee</item>
<item name="android:gravity">@integer/biometric_dialog_text_gravity</item>
<item name="android:marqueeRepeatLimit">1</item>
@@ -204,30 +205,36 @@
</style>
<style name="TextAppearance.AuthCredential.Title" parent="TextAppearance.Material3.HeadlineSmall" >
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthCredential.Subtitle" parent="TextAppearance.Material3.BodyMedium" >
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthCredential.Description" parent="TextAppearance.Material3.BodyMedium" >
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthCredential.VerticalListContentViewDescription" parent="TextAppearance.Material3.TitleSmall">
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthCredential.ContentViewWithButtonDescription" parent="TextAppearance.AuthCredential.Description" />
<style name="TextAppearance.AuthCredential.ContentViewListItem" parent="TextAppearance.Material3.BodySmall">
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item>
<item name="android:paddingTop">@dimen/biometric_prompt_content_list_item_padding_top</item>
<item name="android:breakStrategy">high_quality</item>
</style>
<style name="TextAppearance.AuthCredential.Indicator" parent="TextAppearance.Material3.BodyMedium">
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
<item name="android:marqueeRepeatLimit">marquee_forever</item>
<item name="android:singleLine">true</item>
@@ -250,22 +257,25 @@
</style>
<style name="TextAppearance.AuthNonBioCredential.Title">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">36dp</item>
<item name="android:focusable">true</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Subtitle">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Description">
- <item name="android:fontFamily">google-sans</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:textSize">18sp</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
</style>
<style name="TextAppearance.AuthNonBioCredential.Error">
@@ -282,7 +292,7 @@
<item name="android:gravity">start</item>
</style>
- <style name="TextAppearance.AuthCredential.PasswordEntry" parent="@android:style/TextAppearance.DeviceDefault">
+ <style name="TextAppearance.AuthNonBioCredential.PasswordEntry" parent="@android:style/TextAppearance.DeviceDefault">
<item name="android:gravity">center</item>
<item name="android:paddingTop">28dp</item>
<item name="android:singleLine">true</item>
@@ -291,7 +301,7 @@
<item name="android:background">@drawable/edit_text_filled</item>
</style>
- <style name="AuthCredentialHeaderStyle">
+ <style name="AuthNonBioCredentialHeaderStyle">
<item name="android:paddingStart">48dp</item>
<item name="android:paddingEnd">48dp</item>
<item name="android:paddingTop">48dp</item>
@@ -299,12 +309,12 @@
<item name="android:layout_gravity">top</item>
</style>
- <style name="AuthCredentialIconStyle">
+ <style name="AuthNonBioCredentialIconStyle">
<item name="android:layout_width">@dimen/biometric_auth_icon_size</item>
<item name="android:layout_height">@dimen/biometric_auth_icon_size</item>
</style>
- <style name="AuthCredentialPatternContainerStyle">
+ <style name="AuthNonBioCredentialPatternContainerStyle">
<item name="android:gravity">center</item>
<item name="android:maxHeight">@dimen/biometric_auth_pattern_view_max_size</item>
<item name="android:maxWidth">@dimen/biometric_auth_pattern_view_max_size</item>
@@ -314,7 +324,7 @@
<item name="android:paddingVertical">20dp</item>
</style>
- <style name="AuthCredentialPinPasswordContainerStyle">
+ <style name="AuthNonBioCredentialPinPasswordContainerStyle">
<item name="android:gravity">center</item>
<item name="android:maxHeight">48dp</item>
<item name="android:maxWidth">600dp</item>
@@ -322,7 +332,7 @@
<item name="android:minWidth">200dp</item>
</style>
- <style name="AuthCredentialEmergencyButtonStyle">
+ <style name="AuthNonBioCredentialEmergencyButtonStyle">
<item name="android:background">@drawable/auth_credential_emergency_button_background</item>
<item name="android:textColor">@android:color/system_accent3_900</item>
<item name="android:outlineProvider">none</item>
@@ -333,6 +343,14 @@
<item name="android:textSize">16sp</item>
</style>
+ <style name="AuthCredentialPanelStyle">
+ <item name="android:background">?androidprv:attr/materialColorSurfaceBright</item>
+ <item name="android:clickable">true</item>
+ <item name="android:clipToOutline">true</item>
+ <item name="android:importantForAccessibility">no</item>
+ <item name="android:visibility">visible</item>
+ </style>
+
<style name="AuthCredentialContentViewStyle">
<item name="android:gravity">center_vertical</item>
<item name="android:orientation">vertical</item>
@@ -345,6 +363,7 @@
</style>
<style name="AuthCredentialContentViewMoreOptionsButtonStyle" parent="TextAppearance.Material3.LabelLarge">
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:background">@color/transparent</item>
<item name="android:gravity">start</item>
<item name="enforceTextAppearance">false</item>
@@ -436,17 +455,17 @@
<item name="android:textColor">?attr/wallpaperTextColor</item>
</style>
- <style name="AuthCredentialStyle">
+ <style name="AuthNonBioCredentialStyle">
<item name="*android:regularColor">?android:attr/colorForeground</item>
<item name="*android:successColor">?android:attr/colorForeground</item>
<item name="*android:errorColor">?android:attr/colorError</item>
<item name="*android:dotColor">?android:attr/textColorSecondary</item>
- <item name="headerStyle">@style/AuthCredentialHeaderStyle</item>
- <item name="headerIconStyle">@style/AuthCredentialIconStyle</item>
+ <item name="headerStyle">@style/AuthNonBioCredentialHeaderStyle</item>
+ <item name="headerIconStyle">@style/AuthNonBioCredentialIconStyle</item>
<item name="titleTextAppearance">@style/TextAppearance.AuthNonBioCredential.Title</item>
<item name="subTitleTextAppearance">@style/TextAppearance.AuthNonBioCredential.Subtitle</item>
<item name="descriptionTextAppearance">@style/TextAppearance.AuthNonBioCredential.Description</item>
- <item name="passwordTextAppearance">@style/TextAppearance.AuthCredential.PasswordEntry</item>
+ <item name="passwordTextAppearance">@style/TextAppearance.AuthNonBioCredential.PasswordEntry</item>
<item name="errorTextAppearance">@style/TextAppearance.AuthNonBioCredential.Error</item>
<item name="errorTextAppearanceLand">@style/TextAppearance.AuthNonBioCredential.ErrorLand</item>
</style>
@@ -458,12 +477,12 @@
<item name="*android:dotColor">?android:attr/textColorSecondary</item>
</style>
- <style name="LockPatternContainerStyle" parent="@style/AuthCredentialStyle">
- <item name="containerStyle">@style/AuthCredentialPatternContainerStyle</item>
+ <style name="LockPatternContainerStyle" parent="@style/AuthNonBioCredentialStyle">
+ <item name="containerStyle">@style/AuthNonBioCredentialPatternContainerStyle</item>
</style>
- <style name="LockPinPasswordContainerStyle" parent="@style/AuthCredentialStyle">
- <item name="containerStyle">@style/AuthCredentialPinPasswordContainerStyle</item>
+ <style name="LockPinPasswordContainerStyle" parent="@style/AuthNonBioCredentialStyle">
+ <item name="containerStyle">@style/AuthNonBioCredentialPinPasswordContainerStyle</item>
</style>
<style name="Theme.SystemUI.QuickSettings" parent="@*android:style/Theme.DeviceDefault">
@@ -537,6 +556,12 @@
<item name="android:buttonBarButtonStyle">@style/Widget.Dialog.Button.Large</item>
</style>
+ <style name="Theme.SystemUI.BottomSheet" parent="Theme.SystemUI.Dialog">
+ <!-- default dialog background has insets -->
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowAnimationStyle">@style/Animation.Design.BottomSheetDialog</item>
+ </style>
+
<style name="AlertDialogStyle" parent="@androidprv:style/AlertDialog.DeviceDefault">
<item name="android:layout">@layout/alert_dialog_systemui</item>
</style>
@@ -773,7 +798,6 @@
<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:clickable">true</item>
<item name="android:splitTrack">false</item>
</style>
@@ -1012,23 +1036,11 @@
<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>
- <style name="Theme.VolumePanelActivity" parent="@android:style/Theme.DeviceDefault.DayNight">
- <item name="android:windowFullscreen">true</item>
- <item name="android:windowContentOverlay">@null</item>
- <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:backgroundDimEnabled">true</item>
- <item name="android:windowCloseOnTouchOutside">true</item>
- <item name="android:windowAnimationStyle">@null</item>
- </style>
-
<style name="Widget.SliceView.VolumePanel">
<item name="hideHeaderRow">true</item>
</style>
- <style name="Theme.VolumePanelActivity.Popup" parent="@style/Theme.SystemUI.Dialog">
+ <style name="Theme.VolumePanel.Popup" parent="@style/Theme.SystemUI.Dialog">
<item name="android:dialogCornerRadius">44dp</item>
<item name="android:colorBackground">?androidprv:attr/materialColorSurfaceContainerHigh
</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 87b473f..6e1b670 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -74,6 +74,7 @@
* Contains logic that deals with showing a rotate suggestion button with animation.
*/
public class RotationButtonController {
+ public static final boolean DEBUG_ROTATION = false;
private static final String TAG = "RotationButtonController";
private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index b916fc2..91fb688 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -81,7 +81,6 @@
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardWmStateRefactor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -304,7 +303,7 @@
*/
@Override
public void finish(int targetUserId) {
- if (!RefactorKeyguardDismissIntent.isEnabled()) {
+ if (!SceneContainerFlag.isEnabled()) {
// If there's a pending runnable because the user interacted with a widget
// and we're leaving keyguard, then run it.
boolean deferKeyguardDone = false;
@@ -614,7 +613,7 @@
* @param action callback to be invoked when keyguard disappear animation completes.
*/
public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
- if (RefactorKeyguardDismissIntent.isEnabled()) {
+ if (SceneContainerFlag.isEnabled()) {
return;
}
if (mCancelAction != null) {
@@ -908,7 +907,7 @@
mUiEventLogger.log(uiEvent, getSessionId());
}
- if (RefactorKeyguardDismissIntent.isEnabled()) {
+ if (SceneContainerFlag.isEnabled()) {
if (authenticatedWithPrimaryAuth) {
mPrimaryBouncerInteractor.get()
.notifyKeyguardAuthenticatedPrimaryAuth(targetUserId);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 519622e..167ab90 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -30,6 +30,8 @@
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
import static android.hardware.biometrics.BiometricConstants.LockoutMode;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
import static android.hardware.biometrics.BiometricSourceType.FACE;
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
@@ -1238,9 +1240,9 @@
boolean cameraPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(
SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, SensorPrivacyManager.Sensors.CAMERA);
- final boolean isHwUnavailable = msgId == FaceManager.FACE_ERROR_HW_UNAVAILABLE;
+ final boolean isHwUnavailable = msgId == FACE_ERROR_HW_UNAVAILABLE;
- if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
+ if (msgId == FACE_ERROR_LOCKOUT_PERMANENT) {
if (getFaceAuthInteractor() != null && getFaceAuthInteractor().isFaceAuthStrong()) {
updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index b8af59d..4c9af66 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -121,6 +121,9 @@
SystemProperties.getBoolean("debug.disable_screen_decorations", false);
private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
+
+ private static final boolean sToolkitSetFrameRateReadOnly =
+ android.view.flags.Flags.toolkitSetFrameRateReadOnly();
private boolean mDebug = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
private int mDebugColor = Color.RED;
@@ -892,6 +895,10 @@
lp.width = MATCH_PARENT;
lp.height = MATCH_PARENT;
lp.setTitle("ScreenDecorHwcOverlay");
+ if (sToolkitSetFrameRateReadOnly) {
+ lp.setFrameRateBoostOnTouchEnabled(false);
+ lp.setFrameRatePowerSavingsBalanced(false);
+ }
lp.gravity = Gravity.TOP | Gravity.START;
if (!mDebug) {
lp.setColorMode(ActivityInfo.COLOR_MODE_A8);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index c6716e4..68a69d3 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -192,6 +192,7 @@
private final ShadeController mShadeController;
private final Lazy<PanelExpansionInteractor> mPanelExpansionInteractor;
private final StatusBarWindowCallback mNotificationShadeCallback;
+ private final ScreenshotHelper mScreenshotHelper;
private boolean mDismissNotificationShadeActionRegistered;
@Inject
@@ -221,6 +222,7 @@
(keyguardShowing, keyguardOccluded, keyguardGoingAway, bouncerShowing, mDozing,
panelExpanded, isDreaming) ->
registerOrUnregisterDismissNotificationShadeAction();
+ mScreenshotHelper = new ScreenshotHelper(mContext);
}
@Override
@@ -516,8 +518,7 @@
}
private void handleTakeScreenshot() {
- ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
- screenshotHelper.takeScreenshot(
+ mScreenshotHelper.takeScreenshot(
SCREENSHOT_ACCESSIBILITY_ACTIONS, new Handler(Looper.getMainLooper()), null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
index b8ff0c0..99be762 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
@@ -112,6 +112,7 @@
const val COLOR_INVERSION_TILE_SPEC = "inversion"
const val FONT_SCALING_TILE_SPEC = "font_scaling"
const val REDUCE_BRIGHTNESS_TILE_SPEC = "reduce_brightness"
+ const val ONE_HANDED_TILE_SPEC = "onehanded"
@Provides
@IntoMap
@@ -241,5 +242,19 @@
mapper,
)
else StubQSTileViewModel
+
+ @Provides
+ @IntoMap
+ @StringKey(ONE_HANDED_TILE_SPEC)
+ fun provideOneHandedTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(ONE_HANDED_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = com.android.internal.R.drawable.ic_qs_one_handed_mode,
+ labelRes = R.string.quick_settings_onehanded_label,
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
index e7e12ba..227e4db 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
@@ -19,6 +19,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static com.android.systemui.shared.Flags.bouncerAreaExclusion;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.graphics.Rect;
import android.graphics.Region;
@@ -37,7 +38,9 @@
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
+import com.android.systemui.Flags;
import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
@@ -69,6 +72,9 @@
public String TAG = "DreamOverlayTouchMonitor";
private final Executor mMainExecutor;
private final Executor mBackgroundExecutor;
+
+ private final ConfigurationInteractor mConfigurationInteractor;
+
private final Lifecycle mLifecycle;
private Rect mExclusionRect = null;
@@ -82,6 +88,8 @@
}
};
+ private Consumer<Rect> mMaxBoundsConsumer = rect -> mMaxBounds = rect;
+
/**
* Adds a new {@link TouchSessionImpl} to participate in receiving future touches and gestures.
@@ -262,6 +270,7 @@
*/
private void startMonitoring() {
stopMonitoring(true);
+
if (bouncerAreaExclusion()) {
mBackgroundExecutor.execute(() -> {
try {
@@ -340,8 +349,13 @@
if (!handler.isEnabled()) {
continue;
}
- final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(),
- TYPE_APPLICATION_OVERLAY);
+
+ final Rect maxBounds =
+ Flags.ambientTouchMonitorListenToDisplayChanges()
+ ? mMaxBounds
+ : mDisplayHelper.getMaxBounds(ev.getDisplayId(),
+ TYPE_APPLICATION_OVERLAY);
+
final Region initiationRegion = Region.obtain();
Rect exclusionRect = null;
if (bouncerAreaExclusion()) {
@@ -478,6 +492,8 @@
private final int mDisplayId;
private final IWindowManager mWindowManagerService;
+ private Rect mMaxBounds;
+
/**
* Designated constructor for {@link TouchMonitor}
@@ -500,6 +516,7 @@
Lifecycle lifecycle,
InputSessionComponent.Factory inputSessionFactory,
DisplayHelper displayHelper,
+ ConfigurationInteractor configurationInteractor,
Set<TouchHandler> handlers,
IWindowManager windowManagerService,
@DisplayId int displayId) {
@@ -511,6 +528,7 @@
mLifecycle = lifecycle;
mDisplayHelper = displayHelper;
mWindowManagerService = windowManagerService;
+ mConfigurationInteractor = configurationInteractor;
}
/**
@@ -518,6 +536,9 @@
*/
public void init() {
mLifecycle.addObserver(mLifecycleObserver);
+ if (Flags.ambientTouchMonitorListenToDisplayChanges()) {
+ collectFlow(mLifecycle, mConfigurationInteractor.getMaxBounds(), mMaxBoundsConsumer);
+ }
}
private void isolate(Set<TouchSessionImpl> sessions) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index ea5c5da..5ba0b2d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -29,6 +29,8 @@
import android.annotation.Nullable;
import android.app.AlertDialog;
import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
import android.graphics.PixelFormat;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
@@ -230,9 +232,13 @@
@Override
public void onUseDeviceCredential() {
mConfig.mCallback.onDeviceCredentialPressed(getRequestId());
- mHandler.postDelayed(() -> {
+ if (constraintBp()) {
addCredentialView(false /* animatePanel */, true /* animateContents */);
- }, mConfig.mSkipAnimation ? 0 : ANIMATE_CREDENTIAL_START_DELAY_MS);
+ } else {
+ mHandler.postDelayed(() -> {
+ addCredentialView(false /* animatePanel */, true /* animateContents */);
+ }, mConfig.mSkipAnimation ? 0 : ANIMATE_CREDENTIAL_START_DELAY_MS);
+ }
// TODO(b/313469218): Remove Config
mConfig.mPromptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL);
@@ -382,6 +388,12 @@
});
mPanelView = mLayout.findViewById(R.id.panel);
+ if (!constraintBp()) {
+ final TypedArray ta = mContext.obtainStyledAttributes(new int[]{
+ android.R.attr.colorBackgroundFloating});
+ mPanelView.setBackgroundColor(ta.getColor(0, Color.WHITE));
+ ta.recycle();
+ }
mPanelController = new AuthPanelController(mContext, mPanelView);
mBackgroundExecutor = bgExecutor;
mInteractionJankMonitor = jankMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 4a60d19..01cc33c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -169,7 +169,8 @@
layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or
WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
- privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
+ privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY or
+ WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION
// Avoid announcing window title.
accessibilityTitle = " "
inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 072fe47..da56951 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -87,7 +87,9 @@
*
* TODO(b/288175072): May be able to remove this once constraint layout is implemented
*/
- view.visibility = View.INVISIBLE
+ if (!constraintBp()) {
+ view.visibility = View.INVISIBLE
+ }
val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!
val textColorError =
@@ -102,12 +104,14 @@
val descriptionView = view.requireViewById<TextView>(R.id.description)
val customizedViewContainer =
view.requireViewById<LinearLayout>(R.id.customized_view_container)
+ val udfpsGuidanceView =
+ if (constraintBp()) {
+ view.requireViewById<View>(R.id.panel)
+ } else {
+ backgroundView
+ }
// set selected to enable marquee unless a screen reader is enabled
- logoView.isSelected =
- !accessibilityManager.isEnabled || !accessibilityManager.isTouchExplorationEnabled
- logoDescriptionView.isSelected =
- !accessibilityManager.isEnabled || !accessibilityManager.isTouchExplorationEnabled
titleView.isSelected =
!accessibilityManager.isEnabled || !accessibilityManager.isTouchExplorationEnabled
subtitleView.isSelected =
@@ -226,8 +230,8 @@
}
lifecycleScope.launch {
- viewModel.showBpWithoutIconForCredential.collect {
- if (!it) {
+ viewModel.showBpWithoutIconForCredential.collect { showWithoutIcon ->
+ if (!showWithoutIcon) {
PromptIconViewBinder.bind(
iconView,
iconOverlayView,
@@ -411,24 +415,11 @@
indicatorMessageView.isSelected =
!accessibilityManager.isEnabled ||
!accessibilityManager.isTouchExplorationEnabled
-
- /**
- * Note: Talkback 14.0 has new rate-limitation design to reduce frequency of
- * TYPE_WINDOW_CONTENT_CHANGED events to once every 30 seconds. (context:
- * b/281765653#comment18) Using {@link View#announceForAccessibility}
- * instead as workaround since sending events exceeding this frequency is
- * required.
- */
- indicatorMessageView?.text?.let {
- if (it.isNotBlank()) {
- view.announceForAccessibility(it)
- }
- }
}
}
// Talkback directional guidance
- backgroundView.setOnHoverListener { _, event ->
+ udfpsGuidanceView.setOnHoverListener { _, event ->
launch {
viewModel.onAnnounceAccessibilityHint(
event,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index f380746..d1ad783 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -20,6 +20,7 @@
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.graphics.Outline
+import android.graphics.Rect
import android.transition.AutoTransition
import android.transition.TransitionManager
import android.util.TypedValue
@@ -36,7 +37,6 @@
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.Guideline
import androidx.core.animation.addListener
-import androidx.core.view.doOnAttach
import androidx.core.view.doOnLayout
import androidx.core.view.isGone
import androidx.lifecycle.lifecycleScope
@@ -106,6 +106,52 @@
)
.toInt()
+ var currentSize: PromptSize? = null
+ var currentPosition: PromptPosition = PromptPosition.Bottom
+ panelView.outlineProvider =
+ object : ViewOutlineProvider() {
+ override fun getOutline(view: View, outline: Outline) {
+ when (currentPosition) {
+ PromptPosition.Right -> {
+ outline.setRoundRect(
+ 0,
+ 0,
+ view.width + cornerRadiusPx,
+ view.height,
+ cornerRadiusPx.toFloat()
+ )
+ }
+ PromptPosition.Left -> {
+ outline.setRoundRect(
+ -cornerRadiusPx,
+ 0,
+ view.width,
+ view.height,
+ cornerRadiusPx.toFloat()
+ )
+ }
+ PromptPosition.Top -> {
+ outline.setRoundRect(
+ 0,
+ -cornerRadiusPx,
+ view.width,
+ view.height,
+ cornerRadiusPx.toFloat()
+ )
+ }
+ PromptPosition.Bottom -> {
+ outline.setRoundRect(
+ 0,
+ 0,
+ view.width,
+ view.height + cornerRadiusPx,
+ cornerRadiusPx.toFloat()
+ )
+ }
+ }
+ }
+ }
+
// ConstraintSets for animating between prompt sizes
val mediumConstraintSet = ConstraintSet()
mediumConstraintSet.clone(view as ConstraintLayout)
@@ -115,7 +161,9 @@
val largeConstraintSet = ConstraintSet()
largeConstraintSet.clone(mediumConstraintSet)
- largeConstraintSet.constrainMaxWidth(R.id.panel, view.width)
+ largeConstraintSet.constrainMaxWidth(R.id.panel, 0)
+ largeConstraintSet.setGuidelineBegin(R.id.leftGuideline, 0)
+ largeConstraintSet.setGuidelineEnd(R.id.rightGuideline, 0)
// TODO: Investigate better way to handle 180 rotations
val flipConstraintSet = ConstraintSet()
@@ -138,65 +186,134 @@
}
}
- fun roundCorners(size: PromptSize, position: PromptPosition) {
- var left = 0
- var top = 0
- var right = 0
- var bottom = 0
- when (size) {
- PromptSize.SMALL,
- PromptSize.MEDIUM ->
- when (position) {
- PromptPosition.Right -> {
- left = 0
- top = 0
- right = view.width + cornerRadiusPx
- bottom = view.height
+ view.repeatWhenAttached {
+ lifecycleScope.launch {
+ viewModel.iconPosition.collect { position ->
+ if (position != Rect()) {
+ val iconParams =
+ iconHolderView.layoutParams as ConstraintLayout.LayoutParams
+
+ if (position.left != 0) {
+ iconParams.endToEnd = ConstraintSet.UNSET
+ iconParams.leftMargin = position.left
+ mediumConstraintSet.clear(
+ R.id.biometric_icon,
+ ConstraintSet.END
+ )
+ mediumConstraintSet.connect(
+ R.id.biometric_icon,
+ ConstraintSet.START,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.START
+ )
+ mediumConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.START,
+ position.left
+ )
+ smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.END)
+ smallConstraintSet.connect(
+ R.id.biometric_icon,
+ ConstraintSet.START,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.START
+ )
+ smallConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.START,
+ position.left
+ )
}
- PromptPosition.Left -> {
- left = -cornerRadiusPx
- top = 0
- right = view.width
- bottom = view.height
+ if (position.top != 0) {
+ iconParams.bottomToBottom = ConstraintSet.UNSET
+ iconParams.topMargin = position.top
+ mediumConstraintSet.clear(
+ R.id.biometric_icon,
+ ConstraintSet.BOTTOM
+ )
+ mediumConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.TOP,
+ position.top
+ )
+ smallConstraintSet.clear(
+ R.id.biometric_icon,
+ ConstraintSet.BOTTOM
+ )
+ smallConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.TOP,
+ position.top
+ )
}
- PromptPosition.Top -> {
- left = 0
- top = -cornerRadiusPx
- right = panelView.width
- bottom = view.height
+ if (position.right != 0) {
+ iconParams.startToStart = ConstraintSet.UNSET
+ iconParams.rightMargin = position.right
+ mediumConstraintSet.clear(
+ R.id.biometric_icon,
+ ConstraintSet.START
+ )
+ mediumConstraintSet.connect(
+ R.id.biometric_icon,
+ ConstraintSet.END,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.END
+ )
+ mediumConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.END,
+ position.right
+ )
+ smallConstraintSet.clear(
+ R.id.biometric_icon,
+ ConstraintSet.START
+ )
+ smallConstraintSet.connect(
+ R.id.biometric_icon,
+ ConstraintSet.END,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.END
+ )
+ smallConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.END,
+ position.right
+ )
}
- PromptPosition.Bottom -> {
- left = 0
- top = 0
- right = panelView.width
- bottom = view.height + cornerRadiusPx
+ if (position.bottom != 0) {
+ iconParams.topToTop = ConstraintSet.UNSET
+ iconParams.bottomMargin = position.bottom
+ mediumConstraintSet.clear(
+ R.id.biometric_icon,
+ ConstraintSet.TOP
+ )
+ mediumConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.BOTTOM,
+ position.bottom
+ )
+ smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.TOP)
+ smallConstraintSet.setMargin(
+ R.id.biometric_icon,
+ ConstraintSet.BOTTOM,
+ position.bottom
+ )
}
+ iconHolderView.layoutParams = iconParams
}
- PromptSize.LARGE -> {
- left = 0
- top = 0
- right = view.width
- bottom = view.height
}
}
-
- // Round the panel outline
- panelView.outlineProvider =
- object : ViewOutlineProvider() {
- override fun getOutline(view: View, outline: Outline) {
- outline.setRoundRect(
- left,
- top,
- right,
- bottom,
- cornerRadiusPx.toFloat()
- )
- }
+ lifecycleScope.launch {
+ viewModel.iconSize.collect { iconSize ->
+ iconHolderView.layoutParams.width = iconSize.first
+ iconHolderView.layoutParams.height = iconSize.second
+ mediumConstraintSet.constrainWidth(R.id.biometric_icon, iconSize.first)
+ mediumConstraintSet.constrainHeight(
+ R.id.biometric_icon,
+ iconSize.second
+ )
}
- }
-
- view.repeatWhenAttached {
- var currentSize: PromptSize? = null
+ }
lifecycleScope.launch {
viewModel.guidelineBounds.collect { bounds ->
@@ -249,87 +366,77 @@
lifecycleScope.launch {
combine(viewModel.position, viewModel.size, ::Pair).collect {
(position, size) ->
- view.doOnAttach {
- setVisibilities(size)
+ setVisibilities(size)
- if (position.isLeft) {
- if (size.isSmall) {
- flipConstraintSet.clone(smallConstraintSet)
- } else {
- flipConstraintSet.clone(mediumConstraintSet)
- }
-
- // Move all content to other panel
- flipConstraintSet.connect(
- R.id.scrollView,
- ConstraintSet.START,
- R.id.midGuideline,
- ConstraintSet.START
- )
- flipConstraintSet.connect(
- R.id.scrollView,
- ConstraintSet.END,
- R.id.rightGuideline,
- ConstraintSet.END
- )
+ if (position.isLeft) {
+ if (size.isSmall) {
+ flipConstraintSet.clone(smallConstraintSet)
+ } else {
+ flipConstraintSet.clone(mediumConstraintSet)
}
- roundCorners(size, position)
-
- when {
- size.isSmall -> {
- if (position.isLeft) {
- flipConstraintSet.applyTo(view)
- } else {
- smallConstraintSet.applyTo(view)
- }
- }
- size.isMedium && currentSize.isSmall -> {
- val autoTransition = AutoTransition()
- autoTransition.setDuration(
- ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
- )
-
- TransitionManager.beginDelayedTransition(
- view,
- autoTransition
- )
-
- if (position.isLeft) {
- flipConstraintSet.applyTo(view)
- } else {
- mediumConstraintSet.applyTo(view)
- }
- }
- size.isMedium -> {
- if (position.isLeft) {
- flipConstraintSet.applyTo(view)
- } else {
- mediumConstraintSet.applyTo(view)
- }
- }
- size.isLarge -> {
- val autoTransition = AutoTransition()
- autoTransition.setDuration(
- ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
- )
-
- TransitionManager.beginDelayedTransition(
- view,
- autoTransition
- )
- largeConstraintSet.applyTo(view)
- }
- }
-
- currentSize = size
- view.visibility = View.VISIBLE
- viewModel.setIsIconViewLoaded(false)
- notifyAccessibilityChanged()
-
- view.invalidate()
- view.requestLayout()
+ // Move all content to other panel
+ flipConstraintSet.connect(
+ R.id.scrollView,
+ ConstraintSet.START,
+ R.id.midGuideline,
+ ConstraintSet.START
+ )
+ flipConstraintSet.connect(
+ R.id.scrollView,
+ ConstraintSet.END,
+ R.id.rightGuideline,
+ ConstraintSet.END
+ )
}
+
+ when {
+ size.isSmall -> {
+ if (position.isLeft) {
+ flipConstraintSet.applyTo(view)
+ } else {
+ smallConstraintSet.applyTo(view)
+ }
+ }
+ size.isMedium && currentSize.isSmall -> {
+ val autoTransition = AutoTransition()
+ autoTransition.setDuration(
+ ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
+ )
+
+ TransitionManager.beginDelayedTransition(view, autoTransition)
+
+ if (position.isLeft) {
+ flipConstraintSet.applyTo(view)
+ } else {
+ mediumConstraintSet.applyTo(view)
+ }
+ }
+ size.isMedium -> {
+ if (position.isLeft) {
+ flipConstraintSet.applyTo(view)
+ } else {
+ mediumConstraintSet.applyTo(view)
+ }
+ }
+ size.isLarge && currentSize.isMedium -> {
+ val autoTransition = AutoTransition()
+ autoTransition.setDuration(
+ ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
+ )
+
+ TransitionManager.beginDelayedTransition(view, autoTransition)
+ largeConstraintSet.applyTo(view)
+ }
+ }
+
+ currentSize = size
+ currentPosition = position
+ notifyAccessibilityChanged()
+
+ panelView.invalidateOutline()
+ view.invalidate()
+ view.requestLayout()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
index d9d3715..9e836c3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
@@ -17,12 +17,9 @@
package com.android.systemui.biometrics.ui.binder
-import android.graphics.Rect
import android.graphics.drawable.Animatable2
import android.graphics.drawable.AnimatedVectorDrawable
import android.graphics.drawable.Drawable
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.airbnb.lottie.LottieAnimationView
@@ -77,83 +74,60 @@
}
}
- launch {
- var lottieOnCompositionLoadedListener: LottieOnCompositionLoadedListener? = null
+ if (!constraintBp()) {
+ launch {
+ var lottieOnCompositionLoadedListener: LottieOnCompositionLoadedListener? =
+ null
- combine(viewModel.activeAuthType, viewModel.iconSize, ::Pair).collect {
- (activeAuthType, iconSize) ->
- // Every time after bp shows, [isIconViewLoaded] is set to false in
- // [BiometricViewSizeBinder]. Then when biometric prompt view is redrew
- // (when size or activeAuthType changes), we need to update
- // [isIconViewLoaded] here to keep it correct.
- when (activeAuthType) {
- AuthType.Fingerprint,
- AuthType.Coex -> {
- /**
- * View is only set visible in BiometricViewSizeBinder once
- * PromptSize is determined that accounts for iconView size, to
- * prevent prompt resizing being visible to the user.
- *
- * TODO(b/288175072): May be able to remove this once constraint
- * layout is implemented
- */
- if (lottieOnCompositionLoadedListener != null) {
- iconView.removeLottieOnCompositionLoadedListener(
+ combine(viewModel.activeAuthType, viewModel.iconSize, ::Pair).collect {
+ (activeAuthType, iconSize) ->
+ // Every time after bp shows, [isIconViewLoaded] is set to false in
+ // [BiometricViewSizeBinder]. Then when biometric prompt view is redrew
+ // (when size or activeAuthType changes), we need to update
+ // [isIconViewLoaded] here to keep it correct.
+ when (activeAuthType) {
+ AuthType.Fingerprint,
+ AuthType.Coex -> {
+ /**
+ * View is only set visible in BiometricViewSizeBinder once
+ * PromptSize is determined that accounts for iconView size, to
+ * prevent prompt resizing being visible to the user.
+ *
+ * TODO(b/288175072): May be able to remove this once constraint
+ * layout is implemented
+ */
+ if (lottieOnCompositionLoadedListener != null) {
+ iconView.removeLottieOnCompositionLoadedListener(
+ lottieOnCompositionLoadedListener!!
+ )
+ }
+ lottieOnCompositionLoadedListener =
+ LottieOnCompositionLoadedListener {
+ promptViewModel.setIsIconViewLoaded(true)
+ }
+ iconView.addLottieOnCompositionLoadedListener(
lottieOnCompositionLoadedListener!!
)
}
- lottieOnCompositionLoadedListener =
- LottieOnCompositionLoadedListener {
- promptViewModel.setIsIconViewLoaded(true)
- }
- iconView.addLottieOnCompositionLoadedListener(
- lottieOnCompositionLoadedListener!!
- )
+ AuthType.Face -> {
+ /**
+ * Set to true by default since face icon is a drawable, which
+ * doesn't have a LottieOnCompositionLoadedListener equivalent.
+ *
+ * TODO(b/318569643): To be updated once face assets are updated
+ * from drawables
+ */
+ promptViewModel.setIsIconViewLoaded(true)
+ }
}
- AuthType.Face -> {
- /**
- * Set to true by default since face icon is a drawable, which
- * doesn't have a LottieOnCompositionLoadedListener equivalent.
- *
- * TODO(b/318569643): To be updated once face assets are updated
- * from drawables
- */
- promptViewModel.setIsIconViewLoaded(true)
- }
- }
- if (iconViewLayoutParamSizeOverride == null) {
- iconView.layoutParams.width = iconSize.first
- iconView.layoutParams.height = iconSize.second
+ if (iconViewLayoutParamSizeOverride == null) {
+ iconView.layoutParams.width = iconSize.first
+ iconView.layoutParams.height = iconSize.second
- iconOverlayView.layoutParams.width = iconSize.first
- iconOverlayView.layoutParams.height = iconSize.second
- }
- }
- }
-
- launch {
- viewModel.iconPosition.collect { position ->
- if (constraintBp() && position != Rect()) {
- val iconParams = iconView.layoutParams as ConstraintLayout.LayoutParams
-
- if (position.left != 0) {
- iconParams.endToEnd = ConstraintSet.UNSET
- iconParams.leftMargin = position.left
+ iconOverlayView.layoutParams.width = iconSize.first
+ iconOverlayView.layoutParams.height = iconSize.second
}
- if (position.top != 0) {
- iconParams.bottomToBottom = ConstraintSet.UNSET
- iconParams.topMargin = position.top
- }
- if (position.right != 0) {
- iconParams.startToStart = ConstraintSet.UNSET
- iconParams.rightMargin = position.right
- }
- if (position.bottom != 0) {
- iconParams.topToTop = ConstraintSet.UNSET
- iconParams.bottomMargin = position.bottom
- }
- iconView.layoutParams = iconParams
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
index 8dbed5f..bde3e99 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
@@ -66,10 +66,9 @@
*/
val activeAuthType: Flow<AuthType> =
combine(
- promptViewModel.size,
promptViewModel.modalities.distinctUntilChanged(),
promptViewModel.faceMode.distinctUntilChanged()
- ) { _, modalities, faceMode ->
+ ) { modalities, faceMode ->
if (modalities.hasFaceAndFingerprint && !faceMode) {
AuthType.Coex
} else if (modalities.hasFaceOnly || faceMode) {
@@ -103,68 +102,6 @@
}
.distinctUntilChanged()
- val iconPosition: Flow<Rect> =
- combine(
- udfpsSensorBounds,
- promptViewModel.size,
- promptViewModel.position,
- promptViewModel.modalities
- ) { sensorBounds, size, position, modalities ->
- when (position) {
- PromptPosition.Bottom ->
- if (size.isSmall) {
- Rect(0, 0, 0, promptViewModel.portraitSmallBottomPadding)
- } else if (size.isMedium && modalities.hasUdfps) {
- Rect(0, 0, 0, sensorBounds.bottom)
- } else if (size.isMedium) {
- Rect(0, 0, 0, promptViewModel.portraitMediumBottomPadding)
- } else {
- // Large screen
- Rect(0, 0, 0, promptViewModel.portraitLargeScreenBottomPadding)
- }
- PromptPosition.Right ->
- if (size.isSmall || modalities.hasFaceOnly) {
- Rect(
- 0,
- 0,
- promptViewModel.landscapeSmallHorizontalPadding,
- promptViewModel.landscapeSmallBottomPadding
- )
- } else if (size.isMedium && modalities.hasUdfps) {
- Rect(0, 0, sensorBounds.right, sensorBounds.bottom)
- } else {
- // SFPS
- Rect(
- 0,
- 0,
- promptViewModel.landscapeMediumHorizontalPadding,
- promptViewModel.landscapeMediumBottomPadding
- )
- }
- PromptPosition.Left ->
- if (size.isSmall || modalities.hasFaceOnly) {
- Rect(
- promptViewModel.landscapeSmallHorizontalPadding,
- 0,
- 0,
- promptViewModel.landscapeSmallBottomPadding
- )
- } else if (size.isMedium && modalities.hasUdfps) {
- Rect(sensorBounds.left, 0, 0, sensorBounds.bottom)
- } else {
- // SFPS
- Rect(
- promptViewModel.landscapeMediumHorizontalPadding,
- 0,
- 0,
- promptViewModel.landscapeMediumBottomPadding
- )
- }
- PromptPosition.Top -> Rect()
- }
- }
- .distinctUntilChanged()
-
/** Whether an error message is currently being shown. */
val showingError = promptViewModel.showingError
@@ -215,8 +152,8 @@
combine(
promptViewModel.position,
activeAuthType,
- promptViewModel.fingerprintSensorWidth,
- promptViewModel.fingerprintSensorHeight,
+ promptViewModel.legacyFingerprintSensorWidth,
+ promptViewModel.legacyFingerprintSensorHeight,
) { _, activeAuthType, fingerprintSensorWidth, fingerprintSensorHeight ->
if (activeAuthType == AuthType.Face) {
Pair(promptViewModel.faceIconWidth, promptViewModel.faceIconHeight)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 4e9acbd..2104f3e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -27,6 +27,7 @@
import android.hardware.biometrics.Flags.customBiometricPrompt
import android.hardware.biometrics.PromptContentView
import android.util.Log
+import android.util.RotationUtils
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import com.android.systemui.Flags.bpTalkback
@@ -120,7 +121,28 @@
R.dimen.biometric_prompt_landscape_medium_horizontal_padding
)
- val fingerprintSensorWidth: Flow<Int> =
+ private val udfpsSensorBounds: Flow<Rect> =
+ combine(
+ udfpsOverlayInteractor.udfpsOverlayParams,
+ displayStateInteractor.currentRotation
+ ) { params, rotation ->
+ val rotatedBounds = Rect(params.sensorBounds)
+ RotationUtils.rotateBounds(
+ rotatedBounds,
+ params.naturalDisplayWidth,
+ params.naturalDisplayHeight,
+ rotation.ordinal
+ )
+ Rect(
+ rotatedBounds.left,
+ rotatedBounds.top,
+ params.logicalDisplayWidth - rotatedBounds.right,
+ params.logicalDisplayHeight - rotatedBounds.bottom
+ )
+ }
+ .distinctUntilChanged()
+
+ val legacyFingerprintSensorWidth: Flow<Int> =
combine(modalities, udfpsOverlayInteractor.udfpsOverlayParams) { modalities, overlayParams
->
if (modalities.hasUdfps) {
@@ -130,7 +152,7 @@
}
}
- val fingerprintSensorHeight: Flow<Int> =
+ val legacyFingerprintSensorHeight: Flow<Int> =
combine(modalities, udfpsOverlayInteractor.udfpsOverlayParams) { modalities, overlayParams
->
if (modalities.hasUdfps) {
@@ -140,6 +162,12 @@
}
}
+ val fingerprintSensorWidth: Int =
+ udfpsOverlayInteractor.udfpsOverlayParams.value.sensorBounds.width()
+
+ val fingerprintSensorHeight: Int =
+ udfpsOverlayInteractor.udfpsOverlayParams.value.sensorBounds.height()
+
private val _accessibilityHint = MutableSharedFlow<String>()
/** Hint for talkback directional guidance */
@@ -276,40 +304,54 @@
R.dimen.biometric_prompt_medium_mid_guideline_padding
)
- /**
- * Rect for positioning prompt guidelines (left, top, right, mid)
- *
- * Negative values are used to signify that guideline measuring should be flipped, measuring
- * from opposite side of the screen
- */
- val guidelineBounds: Flow<Rect> =
- combine(size, position, modalities) { size, position, modalities ->
- if (position.isBottom) {
- Rect(0, 0, 0, 0)
- } else if (position.isRight) {
- if (size.isSmall) {
- Rect(-smallHorizontalGuidelinePadding, 0, 0, 0)
- } else if (modalities.hasUdfps) {
- Rect(udfpsHorizontalGuidelinePadding, 0, 0, udfpsMidGuidelinePadding)
- } else if (modalities.isEmpty) {
- // TODO: Temporary fix until no biometric landscape layout is added
- Rect(-mediumHorizontalGuidelinePadding, 0, 0, 6)
- } else {
- Rect(-mediumHorizontalGuidelinePadding, 0, 0, mediumMidGuidelinePadding)
- }
- } else if (position.isLeft) {
- if (size.isSmall) {
- Rect(0, 0, -smallHorizontalGuidelinePadding, 0)
- } else if (modalities.hasUdfps) {
- Rect(0, 0, udfpsHorizontalGuidelinePadding, -udfpsMidGuidelinePadding)
- } else if (modalities.isEmpty) {
- // TODO: Temporary fix until no biometric landscape layout is added
- Rect(0, 0, -mediumHorizontalGuidelinePadding, -6)
- } else {
- Rect(0, 0, -mediumHorizontalGuidelinePadding, -mediumMidGuidelinePadding)
- }
- } else {
- Rect()
+ /** Rect for positioning biometric icon */
+ val iconPosition: Flow<Rect> =
+ combine(udfpsSensorBounds, size, position, modalities) {
+ sensorBounds,
+ size,
+ position,
+ modalities ->
+ when (position) {
+ PromptPosition.Bottom ->
+ if (size.isSmall) {
+ Rect(0, 0, 0, portraitSmallBottomPadding)
+ } else if (size.isMedium && modalities.hasUdfps) {
+ Rect(0, 0, 0, sensorBounds.bottom)
+ } else if (size.isMedium) {
+ Rect(0, 0, 0, portraitMediumBottomPadding)
+ } else {
+ // Large screen
+ Rect(0, 0, 0, portraitLargeScreenBottomPadding)
+ }
+ PromptPosition.Right ->
+ if (size.isSmall || modalities.hasFaceOnly) {
+ Rect(0, 0, landscapeSmallHorizontalPadding, landscapeSmallBottomPadding)
+ } else if (size.isMedium && modalities.hasUdfps) {
+ Rect(0, 0, sensorBounds.right, sensorBounds.bottom)
+ } else {
+ // SFPS
+ Rect(
+ 0,
+ 0,
+ landscapeMediumHorizontalPadding,
+ landscapeMediumBottomPadding
+ )
+ }
+ PromptPosition.Left ->
+ if (size.isSmall || modalities.hasFaceOnly) {
+ Rect(landscapeSmallHorizontalPadding, 0, 0, landscapeSmallBottomPadding)
+ } else if (size.isMedium && modalities.hasUdfps) {
+ Rect(sensorBounds.left, 0, 0, sensorBounds.bottom)
+ } else {
+ // SFPS
+ Rect(
+ landscapeMediumHorizontalPadding,
+ 0,
+ 0,
+ landscapeMediumBottomPadding
+ )
+ }
+ PromptPosition.Top -> Rect()
}
}
.distinctUntilChanged()
@@ -373,6 +415,62 @@
_isIconViewLoaded.value = iconViewLoaded
}
+ /** The size of the biometric icon */
+ val iconSize: Flow<Pair<Int, Int>> =
+ combine(iconViewModel.activeAuthType, modalities) { activeAuthType, modalities ->
+ if (activeAuthType == PromptIconViewModel.AuthType.Face) {
+ Pair(faceIconWidth, faceIconHeight)
+ } else {
+ if (modalities.hasUdfps) {
+ Pair(fingerprintSensorWidth, fingerprintSensorHeight)
+ } else {
+ Pair(fingerprintIconWidth, fingerprintIconHeight)
+ }
+ }
+ }
+
+ /**
+ * Rect for positioning prompt guidelines (left, top, right, mid)
+ *
+ * Negative values are used to signify that guideline measuring should be flipped, measuring
+ * from opposite side of the screen
+ */
+ val guidelineBounds: Flow<Rect> =
+ combine(iconPosition, size, position, modalities) { _, size, position, modalities ->
+ when (position) {
+ PromptPosition.Bottom -> Rect(0, 0, 0, 0)
+ PromptPosition.Right ->
+ if (size.isSmall) {
+ Rect(-smallHorizontalGuidelinePadding, 0, 0, 0)
+ } else if (modalities.hasUdfps) {
+ Rect(udfpsHorizontalGuidelinePadding, 0, 0, udfpsMidGuidelinePadding)
+ } else if (modalities.isEmpty) {
+ // TODO: Temporary fix until no biometric landscape layout is added
+ Rect(-mediumHorizontalGuidelinePadding, 0, 0, 6)
+ } else {
+ Rect(-mediumHorizontalGuidelinePadding, 0, 0, mediumMidGuidelinePadding)
+ }
+ PromptPosition.Left ->
+ if (size.isSmall) {
+ Rect(0, 0, -smallHorizontalGuidelinePadding, 0)
+ } else if (modalities.hasUdfps) {
+ Rect(0, 0, udfpsHorizontalGuidelinePadding, -udfpsMidGuidelinePadding)
+ } else if (modalities.isEmpty) {
+ // TODO: Temporary fix until no biometric landscape layout is added
+ Rect(0, 0, -mediumHorizontalGuidelinePadding, -6)
+ } else {
+ Rect(
+ 0,
+ 0,
+ -mediumHorizontalGuidelinePadding,
+ -mediumMidGuidelinePadding
+ )
+ }
+ PromptPosition.Top -> Rect()
+ }
+ }
+ .distinctUntilChanged()
+
/** Padding for prompt UI elements */
val promptPadding: Flow<Rect> =
combine(size, displayStateInteractor.currentRotation) { size, rotation ->
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
index 638af58..e0e1971 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
@@ -48,6 +48,12 @@
}
}
+ /** Returns the unadjusted screen size. */
+ val maxBounds: Flow<Rect> =
+ repository.configurationValues
+ .map { Rect(it.windowConfiguration.maxBounds) }
+ .distinctUntilChanged()
+
/**
* Returns screen size adjusted to rotation, so returned screen sizes are stable across all
* rotations, could be useful if you need to react to screen resize (e.g. fold/unfold on
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index 4ac43bc..db251fd 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -18,6 +18,7 @@
import android.content.ComponentName
import android.os.UserHandle
+import android.view.View
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
@@ -37,8 +38,8 @@
) {
val currentScene: Flow<SceneKey> = communalInteractor.desiredScene
- /** Whether communal hub can be focused to enable accessibility actions. */
- val isFocusable: Flow<Boolean> = communalInteractor.isIdleOnCommunal
+ /** Whether communal hub should be focused by accessibility tools. */
+ open val isFocusable: Flow<Boolean> = MutableStateFlow(false)
/** Whether widgets are currently being re-ordered. */
open val reorderingWidgets: StateFlow<Boolean> = MutableStateFlow(false)
@@ -49,6 +50,9 @@
val selectedKey: StateFlow<String?>
get() = _selectedKey
+ /** Accessibility delegate to be set on CommunalAppWidgetHostView. */
+ open val widgetAccessibilityDelegate: View.AccessibilityDelegate? = null
+
fun signalUserInteraction() {
communalInteractor.signalUserInteraction()
}
@@ -88,14 +92,14 @@
/** Whether in edit mode for the communal hub. */
open val isEditMode = false
- /** Whether the popup message triggered by dismissing the CTA tile is showing. */
- open val isPopupOnDismissCtaShowing: Flow<Boolean> = flowOf(false)
+ /** Whether the type of popup currently showing */
+ open val currentPopup: Flow<PopupType?> = flowOf(null)
/** Whether the communal hub is empty with no widget available. */
open val isEmptyState: Flow<Boolean> = flowOf(false)
- /** Hide the popup message triggered by dismissing the CTA tile. */
- open fun onHidePopupAfterDismissCta() {}
+ /** Called as the UI request to dismiss the any displaying popup */
+ open fun onHidePopup() {}
/** Called as the UI requests deleting a widget. */
open fun onDeleteWidget(id: Int) {}
@@ -127,6 +131,9 @@
/** Called as the user cancels dragging a widget to reorder. */
open fun onReorderWidgetCancel() {}
+ /** Called as the user request to show the customize widget button. */
+ open fun onShowCustomizeWidgetButton() {}
+
/** Set the key of the currently selected item */
fun setSelectedKey(key: String?) {
_selectedKey.value = key
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 f13b5759..1120466 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
@@ -16,12 +16,18 @@
package com.android.systemui.communal.ui.viewmodel
+import android.content.res.Resources
+import android.view.View
+import android.view.accessibility.AccessibilityNodeInfo
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+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.KeyguardState
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.CommunalLog
@@ -29,7 +35,9 @@
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.media.dagger.MediaModule
+import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineScope
@@ -54,6 +62,8 @@
@Inject
constructor(
@Application private val scope: CoroutineScope,
+ @Main private val resources: Resources,
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val communalInteractor: CommunalInteractor,
tutorialInteractor: CommunalTutorialInteractor,
private val shadeInteractor: ShadeInteractor,
@@ -90,9 +100,39 @@
.distinctUntilChanged()
.onEach { logger.d("isEmptyState: $it") }
- private val _isPopupOnDismissCtaShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
- override val isPopupOnDismissCtaShowing: Flow<Boolean> =
- _isPopupOnDismissCtaShowing.asStateFlow()
+ private val _currentPopup: MutableStateFlow<PopupType?> = MutableStateFlow(null)
+ override val currentPopup: Flow<PopupType?> = _currentPopup.asStateFlow()
+
+ // The widget is focusable for accessibility when the hub is fully visible and shade is not
+ // opened.
+ override val isFocusable: Flow<Boolean> =
+ combine(
+ keyguardTransitionInteractor.isFinishedInState(KeyguardState.GLANCEABLE_HUB),
+ communalInteractor.isIdleOnCommunal,
+ shadeInteractor.isAnyFullyExpanded,
+ ) { transitionedToGlanceableHub, isIdleOnCommunal, isAnyFullyExpanded ->
+ transitionedToGlanceableHub && isIdleOnCommunal && !isAnyFullyExpanded
+ }
+ .distinctUntilChanged()
+
+ override val widgetAccessibilityDelegate =
+ object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ // Hint user to long press in order to enter edit mode
+ info.addAction(
+ AccessibilityNodeInfo.AccessibilityAction(
+ AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.id,
+ resources
+ .getString(R.string.accessibility_action_label_edit_widgets)
+ .lowercase()
+ )
+ )
+ }
+ }
private val _isEnableWidgetDialogShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
val isEnableWidgetDialogShowing: Flow<Boolean> = _isEnableWidgetDialogShowing.asStateFlow()
@@ -124,14 +164,16 @@
override fun onDismissCtaTile() {
scope.launch {
communalInteractor.dismissCtaTile()
- setPopupOnDismissCtaVisibility(true)
- schedulePopupHiding()
+ setCurrentPopupType(PopupType.CtaTile)
}
}
- override fun onHidePopupAfterDismissCta() {
- cancelDelayedPopupHiding()
- setPopupOnDismissCtaVisibility(false)
+ override fun onShowCustomizeWidgetButton() {
+ setCurrentPopupType(PopupType.CustomizeWidgetButton)
+ }
+
+ override fun onHidePopup() {
+ setCurrentPopupType(null)
}
override fun onOpenEnableWidgetDialog() {
@@ -168,32 +210,42 @@
_isEnableWorkProfileDialogShowing.value = isVisible
}
- private fun setPopupOnDismissCtaVisibility(isVisible: Boolean) {
- _isPopupOnDismissCtaShowing.value = isVisible
+ private fun setCurrentPopupType(popupType: PopupType?) {
+ _currentPopup.value = popupType
+ delayedHideCurrentPopupJob?.cancel()
+
+ if (popupType != null) {
+ delayedHideCurrentPopupJob =
+ scope.launch {
+ delay(POPUP_AUTO_HIDE_TIMEOUT_MS)
+ setCurrentPopupType(null)
+ }
+ } else {
+ delayedHideCurrentPopupJob = null
+ }
}
- private var delayedHidePopupJob: Job? = null
-
- private fun schedulePopupHiding() {
- cancelDelayedPopupHiding()
- delayedHidePopupJob =
- scope.launch {
- delay(POPUP_AUTO_HIDE_TIMEOUT_MS)
- onHidePopupAfterDismissCta()
- }
- }
-
- private fun cancelDelayedPopupHiding() {
- delayedHidePopupJob?.cancel()
- delayedHidePopupJob = null
- }
+ private var delayedHideCurrentPopupJob: Job? = null
/** Whether we can transition to a new scene based on a user gesture. */
fun canChangeScene(): Boolean {
return !shadeInteractor.isAnyFullyExpanded.value
}
+ /**
+ * Whether touches should be disabled in communal.
+ *
+ * This is needed because the notification shade does not block touches in blank areas and these
+ * fall through to the glanceable hub, which we don't want.
+ */
+ val touchesAllowed: Flow<Boolean> = not(shadeInteractor.isAnyFullyExpanded)
+
companion object {
const val POPUP_AUTO_HIDE_TIMEOUT_MS = 12000L
}
}
+
+sealed class PopupType {
+ object CtaTile : PopupType()
+ object CustomizeWidgetButton : PopupType()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
index 2af49aa..db7ffc1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
@@ -20,8 +20,6 @@
import android.content.pm.PackageManager
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsMetricsLoggerImpl
-import com.android.systemui.controls.settings.ControlsSettingsRepository
-import com.android.systemui.controls.settings.ControlsSettingsRepositoryImpl
import com.android.systemui.controls.controller.ControlsBindingController
import com.android.systemui.controls.controller.ControlsBindingControllerImpl
import com.android.systemui.controls.controller.ControlsController
@@ -40,14 +38,20 @@
import com.android.systemui.controls.panels.SelectedComponentRepositoryImpl
import com.android.systemui.controls.settings.ControlsSettingsDialogManager
import com.android.systemui.controls.settings.ControlsSettingsDialogManagerImpl
+import com.android.systemui.controls.settings.ControlsSettingsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepositoryImpl
import com.android.systemui.controls.ui.ControlActionCoordinator
import com.android.systemui.controls.ui.ControlActionCoordinatorImpl
import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.controls.ui.ControlsUiControllerImpl
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.qs.tiles.DeviceControlsTile
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
import dagger.Binds
import dagger.BindsOptionalOf
import dagger.Module
@@ -75,6 +79,22 @@
fun providesControlsFeatureEnabled(pm: PackageManager): Boolean {
return pm.hasSystemFeature(PackageManager.FEATURE_CONTROLS)
}
+
+ const val DEVICE_CONTROLS_SPEC = "controls"
+
+ @Provides
+ @IntoMap
+ @StringKey(DEVICE_CONTROLS_SPEC)
+ fun provideDeviceControlsTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(DEVICE_CONTROLS_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = com.android.systemui.res.R.drawable.controls_icon,
+ labelRes = com.android.systemui.res.R.string.quick_controls_title
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
}
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
index 2fa42ec..7ced932 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
@@ -24,7 +24,6 @@
import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import com.android.systemui.screenshot.SmartActionsReceiver;
-import com.android.systemui.volume.VolumePanelDialogReceiver;
import dagger.Binds;
import dagger.Module;
@@ -59,15 +58,6 @@
*/
@Binds
@IntoMap
- @ClassKey(VolumePanelDialogReceiver.class)
- public abstract BroadcastReceiver bindVolumePanelDialogReceiver(
- VolumePanelDialogReceiver broadcastReceiver);
-
- /**
- *
- */
- @Binds
- @IntoMap
@ClassKey(PeopleSpaceWidgetPinnedReceiver.class)
public abstract BroadcastReceiver bindPeopleSpaceWidgetPinnedReceiver(
PeopleSpaceWidgetPinnedReceiver broadcastReceiver);
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
index f1ab4d1..ba45a51 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -518,9 +518,12 @@
private fun onFaceAuthRequestCompleted() {
cancelNotReceivedHandlerJob?.cancel()
- cancellationInProgress.value = false
_isAuthRunning.value = false
authCancellationSignal = null
+ // Updates to "cancellationInProgress" may re-trigger face auth
+ // (see processPendingAuthRequests()), so we must update this after setting _isAuthRunning
+ // to false.
+ cancellationInProgress.value = false
}
private val detectionCallback =
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
index 98deda09..ffe392a 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
@@ -16,6 +16,7 @@
package com.android.systemui.deviceentry.domain.interactor
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START
import android.hardware.face.FaceManager
import com.android.systemui.biometrics.FaceHelpMessageDeferralFactory
import com.android.systemui.dagger.SysUISingleton
@@ -86,7 +87,7 @@
}
}
.collect {
- if (it.acquiredInfo == FaceManager.FACE_ACQUIRED_START) {
+ if (it.acquiredInfo == FACE_ACQUIRED_START) {
faceHelpMessageDeferral.reset()
}
faceHelpMessageDeferral.processFrame(it.acquiredInfo)
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
index 5f1667a..3365340 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
@@ -16,6 +16,12 @@
package com.android.systemui.deviceentry.shared.model
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS
import android.hardware.face.FaceManager
import android.os.SystemClock.elapsedRealtime
@@ -62,24 +68,22 @@
* Method that checks if [msgId] is a lockout error. A lockout error means that face
* authentication is locked out.
*/
- fun isLockoutError() =
- msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT || msgId == FaceManager.FACE_ERROR_LOCKOUT
+ fun isLockoutError() = msgId == FACE_ERROR_LOCKOUT_PERMANENT || msgId == FACE_ERROR_LOCKOUT
/**
* Method that checks if [msgId] is a cancellation error. This means that face authentication
* was cancelled before it completed.
*/
- fun isCancellationError() = msgId == FaceManager.FACE_ERROR_CANCELED
+ fun isCancellationError() = msgId == FACE_ERROR_CANCELED
- fun isUnableToProcessError() = msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS
+ fun isUnableToProcessError() = msgId == FACE_ERROR_UNABLE_TO_PROCESS
/** Method that checks if [msgId] is a hardware error. */
fun isHardwareError() =
- msgId == FaceManager.FACE_ERROR_HW_UNAVAILABLE ||
- msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS
+ msgId == FACE_ERROR_HW_UNAVAILABLE || msgId == FACE_ERROR_UNABLE_TO_PROCESS
/** Method that checks if [msgId] is a timeout error. */
- fun isTimeoutError() = msgId == FaceManager.FACE_ERROR_TIMEOUT
+ fun isTimeoutError() = msgId == FACE_ERROR_TIMEOUT
companion object {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index c618e92..aa7a7da 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -16,6 +16,8 @@
package com.android.systemui.dreams;
+import static android.service.dreams.Flags.dreamWakeRedirect;
+
import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
import static com.android.systemui.dreams.dagger.DreamModule.DREAM_TOUCH_INSET_MANAGER;
import static com.android.systemui.dreams.dagger.DreamModule.HOME_CONTROL_PANEL_DREAM_COMPONENT;
@@ -149,6 +151,14 @@
private final CommunalInteractor mCommunalInteractor;
+ private boolean mCommunalAvailable;
+
+ final Consumer<Boolean> mIsCommunalAvailableCallback =
+ isAvailable -> {
+ mCommunalAvailable = isAvailable;
+ updateRedirectWakeup();
+ };
+
private final SystemDialogsCloser mSystemDialogsCloser;
private final KeyguardUpdateMonitorCallback mKeyguardCallback =
@@ -287,6 +297,8 @@
mExecutor.execute(() -> setLifecycleStateLocked(Lifecycle.State.CREATED));
+ collectFlow(getLifecycle(), mCommunalInteractor.isCommunalAvailable(),
+ mIsCommunalAvailableCallback);
collectFlow(getLifecycle(), communalInteractor.isCommunalVisible(),
mCommunalVisibleConsumer);
collectFlow(getLifecycle(), keyguardInteractor.primaryBouncerShowing,
@@ -374,6 +386,16 @@
mDreamOverlayCallbackController.onStartDream();
mStarted = true;
+
+ updateRedirectWakeup();
+ }
+
+ private void updateRedirectWakeup() {
+ if (!mStarted || !dreamWakeRedirect()) {
+ return;
+ }
+
+ redirectWake(mCommunalAvailable);
}
@Override
@@ -381,6 +403,11 @@
resetCurrentDreamOverlayLocked();
}
+ @Override
+ public void onWakeRequested() {
+ mCommunalInteractor.changeScene(CommunalScenes.Communal, null);
+ }
+
private Lifecycle.State getLifecycleStateLocked() {
return mLifecycleRegistry.getCurrentState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index 516b8c5..b0d134f 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -36,6 +36,11 @@
import com.android.systemui.dreams.homecontrols.DreamActivityProvider;
import com.android.systemui.dreams.homecontrols.DreamActivityProviderImpl;
import com.android.systemui.dreams.homecontrols.HomeControlsDreamService;
+import com.android.systemui.qs.QsEventLogger;
+import com.android.systemui.qs.pipeline.shared.TileSpec;
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig;
+import com.android.systemui.qs.tiles.viewmodel.QSTilePolicy;
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig;
import com.android.systemui.res.R;
import com.android.systemui.touch.TouchInsetManager;
@@ -44,6 +49,7 @@
import dagger.Provides;
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
+import dagger.multibindings.StringKey;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -70,6 +76,7 @@
String DREAM_SUPPORTED = "dream_supported";
String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
String HOME_CONTROL_PANEL_DREAM_COMPONENT = "home_control_panel_dream_component";
+ String DREAM_TILE_SPEC = "dream";
/**
* Provides the dream component
@@ -178,6 +185,23 @@
return resources.getString(R.string.app_label);
}
+ /** Provides config for the dream tile */
+ @Provides
+ @IntoMap
+ @StringKey(DREAM_TILE_SPEC)
+ static QSTileConfig provideDreamTileConfig(QsEventLogger uiEventLogger) {
+ TileSpec tileSpec = TileSpec.create(DREAM_TILE_SPEC);
+ return new QSTileConfig(tileSpec,
+ new QSTileUIConfig.Resource(
+ R.drawable.ic_qs_screen_saver,
+ R.string.quick_settings_screensaver_label),
+ uiEventLogger.getNewInstanceId(),
+ tileSpec.getSpec(),
+ QSTilePolicy.NoRestrictions.INSTANCE
+ );
+ }
+
+
/** Provides activity for dream service */
@Binds
DreamActivityProvider bindActivityProvider(DreamActivityProviderImpl impl);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 0bc29a8..95bc514 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -123,6 +123,7 @@
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.globalactions.domain.interactor.GlobalActionsInteractor;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
import com.android.systemui.scrim.ScrimDrawable;
@@ -186,6 +187,7 @@
private static final String GLOBAL_ACTION_KEY_LOGOUT = "logout";
static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency";
static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
+ static final String GLOBAL_ACTION_KEY_SYSTEM_UPDATE = "system_update";
// See NotificationManagerService#scheduleDurationReachedLocked
private static final long TOAST_FADE_TIME = 333;
@@ -213,6 +215,7 @@
private final TelecomManager mTelecomManager;
private final MetricsLogger mMetricsLogger;
private final UiEventLogger mUiEventLogger;
+ private final ActivityStarter mActivityStarter;
// Used for RingerModeTracker
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
@@ -317,7 +320,10 @@
GA_CLOSE_TAP_OUTSIDE(810),
@UiEvent(doc = "Power menu was closed via power + volume up.")
- GA_CLOSE_POWER_VOLUP(811);
+ GA_CLOSE_POWER_VOLUP(811),
+
+ @UiEvent(doc = "System Update button was pressed.")
+ GA_SYSTEM_UPDATE_PRESS(1716);
private final int mId;
@@ -349,6 +355,7 @@
@NonNull VibratorHelper vibrator,
@Main Resources resources,
ConfigurationController configurationController,
+ ActivityStarter activityStarter,
UserTracker userTracker,
KeyguardStateController keyguardStateController,
UserManager userManager,
@@ -385,6 +392,7 @@
mSecureSettings = secureSettings;
mResources = resources;
mConfigurationController = configurationController;
+ mActivityStarter = activityStarter;
mUserTracker = userTracker;
mUserManager = userManager;
mTrustManager = trustManager;
@@ -659,6 +667,8 @@
if (shouldDisplayEmergency()) {
addIfShouldShowAction(tempActions, new EmergencyDialerAction());
}
+ } else if (GLOBAL_ACTION_KEY_SYSTEM_UPDATE.equals(actionKey)) {
+ addIfShouldShowAction(tempActions, new SystemUpdateAction());
} else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
@@ -1145,6 +1155,40 @@
}
}
+ @VisibleForTesting
+ final class SystemUpdateAction extends SinglePressAction {
+
+ SystemUpdateAction() {
+ super(com.android.settingslib.R.drawable.ic_system_update,
+ com.android.settingslib.R.string.system_update_settings_list_item_title);
+ }
+
+ @Override
+ public void onPress() {
+ mUiEventLogger.log(GlobalActionsEvent.GA_SYSTEM_UPDATE_PRESS);
+ launchSystemUpdate();
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return false;
+ }
+
+ private void launchSystemUpdate() {
+ Intent intent = new Intent(Settings.ACTION_SYSTEM_UPDATE_SETTINGS);
+ intent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ // postStartActivityDismissingKeyguard is used for showing keyguard
+ // input/pin/password screen if lockscreen is secured, before sending the intent.
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
+ }
+ }
+
private Action getSettingsAction() {
return new SinglePressAction(R.drawable.ic_settings,
R.string.global_action_settings) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index ae163ea..674c128 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -89,14 +90,14 @@
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.transition.Transitions;
-import kotlinx.coroutines.CoroutineScope;
-
import java.util.ArrayList;
import java.util.Map;
import java.util.WeakHashMap;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineScope;
+
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
@@ -223,6 +224,20 @@
initAlphaForAnimationTargets(t, apps);
initAlphaForAnimationTargets(t, wallpapers);
+ // If the keyguard is going away, hide the dream if one exists.
+ if (dismissDreamOnKeyguardDismiss()
+ && (info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
+ for (RemoteAnimationTarget app : apps) {
+ final boolean isDream = app.taskInfo != null
+ && app.taskInfo.getActivityType()
+ == WindowConfiguration.ACTIVITY_TYPE_DREAM;
+ if (isDream && app.mode == RemoteAnimationTarget.MODE_CLOSING) {
+ t.hide(app.leash);
+ break;
+ }
+ }
+ }
+
t.apply();
runner.onAnimationStart(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 46aec25..5d31d1e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -21,6 +21,7 @@
import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
import static android.provider.Settings.System.LOCKSCREEN_SOUNDS_ENABLED;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
@@ -3092,13 +3093,22 @@
createInteractionJankMonitorConf(
CUJ_LOCKSCREEN_UNLOCK_ANIMATION, "DismissPanel"));
+ // Filter out any closing apps, such as the dream.
+ RemoteAnimationTarget[] openingApps = apps;
+ if (dismissDreamOnKeyguardDismiss()) {
+ openingApps = Arrays.stream(apps)
+ .filter(a -> a.mode == RemoteAnimationTarget.MODE_OPENING)
+ .toArray(RemoteAnimationTarget[]::new);
+ }
+
// Pass the surface and metadata to the unlock animation controller.
RemoteAnimationTarget[] openingWallpapers = Arrays.stream(wallpapers).filter(
w -> w.mode == RemoteAnimationTarget.MODE_OPENING).toArray(
RemoteAnimationTarget[]::new);
+
mKeyguardUnlockAnimationControllerLazy.get()
.notifyStartSurfaceBehindRemoteAnimation(
- apps, openingWallpapers, startTime,
+ openingApps, openingWallpapers, startTime,
mSurfaceBehindRemoteAnimationRequested);
} else {
mInteractionJankMonitor.begin(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index e441017..5a28f711 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -193,5 +193,6 @@
val TO_AOD_DURATION = TRANSITION_DURATION_MS
val TO_PRIMARY_BOUNCER_DURATION = TRANSITION_DURATION_MS
val TO_DOZING_DURATION = TRANSITION_DURATION_MS
+ val TO_OCCLUDED_DURATION = TRANSITION_DURATION_MS
}
}
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 1fba737..c2843d8 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
@@ -168,11 +168,13 @@
keyguardInteractor.isKeyguardOccluded
.filterRelevantKeyguardStateAnd { isOccluded -> isOccluded }
.collect {
- startTransitionTo(
- toState = KeyguardState.OCCLUDED,
- modeOnCanceled = TransitionModeOnCanceled.RESET,
- ownerReason = "isOccluded = true",
- )
+ if (!maybeHandleInsecurePowerGesture()) {
+ startTransitionTo(
+ toState = KeyguardState.OCCLUDED,
+ modeOnCanceled = TransitionModeOnCanceled.RESET,
+ ownerReason = "isOccluded = true",
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardOcclusionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardOcclusionInteractor.kt
index 4abd6c6..f385671 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardOcclusionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardOcclusionInteractor.kt
@@ -77,7 +77,9 @@
// transition, to ensure we don't transition while moving between, for example,
// *_BOUNCER -> LOCKSCREEN.
return powerInteractor.detailedWakefulness.value.powerButtonLaunchGestureTriggered &&
- KeyguardState.deviceIsAsleepInState(transitionInteractor.getStartedState())
+ KeyguardState.deviceIsAsleepInState(
+ transitionInteractor.currentTransitionInfoInternal.value.to
+ )
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
index 2850165..b2a24ca 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
@@ -225,10 +225,12 @@
if (!KeyguardWmStateRefactor.isEnabled) {
scope.launch {
keyguardInteractor.onCameraLaunchDetected.filterRelevantKeyguardState().collect {
- startTransitionTo(
- toState = KeyguardState.OCCLUDED,
- modeOnCanceled = TransitionModeOnCanceled.RESET,
- )
+ if (!maybeHandleInsecurePowerGesture()) {
+ startTransitionTo(
+ toState = KeyguardState.OCCLUDED,
+ modeOnCanceled = TransitionModeOnCanceled.RESET,
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
index f5cd767..63bfba6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
@@ -19,10 +19,10 @@
import android.animation.FloatEvaluator
import android.animation.IntEvaluator
-import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.StatusBarState
-import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.hideAffordancesRequest
import javax.inject.Inject
@@ -38,17 +38,16 @@
class UdfpsKeyguardInteractor
@Inject
constructor(
- configRepo: ConfigurationRepository,
burnInInteractor: BurnInInteractor,
keyguardInteractor: KeyguardInteractor,
- shadeRepository: ShadeRepository,
+ shadeInteractor: ShadeInteractor,
+ shadeLockscreenInteractor: ShadeLockscreenInteractor,
dialogManager: SystemUIDialogManager,
) {
private val intEvaluator = IntEvaluator()
private val floatEvaluator = FloatEvaluator()
val dozeAmount = keyguardInteractor.dozeAmount
- val scaleForResolution = configRepo.scaleForResolution
/** Burn-in offsets for the UDFPS view to mitigate burn-in on AOD. */
val burnInOffsets: Flow<Offsets> =
@@ -68,13 +67,14 @@
val dialogHideAffordancesRequest: Flow<Boolean> = dialogManager.hideAffordancesRequest
val qsProgress: Flow<Float> =
- shadeRepository.qsExpansion // swipe from top of LS
+ shadeInteractor.qsExpansion // swipe from top of LS
.map { (it * 2).coerceIn(0f, 1f) }
.onStart { emit(0f) }
val shadeExpansion: Flow<Float> =
combine(
- shadeRepository.udfpsTransitionToFullShadeProgress, // swipe from middle of LS
+ shadeLockscreenInteractor
+ .udfpsTransitionToFullShadeProgress, // swipe from middle of LS
keyguardInteractor.statusBarState, // quick swipe from middle of LS
) { shadeProgress, statusBarState ->
if (statusBarState == StatusBarState.SHADE_LOCKED) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
index 93b3ba5..b293027 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
@@ -20,8 +20,8 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
import com.android.systemui.log.core.LogLevel
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -40,7 +40,7 @@
) : CoreStartable {
override fun start() {
- if (!RefactorKeyguardDismissIntent.isEnabled) {
+ if (!SceneContainerFlag.isEnabled) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
index f77d012..ac24591 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
@@ -22,9 +22,9 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.keyguard.domain.interactor.KeyguardDismissInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
import com.android.systemui.keyguard.shared.model.KeyguardDone
import com.android.systemui.log.core.LogLevel
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -44,7 +44,7 @@
) : CoreStartable {
override fun start() {
- if (!RefactorKeyguardDismissIntent.isEnabled) {
+ if (!SceneContainerFlag.isEnabled) {
return
}
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 3b21141..a8e9041 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
@@ -18,6 +18,7 @@
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToDozingTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel
@@ -71,6 +72,12 @@
@Binds
@IntoSet
+ abstract fun alternateBouncerToOccluded(
+ impl: AlternateBouncerToOccludedTransitionViewModel
+ ): DeviceEntryIconTransition
+
+ @Binds
+ @IntoSet
abstract fun alternateBouncerToPrimaryBouncer(
impl: AlternateBouncerToPrimaryBouncerTransitionViewModel
): DeviceEntryIconTransition
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
index 0bc60c4..7c29b39 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
@@ -21,6 +21,7 @@
import android.animation.ValueAnimator
import android.graphics.Rect
import android.transition.Transition
+import android.transition.TransitionListenerAdapter
import android.transition.TransitionSet
import android.transition.TransitionValues
import android.util.Log
@@ -169,6 +170,18 @@
return@OnPreDrawListener true
}
+ this@VisibilityBoundsTransition.addListener(
+ object : TransitionListenerAdapter() {
+ override fun onTransitionStart(t: Transition) {
+ toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
+ }
+
+ override fun onTransitionEnd(t: Transition) {
+ toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
+ }
+ }
+ )
+
val listener =
object : AnimatorListenerAdapter() {
override fun onAnimationStart(anim: Animator) {
@@ -178,26 +191,11 @@
override fun onAnimationEnd(anim: Animator) {
assignAnimValues("end", 1f, toVis)
if (sendToBack) toView.translationZ = 0f
- toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
- }
-
- override fun onAnimationPause(anim: Animator) {
- toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
- }
-
- override fun onAnimationResume(anim: Animator) {
- toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
}
}
- anim.duration = duration
- anim.startDelay = startDelay
- anim.interpolator = interpolator
anim.addListener(listener)
- anim.addPauseListener(listener)
-
assignAnimValues("init", 0f, fromVis)
- toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt
new file mode 100644
index 0000000..27febd3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromAlternateBouncerTransitionInteractor.Companion.TO_OCCLUDED_DURATION
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Breaks down ALTERNATE_BOUNCER->GONE transition into discrete steps for corresponding views to
+ * consume.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class AlternateBouncerToOccludedTransitionViewModel
+@Inject
+constructor(
+ animationFlow: KeyguardTransitionAnimationFlow,
+) : DeviceEntryIconTransition {
+ private val transitionAnimation =
+ animationFlow.setup(
+ duration = TO_OCCLUDED_DURATION,
+ from = ALTERNATE_BOUNCER,
+ to = KeyguardState.OCCLUDED,
+ )
+
+ override val deviceEntryParentViewAlpha: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(0f)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
index 7e39a88..adc090d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
@@ -57,5 +57,15 @@
)
}
+ fun notificationAlpha(viewState: ViewStateAccessor): Flow<Float> {
+ var startAlpha = 1f
+ return transitionAnimation.sharedFlow(
+ duration = 200.milliseconds,
+ onStart = { startAlpha = viewState.alpha() },
+ onStep = { startAlpha },
+ onFinish = { 1f },
+ )
+ }
+
override val deviceEntryParentViewAlpha = transitionAnimation.immediatelyTransitionTo(0f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
index 24429fa..e0a3af6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
@@ -19,11 +19,11 @@
import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.ScrimAlpha
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.SysuiStatusBarStateController
import dagger.Lazy
@@ -48,7 +48,7 @@
) {
/** Common fade for scrim alpha values during *BOUNCER->GONE */
fun scrimAlpha(duration: Duration, fromState: KeyguardState): Flow<ScrimAlpha> {
- return if (RefactorKeyguardDismissIntent.isEnabled) {
+ return if (SceneContainerFlag.isEnabled) {
keyguardDismissActionInteractor
.get()
.willAnimateDismissActionOnLockscreen
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
index a08a234..b1fa710 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -20,11 +20,11 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.keyguard.shared.model.ScrimAlpha
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.SysuiStatusBarStateController
import dagger.Lazy
import javax.inject.Inject
@@ -80,7 +80,7 @@
/** Bouncer container alpha */
val bouncerAlpha: Flow<Float> =
- if (RefactorKeyguardDismissIntent.isEnabled) {
+ if (SceneContainerFlag.isEnabled) {
keyguardDismissActionInteractor
.get()
.willAnimateDismissActionOnLockscreen
@@ -104,7 +104,7 @@
/** Lockscreen alpha */
val lockscreenAlpha: Flow<Float> =
- if (RefactorKeyguardDismissIntent.isEnabled) {
+ if (SceneContainerFlag.isEnabled) {
keyguardDismissActionInteractor
.get()
.willAnimateDismissActionOnLockscreen
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
index df3a974..9719c02 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
@@ -16,24 +16,64 @@
package com.android.systemui.media.controls.data.repository
+import android.content.Context
import com.android.internal.logging.InstanceId
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.media.controls.data.model.MediaSortKeyModel
import com.android.systemui.media.controls.shared.model.MediaCommonModel
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.time.SystemClock
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import java.util.Locale
import java.util.TreeMap
import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** A repository that holds the state of filtered media data on the device. */
@SysUISingleton
-class MediaFilterRepository @Inject constructor(private val systemClock: SystemClock) {
+class MediaFilterRepository
+@Inject
+constructor(
+ @Application applicationContext: Context,
+ private val systemClock: SystemClock,
+ private val configurationController: ConfigurationController,
+) {
+
+ val onAnyMediaConfigurationChange: Flow<Unit> = conflatedCallbackFlow {
+ val callback =
+ object : ConfigurationController.ConfigurationListener {
+ override fun onDensityOrFontScaleChanged() {
+ trySend(Unit)
+ }
+
+ override fun onThemeChanged() {
+ trySend(Unit)
+ }
+
+ override fun onUiModeChanged() {
+ trySend(Unit)
+ }
+
+ override fun onLocaleListChanged() {
+ if (locale != applicationContext.resources.configuration.locales.get(0)) {
+ locale = applicationContext.resources.configuration.locales.get(0)
+ trySend(Unit)
+ }
+ }
+ }
+ configurationController.addCallback(callback)
+ trySend(Unit)
+ awaitClose { configurationController.removeCallback(callback) }
+ }
/** Instance id of media control that recommendations card reactivated. */
private val _reactivatedId: MutableStateFlow<InstanceId?> = MutableStateFlow(null)
@@ -76,6 +116,7 @@
val isMediaFromRec: StateFlow<Boolean> = _isMediaFromRec.asStateFlow()
private var mediaFromRecPackageName: String? = null
+ private var locale: Locale = applicationContext.resources.configuration.locales.get(0)
fun addMediaEntry(key: String, data: MediaData) {
val entries = LinkedHashMap<String, MediaData>(_allUserEntries.value)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
index 13f934e..33c0b19 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
@@ -157,7 +157,7 @@
// Set up links back into the pipeline for listeners that need to send events upstream.
mediaTimeoutListener.timeoutCallback = { key: String, timedOut: Boolean ->
- setInactive(key, timedOut)
+ mediaDataProcessor.setInactive(key, timedOut)
}
mediaTimeoutListener.stateCallback = { key: String, state: PlaybackState ->
mediaDataProcessor.updateState(key, state)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
index c0bb628..9f2d132 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
@@ -83,6 +83,8 @@
.pairwiseBy(initialValue = false) { wasPlaying, isPlaying -> !wasPlaying && isPlaying }
.distinctUntilChanged()
+ val onAnyMediaConfigurationChange: Flow<Unit> = repository.onAnyMediaConfigurationChange
+
fun removeMediaControl(
token: MediaSession.Token?,
instanceId: InstanceId,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
index dea5810..dd6b264 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
@@ -65,6 +65,8 @@
.distinctUntilChanged()
.stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
+ val onAnyMediaConfigurationChange: Flow<Unit> = repository.onAnyMediaConfigurationChange
+
fun removeMediaRecommendations(key: String, dismissIntent: Intent?, delayMs: Long) {
mediaDataProcessor.dismissSmartspaceRecommendation(key, delayMs)
if (dismissIntent == null) {
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 8dd3379..73fb558 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
@@ -100,7 +100,7 @@
}
}
- private suspend fun bindMediaCard(
+ suspend fun bindMediaCard(
viewHolder: MediaViewHolder,
viewController: MediaViewController,
viewModel: MediaPlayerViewModel,
@@ -333,7 +333,7 @@
}
}
}
- updateSeekBarVisibility(viewController.expandedLayout, isSeekBarEnabled = false)
+ updateSeekBarVisibility(viewController.expandedLayout, viewController.isSeekBarEnabled)
}
private fun bindButtonCommon(
@@ -472,6 +472,7 @@
if (viewModel.shouldAddGradient) 333 else 80
)
}
+ ?: albumView.setImageDrawable(artwork)
}
viewController.isArtworkBound = viewModel.shouldAddGradient
viewController.prevArtwork = artwork
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
index fe13da6..bd4d435 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
@@ -68,7 +68,7 @@
}
}
- private fun bindRecsCard(
+ fun bindRecsCard(
viewHolder: RecommendationViewHolder,
viewModel: MediaRecsCardViewModel,
mediaViewController: MediaViewController,
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 c02ce3b..e17c0bb 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
@@ -139,6 +139,8 @@
}
reattachHostView()
onMediaHostVisibilityChanged(mediaHost.visible)
+
+ singlePaneContainer?.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
}
/** Called whenever the media hosts visibility changes */
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 d2dd289..0478178 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
@@ -35,6 +35,7 @@
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import androidx.recyclerview.widget.DiffUtil
import com.android.app.tracing.traceSection
import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
@@ -53,12 +54,18 @@
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.media.controls.ui.binder.MediaControlViewBinder
+import com.android.systemui.media.controls.ui.binder.MediaRecommendationsViewBinder
import com.android.systemui.media.controls.ui.controller.MediaControlPanel.SMARTSPACE_CARD_DISMISS_EVENT
+import com.android.systemui.media.controls.ui.util.MediaViewModelCallback
+import com.android.systemui.media.controls.ui.util.MediaViewModelListUpdateCallback
import com.android.systemui.media.controls.ui.view.MediaCarouselScrollHandler
import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.media.controls.ui.view.MediaScrollView
import com.android.systemui.media.controls.ui.view.MediaViewHolder
import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
+import com.android.systemui.media.controls.ui.viewmodel.MediaCarouselViewModel
+import com.android.systemui.media.controls.ui.viewmodel.MediaCommonViewModel
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.media.controls.util.SmallHash
@@ -118,12 +125,13 @@
private val mediaHostStatesManager: MediaHostStatesManager,
private val activityStarter: ActivityStarter,
private val systemClock: SystemClock,
+ @Main private val mainDispatcher: CoroutineDispatcher,
@Main executor: DelayableExecutor,
@Background private val bgExecutor: Executor,
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val mediaManager: MediaDataManager,
configurationController: ConfigurationController,
- falsingManager: FalsingManager,
+ private val falsingManager: FalsingManager,
dumpManager: DumpManager,
private val logger: MediaUiEventLogger,
private val debugLogger: MediaCarouselControllerLogger,
@@ -132,6 +140,8 @@
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val globalSettings: GlobalSettings,
private val secureSettings: SecureSettings,
+ private val mediaCarouselViewModel: MediaCarouselViewModel,
+ private val mediaViewControllerFactory: Provider<MediaViewController>,
) : Dumpable {
/** The current width of the carousel */
var currentCarouselWidth: Int = 0
@@ -182,7 +192,6 @@
private set
private val mediaContent: ViewGroup
@VisibleForTesting var pageIndicator: PageIndicator
- private val visualStabilityCallback: OnReorderingAllowedListener
private var needsReordering: Boolean = false
private var keysNeedRemoval = mutableSetOf<String>()
var shouldScrollToKey: Boolean = false
@@ -201,7 +210,11 @@
private val animationScaleObserver: ContentObserver =
object : ContentObserver(null) {
override fun onChange(selfChange: Boolean) {
- MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+ MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
+ } else {
+ controllerByViewModel.values.forEach { it.updateAnimatorDurationScale() }
+ }
}
}
@@ -297,6 +310,9 @@
private var widthInSceneContainerPx = 0
private var heightInSceneContainerPx = 0
+ private val controllerByViewModel = mutableMapOf<MediaCommonViewModel, MediaViewController>()
+ private val commonViewModels = mutableListOf<MediaCommonViewModel>()
+
init {
dumpManager.registerDumpable(TAG, this)
mediaFrame = inflateMediaCarousel()
@@ -320,7 +336,48 @@
inflateSettingsButton()
mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
configurationController.addCallback(configListener)
- visualStabilityCallback = OnReorderingAllowedListener {
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+ setUpListeners()
+ }
+ mediaFrame.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
+ // The pageIndicator is not laid out yet when we get the current state update,
+ // Lets make sure we have the right dimensions
+ updatePageIndicatorLocation()
+ }
+ mediaHostStatesManager.addCallback(
+ object : MediaHostStatesManager.Callback {
+ override fun onHostStateChanged(
+ @MediaLocation location: Int,
+ mediaHostState: MediaHostState
+ ) {
+ updateUserVisibility()
+ if (location == desiredLocation) {
+ onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)
+ }
+ }
+ }
+ )
+ keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+ mediaCarousel.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ listenForAnyStateToGoneKeyguardTransition(this)
+ listenForAnyStateToLockscreenTransition(this)
+ listenForLockscreenSettingChanges(this)
+
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) return@repeatOnLifecycle
+ listenForMediaItemsChanges(this)
+ }
+ }
+
+ // Notifies all active players about animation scale changes.
+ globalSettings.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
+ animationScaleObserver
+ )
+ }
+
+ private fun setUpListeners() {
+ val visualStabilityCallback = OnReorderingAllowedListener {
if (needsReordering) {
needsReordering = false
reorderAllPlayers(previousVisiblePlayerKey = null)
@@ -530,35 +587,6 @@
}
}
)
- mediaFrame.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
- // The pageIndicator is not laid out yet when we get the current state update,
- // Lets make sure we have the right dimensions
- updatePageIndicatorLocation()
- }
- mediaHostStatesManager.addCallback(
- object : MediaHostStatesManager.Callback {
- override fun onHostStateChanged(location: Int, mediaHostState: MediaHostState) {
- updateUserVisibility()
- if (location == desiredLocation) {
- onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)
- }
- }
- }
- )
- keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
- mediaCarousel.repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- listenForAnyStateToGoneKeyguardTransition(this)
- listenForAnyStateToLockscreenTransition(this)
- listenForLockscreenSettingChanges(this)
- }
- }
-
- // Notifies all active players about animation scale changes.
- globalSettings.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
- animationScaleObserver
- )
}
private fun inflateSettingsButton() {
@@ -642,6 +670,125 @@
}
}
+ private fun listenForMediaItemsChanges(scope: CoroutineScope): Job {
+ return scope.launch {
+ mediaCarouselViewModel.mediaItems.collectLatest {
+ val diffUtilCallback = MediaViewModelCallback(commonViewModels, it)
+ val listUpdateCallback =
+ MediaViewModelListUpdateCallback(
+ old = commonViewModels,
+ new = it,
+ onAdded = this@MediaCarouselController::onAdded,
+ onUpdated = this@MediaCarouselController::onUpdated,
+ onRemoved = this@MediaCarouselController::onRemoved,
+ onMoved = this@MediaCarouselController::onMoved,
+ )
+ DiffUtil.calculateDiff(diffUtilCallback).dispatchUpdatesTo(listUpdateCallback)
+ setNewViewModelsList(it)
+ }
+ }
+ }
+
+ private fun onAdded(commonViewModel: MediaCommonViewModel, position: Int) {
+ val viewController = mediaViewControllerFactory.get()
+ viewController.sizeChangedListener = this::updateCarouselDimensions
+ val lp =
+ LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ when (commonViewModel) {
+ is MediaCommonViewModel.MediaControl -> {
+ val viewHolder = MediaViewHolder.create(LayoutInflater.from(context), mediaContent)
+ if (mediaFlags.isSceneContainerEnabled()) {
+ viewController.widthInSceneContainerPx = widthInSceneContainerPx
+ viewController.heightInSceneContainerPx = heightInSceneContainerPx
+ }
+ viewController.attachPlayer(viewHolder)
+ viewController.mediaViewHolder.player.layoutParams = lp
+ MediaControlViewBinder.bind(
+ viewHolder,
+ commonViewModel.controlViewModel,
+ viewController,
+ falsingManager,
+ backgroundDispatcher,
+ mainDispatcher,
+ mediaFlags
+ )
+ mediaContent.addView(viewHolder.player, position)
+ }
+ is MediaCommonViewModel.MediaRecommendations -> {
+ val viewHolder =
+ RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent)
+ viewController.attachRecommendations(viewHolder)
+ viewController.recommendationViewHolder.recommendations.layoutParams = lp
+ MediaRecommendationsViewBinder.bind(
+ viewHolder,
+ commonViewModel.recsViewModel,
+ viewController,
+ falsingManager,
+ )
+ mediaContent.addView(viewHolder.recommendations, position)
+ }
+ }
+ viewController.setListening(mediaCarouselScrollHandler.visibleToUser && currentlyExpanded)
+ updateViewControllerToState(viewController, noAnimation = true)
+ updatePageIndicator()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ mediaFrame.requiresRemeasuring = true
+ commonViewModel.onAdded(commonViewModel)
+ controllerByViewModel[commonViewModel] = viewController
+ }
+
+ private fun onUpdated(commonViewModel: MediaCommonViewModel) {
+ commonViewModel.onUpdated(commonViewModel)
+ updatePageIndicator()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ }
+
+ private fun onRemoved(commonViewModel: MediaCommonViewModel) {
+ controllerByViewModel.remove(commonViewModel)?.let {
+ when (commonViewModel) {
+ is MediaCommonViewModel.MediaControl -> {
+ mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder.player)
+ mediaContent.removeView(it.mediaViewHolder.player)
+ }
+ is MediaCommonViewModel.MediaRecommendations -> {
+ mediaContent.removeView(it.recommendationViewHolder.recommendations)
+ }
+ }
+ it.onDestroy()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ updatePageIndicator()
+ commonViewModel.onRemoved(true)
+ }
+ }
+
+ private fun onMoved(commonViewModel: MediaCommonViewModel, from: Int, to: Int) {
+ controllerByViewModel[commonViewModel]?.let {
+ mediaContent.removeViewAt(from)
+ when (commonViewModel) {
+ is MediaCommonViewModel.MediaControl -> {
+ mediaContent.addView(it.mediaViewHolder.player, to)
+ }
+ is MediaCommonViewModel.MediaRecommendations -> {
+ mediaContent.addView(it.recommendationViewHolder.recommendations, to)
+ }
+ }
+ }
+ updatePageIndicator()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ }
+
+ private fun setNewViewModelsList(viewModels: List<MediaCommonViewModel>) {
+ commonViewModels.clear()
+ commonViewModels.addAll(viewModels)
+
+ // Ensure we only show the needed UMOs in media carousel.
+ val viewSet = viewModels.toHashSet()
+ controllerByViewModel.filter { !viewSet.contains(it.key) }.forEach { onRemoved(it.key) }
+ }
+
private suspend fun getMediaLockScreenSetting(): Boolean {
return withContext(backgroundDispatcher) {
secureSettings.getBoolForUser(
@@ -758,7 +905,7 @@
isSsReactivated,
debugLogger
)
- updatePlayerToState(newPlayer.mediaViewController, noAnimation = true)
+ updateViewControllerToState(newPlayer.mediaViewController, noAnimation = true)
// Media data added from a recommendation card should starts playing.
if (
(shouldScrollToKey && data.isPlaying == true) ||
@@ -856,7 +1003,7 @@
systemClock,
debugLogger,
)
- updatePlayerToState(newRecs.mediaViewController, noAnimation = true)
+ updateViewControllerToState(newRecs.mediaViewController, noAnimation = true)
reorderAllPlayers(curVisibleMediaKey)
updatePageIndicator()
mediaFrame.requiresRemeasuring = true
@@ -905,6 +1052,10 @@
}
private fun updatePlayers(recreateMedia: Boolean) {
+ if (mediaFlags.isMediaControlsRefactorEnabled()) {
+ updateMediaPlayers(recreateMedia)
+ return
+ }
pageIndicator.tintList =
ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
val previousVisibleKey =
@@ -940,6 +1091,28 @@
}
}
+ private fun updateMediaPlayers(recreateMedia: Boolean) {
+ pageIndicator.tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ if (recreateMedia) {
+ mediaContent.removeAllViews()
+ commonViewModels.forEach { viewModel ->
+ when (viewModel) {
+ is MediaCommonViewModel.MediaControl -> {
+ controllerByViewModel[viewModel]?.mediaViewHolder?.let {
+ mediaContent.addView(it.player)
+ }
+ }
+ is MediaCommonViewModel.MediaRecommendations -> {
+ controllerByViewModel[viewModel]?.recommendationViewHolder?.let {
+ mediaContent.addView(it.recommendations)
+ }
+ }
+ }
+ }
+ }
+ }
+
private fun updatePageIndicator() {
val numPages = mediaContent.getChildCount()
pageIndicator.setNumPages(numPages)
@@ -979,8 +1152,14 @@
currentStartLocation = startLocation
currentEndLocation = endLocation
currentTransitionProgress = progress
- for (mediaPlayer in MediaPlayerData.players()) {
- updatePlayerToState(mediaPlayer.mediaViewController, immediately)
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+ for (mediaPlayer in MediaPlayerData.players()) {
+ updateViewControllerToState(mediaPlayer.mediaViewController, immediately)
+ }
+ } else {
+ controllerByViewModel.values.forEach {
+ updateViewControllerToState(it, immediately)
+ }
}
maybeResetSettingsCog()
updatePageIndicatorAlpha()
@@ -1035,8 +1214,14 @@
/** Update listening to seekbar. */
private fun updateSeekbarListening(visibleToUser: Boolean) {
- for (player in MediaPlayerData.players()) {
- player.setListening(visibleToUser && currentlyExpanded)
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+ for (player in MediaPlayerData.players()) {
+ player.setListening(visibleToUser && currentlyExpanded)
+ }
+ } else {
+ controllerByViewModel.values.forEach {
+ it.setListening(visibleToUser && currentlyExpanded)
+ }
}
}
@@ -1044,12 +1229,22 @@
private fun updateCarouselDimensions() {
var width = 0
var height = 0
- for (mediaPlayer in MediaPlayerData.players()) {
- val controller = mediaPlayer.mediaViewController
- // When transitioning the view to gone, the view gets smaller, but the translation
- // Doesn't, let's add the translation
- width = Math.max(width, controller.currentWidth + controller.translationX.toInt())
- height = Math.max(height, controller.currentHeight + controller.translationY.toInt())
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+ for (mediaPlayer in MediaPlayerData.players()) {
+ val controller = mediaPlayer.mediaViewController
+ // When transitioning the view to gone, the view gets smaller, but the translation
+ // Doesn't, let's add the translation
+ width = Math.max(width, controller.currentWidth + controller.translationX.toInt())
+ height =
+ Math.max(height, controller.currentHeight + controller.translationY.toInt())
+ }
+ } else {
+ controllerByViewModel.values.forEach {
+ // When transitioning the view to gone, the view gets smaller, but the translation
+ // Doesn't, let's add the translation
+ width = Math.max(width, it.currentWidth + it.translationX.toInt())
+ height = Math.max(height, it.currentHeight + it.translationY.toInt())
+ }
}
if (width != currentCarouselWidth || height != currentCarouselHeight) {
currentCarouselWidth = width
@@ -1080,7 +1275,10 @@
}
}
- private fun updatePlayerToState(viewController: MediaViewController, noAnimation: Boolean) {
+ private fun updateViewControllerToState(
+ viewController: MediaViewController,
+ noAnimation: Boolean
+ ) {
viewController.setCurrentState(
startLocation = currentStartLocation,
endLocation = currentEndLocation,
@@ -1123,18 +1321,31 @@
!mediaManager.hasActiveMediaOrRecommendation() &&
desiredHostState.showsOnlyActiveMedia
- for (mediaPlayer in MediaPlayerData.players()) {
- if (animate) {
- mediaPlayer.mediaViewController.animatePendingStateChange(
- duration = duration,
- delay = startDelay
- )
- }
- if (shouldCloseGuts && mediaPlayer.mediaViewController.isGutsVisible) {
- mediaPlayer.closeGuts(!animate)
- }
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+ for (mediaPlayer in MediaPlayerData.players()) {
+ if (animate) {
+ mediaPlayer.mediaViewController.animatePendingStateChange(
+ duration = duration,
+ delay = startDelay
+ )
+ }
+ if (shouldCloseGuts && mediaPlayer.mediaViewController.isGutsVisible) {
+ mediaPlayer.closeGuts(!animate)
+ }
- mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
+ mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
+ }
+ } else {
+ controllerByViewModel.values.forEach { controller ->
+ if (animate) {
+ controller.animatePendingStateChange(duration, startDelay)
+ }
+ if (shouldCloseGuts && controller.isGutsVisible) {
+ controller.closeGuts(!animate)
+ }
+
+ controller.onLocationPreChange(desiredLocation)
+ }
}
mediaCarouselScrollHandler.showsSettingsButton = !it.showsOnlyActiveMedia
mediaCarouselScrollHandler.falsingProtectionNeeded = it.falsingProtectionNeeded
@@ -1150,7 +1361,11 @@
}
fun closeGuts(immediate: Boolean = true) {
- MediaPlayerData.players().forEach { it.closeGuts(immediate) }
+ if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+ MediaPlayerData.players().forEach { it.closeGuts(immediate) }
+ } else {
+ controllerByViewModel.values.forEach { it.closeGuts(immediate) }
+ }
}
/** Update the size of the carousel, remeasuring it if necessary. */
@@ -1288,6 +1503,10 @@
}
private fun onSwipeToDismiss() {
+ if (mediaFlags.isMediaControlsRefactorEnabled()) {
+ mediaCarouselViewModel.onSwipeToDismiss()
+ return
+ }
MediaPlayerData.players().forEachIndexed { index, it ->
if (it.mIsImpressed) {
logSmartspaceCardReported(
@@ -1319,6 +1538,7 @@
println("dataKeys: ${MediaPlayerData.dataKeys()}")
println("orderedPlayerSortKeys: ${MediaPlayerData.playerKeys()}")
println("visiblePlayerSortKeys: ${MediaPlayerData.visiblePlayerKeys()}")
+ println("commonViewModels: $commonViewModels")
println("smartspaceMediaData: ${MediaPlayerData.smartspaceMediaData}")
println("shouldPrioritizeSs: ${MediaPlayerData.shouldPrioritizeSs}")
println("current size: $currentCarouselWidth x $currentCarouselHeight")
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
index 5188132..96a8239 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
@@ -31,6 +31,7 @@
import com.android.systemui.util.Utils
import com.android.systemui.util.kotlin.pairwiseBy
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
@@ -50,6 +51,7 @@
@Application private val applicationScope: CoroutineScope,
@Application private val applicationContext: Context,
@Background private val backgroundDispatcher: CoroutineDispatcher,
+ @Background private val backgroundExecutor: Executor,
private val visualStabilityProvider: VisualStabilityProvider,
private val interactor: MediaCarouselInteractor,
private val controlInteractorFactory: MediaControlInteractorFactory,
@@ -142,9 +144,9 @@
private fun createMediaControlViewModel(instanceId: InstanceId): MediaControlViewModel {
return MediaControlViewModel(
- applicationScope = applicationScope,
applicationContext = applicationContext,
backgroundDispatcher = backgroundDispatcher,
+ backgroundExecutor = backgroundExecutor,
interactor = controlInteractorFactory.create(instanceId),
logger = logger,
)
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 52e49d6..bc364c3 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
@@ -41,21 +41,21 @@
import com.android.systemui.monet.Style
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.sample
+import java.util.concurrent.Executor
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
/** Models UI state and handles user input for a media control. */
class MediaControlViewModel(
@Application private val applicationContext: Context,
- @Application private val applicationScope: CoroutineScope,
@Background private val backgroundDispatcher: CoroutineDispatcher,
+ @Background private val backgroundExecutor: Executor,
private val interactor: MediaControlInteractor,
private val logger: MediaUiEventLogger,
) {
@@ -72,9 +72,15 @@
.distinctUntilChanged()
)
+ @OptIn(ExperimentalCoroutinesApi::class)
val player: Flow<MediaPlayerViewModel?> =
- combine(playTurbulenceNoise, interactor.mediaControl) { playTurbulenceNoise, mediaControl ->
- mediaControl?.let { toViewModel(it, playTurbulenceNoise) }
+ interactor.onAnyMediaConfigurationChange
+ .flatMapLatest {
+ combine(playTurbulenceNoise, interactor.mediaControl) {
+ playTurbulenceNoise,
+ mediaControl ->
+ mediaControl?.let { toViewModel(it, playTurbulenceNoise) }
+ }
}
.distinctUntilChanged()
.flowOn(backgroundDispatcher)
@@ -161,12 +167,10 @@
if (model.isResume && model.resumeProgress != null) {
seekBarViewModel.updateStaticProgress(model.resumeProgress)
} else {
- applicationScope.launch {
- withContext(backgroundDispatcher) {
- seekBarViewModel.updateController(
- model.token?.let { MediaController(applicationContext, it) }
- )
- }
+ backgroundExecutor.execute {
+ seekBarViewModel.updateController(
+ model.token?.let { MediaController(applicationContext, it) }
+ )
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
index 5cd9804..52c4bc5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
@@ -50,8 +50,10 @@
import com.android.systemui.res.R
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
@@ -67,9 +69,12 @@
private val logger: MediaUiEventLogger,
) {
+ @OptIn(ExperimentalCoroutinesApi::class)
val mediaRecsCard: Flow<MediaRecsCardViewModel?> =
- interactor.recommendations
- .map { recsCard -> toRecsViewModel(recsCard) }
+ interactor.onAnyMediaConfigurationChange
+ .flatMapLatest {
+ interactor.recommendations.map { recsCard -> toRecsViewModel(recsCard) }
+ }
.distinctUntilChanged()
.flowOn(backgroundDispatcher)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
index 22b3f35..cef1e69 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
@@ -33,19 +33,12 @@
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR
-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.media.controls.util.MediaFlags
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.util.concurrency.RepeatableExecutor
import javax.inject.Inject
import kotlin.math.abs
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
private const val POSITION_UPDATE_INTERVAL_MILLIS = 100L
private const val MIN_FLING_VELOCITY_SCALE_FACTOR = 10
@@ -88,11 +81,8 @@
class SeekBarViewModel
@Inject
constructor(
- @Application private val applicationScope: CoroutineScope,
- @Main private val mainDispatcher: CoroutineDispatcher,
@Background private val bgExecutor: RepeatableExecutor,
private val falsingManager: FalsingManager,
- private val mediaFlags: MediaFlags,
) {
private var _data =
Progress(
@@ -118,19 +108,9 @@
private var controller: MediaController? = null
set(value) {
if (field?.sessionToken != value?.sessionToken) {
- if (!mediaFlags.isMediaControlsRefactorEnabled()) {
- field?.unregisterCallback(callback)
- value?.registerCallback(callback)
- field = value
- } else {
- applicationScope.launch {
- withContext(mainDispatcher) {
- field?.unregisterCallback(callback)
- value?.registerCallback(callback)
- field = value
- }
- }
- }
+ field?.unregisterCallback(callback)
+ value?.registerCallback(callback)
+ field = value
}
}
private var playbackState: PlaybackState? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index 4e77d13..6a6eba1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -51,8 +51,7 @@
fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
/** Check whether to use scene framework */
- fun isSceneContainerEnabled() =
- SceneContainerFlag.isEnabled && MediaInSceneContainerFlag.isEnabled
+ fun isSceneContainerEnabled() = SceneContainerFlag.isEnabled
/** Check whether to use media refactor code */
fun isMediaControlsRefactorEnabled() = MediaControlsRefactorFlag.isEnabled
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt
deleted file mode 100644
index 77279f2..0000000
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.media.controls.util
-
-import com.android.systemui.Flags
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-
-/** Helper for reading or using the media_in_scene_container flag state. */
-@Suppress("NOTHING_TO_INLINE")
-object MediaInSceneContainerFlag {
- /** The aconfig flag name */
- const val FLAG_NAME = Flags.FLAG_MEDIA_IN_SCENE_CONTAINER
-
- /** A token used for dependency declaration */
- val token: FlagToken
- get() = FlagToken(FLAG_NAME, isEnabled)
-
- /** Is the flag enabled? */
- @JvmStatic
- inline val isEnabled
- get() = Flags.mediaInSceneContainer()
-
- /**
- * Called to ensure code is only run when the flag is enabled. This protects users from the
- * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
- * build to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun isUnexpectedlyInLegacyMode() =
- RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
-
- /**
- * Called to ensure code is only run when the flag is disabled. This will throw an exception if
- * the flag is enabled to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 48f432e..6cc4dcb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -254,6 +254,7 @@
window.setAttributes(lp);
window.setContentView(mDialogView);
window.setTitle(mContext.getString(R.string.media_output_dialog_accessibility_title));
+ window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
mHeaderTitle = mDialogView.requireViewById(R.id.header_title);
mHeaderSubtitle = mDialogView.requireViewById(R.id.header_subtitle);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 1a2ae8a..906ebad 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -39,6 +39,7 @@
import static com.android.systemui.navigationbar.NavBarHelper.transitionMode;
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
+import static com.android.systemui.shared.rotation.RotationButtonController.DEBUG_ROTATION;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
@@ -121,7 +122,6 @@
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
import com.android.systemui.navigationbar.buttons.DeadZone;
import com.android.systemui.navigationbar.buttons.KeyButtonView;
-import com.android.systemui.navigationbar.buttons.RotationContextButton;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.navigationbar.gestural.QuickswitchOrientedNavHandle;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -135,7 +135,6 @@
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.rotation.RotationButton;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
@@ -658,8 +657,8 @@
// When in gestural and the IME is showing, don't use the nearest region since it will
// take gesture space away from the IME
info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- info.touchableRegion.set(getButtonLocations(false /* includeFloatingButtons */,
- false /* inScreen */, false /* useNearestRegion */));
+ info.touchableRegion.set(
+ getButtonLocations(false /* inScreen */, false /* useNearestRegion */));
};
mRegionSamplingHelper = new RegionSamplingHelper(mView,
@@ -795,10 +794,7 @@
repositionNavigationBar(mCurrentRotation);
mView.setUpdateActiveTouchRegionsCallback(
() -> mOverviewProxyService.onActiveNavBarRegionChanges(
- getButtonLocations(
- true /* includeFloatingButtons */,
- true /* inScreen */,
- true /* useNearestRegion */)));
+ getButtonLocations(true /* inScreen */, true /* useNearestRegion */)));
mView.getViewTreeObserver().addOnComputeInternalInsetsListener(
mOnComputeInternalInsetsListener);
@@ -1135,16 +1131,14 @@
.hasDisable2RotateSuggestionFlag(mDisabledFlags2);
final RotationButtonController rotationButtonController =
mView.getRotationButtonController();
- final RotationButton rotationButton = rotationButtonController.getRotationButton();
-
- if (RotationContextButton.DEBUG_ROTATION) {
+ if (DEBUG_ROTATION) {
Log.v(TAG, "onRotationProposal proposedRotation=" + Surface.rotationToString(rotation)
+ ", isValid=" + isValid + ", mNavBarWindowState="
+ StatusBarManager.windowStateToString(mNavigationBarWindowState)
+ ", rotateSuggestionsDisabled=" + rotateSuggestionsDisabled
- + ", isRotateButtonVisible=" + rotationButton.isVisible());
+ + ", isRotateButtonVisible="
+ + rotationButtonController.getRotationButton().isVisible());
}
-
// Respect the disabled flag, no need for action as flag change callback will handle hiding
if (rotateSuggestionsDisabled) return;
@@ -1903,14 +1897,11 @@
}
/**
- * @param includeFloatingButtons Whether to include the floating rotation and overlay button in
- * the region for all the buttons
* @param inScreenSpace Whether to return values in screen space or window space
* @param useNearestRegion Whether to use the nearest region instead of the actual button bounds
* @return
*/
- Region getButtonLocations(boolean includeFloatingButtons, boolean inScreenSpace,
- boolean useNearestRegion) {
+ Region getButtonLocations(boolean inScreenSpace, boolean useNearestRegion) {
if (useNearestRegion && !inScreenSpace) {
// We currently don't support getting the nearest region in anything but screen space
useNearestRegion = false;
@@ -1928,13 +1919,10 @@
updateButtonLocation(
region, touchRegionCache, mView.getAccessibilityButton(), inScreenSpace,
useNearestRegion);
- if (includeFloatingButtons && mView.getFloatingRotationButton().isVisible()) {
+ if (mView.getFloatingRotationButton().isVisible()) {
// Note: this button is floating so the nearest region doesn't apply
updateButtonLocation(
region, mView.getFloatingRotationButton().getCurrentView(), inScreenSpace);
- } else {
- updateButtonLocation(region, touchRegionCache, mView.getRotateSuggestionButton(),
- inScreenSpace, useNearestRegion);
}
return region;
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 3c69ed9..a73275c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -69,7 +69,6 @@
import com.android.systemui.navigationbar.buttons.DeadZone;
import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
-import com.android.systemui.navigationbar.buttons.RotationContextButton;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.Recents;
import com.android.systemui.res.R;
@@ -153,7 +152,6 @@
private ShadeViewController mShadeViewController;
@Nullable
private PanelExpansionInteractor mPanelExpansionInteractor;
- private RotationContextButton mRotationContextButton;
private FloatingRotationButton mFloatingRotationButton;
private RotationButtonController mRotationButtonController;
@@ -293,8 +291,6 @@
R.drawable.ic_sysbar_accessibility_button);
mContextualButtonGroup.addButton(imeSwitcherButton);
mContextualButtonGroup.addButton(accessibilityButton);
- mRotationContextButton = new RotationContextButton(R.id.rotate_suggestion,
- mLightContext, R.drawable.ic_sysbar_rotate_button_ccw_start_0);
mFloatingRotationButton = new FloatingRotationButton(mContext,
R.string.accessibility_rotate_button,
R.layout.rotate_suggestion,
@@ -433,10 +429,6 @@
return mButtonDispatchers.get(R.id.accessibility_button);
}
- public RotationContextButton getRotateSuggestionButton() {
- return (RotationContextButton) mButtonDispatchers.get(R.id.rotate_suggestion);
- }
-
public ButtonDispatcher getHomeHandle() {
return mButtonDispatchers.get(R.id.home_handle);
}
@@ -483,18 +475,8 @@
* Updates the rotation button based on the current navigation mode.
*/
void updateRotationButton() {
- if (isGesturalMode(mNavBarMode)) {
- mContextualButtonGroup.removeButton(R.id.rotate_suggestion);
- mButtonDispatchers.remove(R.id.rotate_suggestion);
- mRotationButtonController.setRotationButton(mFloatingRotationButton,
- mRotationButtonListener);
- } else if (mContextualButtonGroup.getContextButton(R.id.rotate_suggestion) == null) {
- mContextualButtonGroup.addButton(mRotationContextButton);
- mButtonDispatchers.put(R.id.rotate_suggestion, mRotationContextButton);
- mRotationButtonController.setRotationButton(mRotationContextButton,
- mRotationButtonListener);
- }
- mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
+ mRotationButtonController.setRotationButton(mFloatingRotationButton,
+ mRotationButtonListener);
}
public KeyButtonDrawable getBackDrawable() {
@@ -1143,7 +1125,6 @@
dumpButton(pw, "home", getHomeButton());
dumpButton(pw, "handle", getHomeHandle());
dumpButton(pw, "rcnt", getRecentsButton());
- dumpButton(pw, "rota", getRotateSuggestionButton());
dumpButton(pw, "a11y", getAccessibilityButton());
dumpButton(pw, "ime", getImeSwitchButton());
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
deleted file mode 100644
index ac014b5..0000000
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/RotationContextButton.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.navigationbar.buttons;
-
-import android.annotation.DrawableRes;
-import android.annotation.IdRes;
-import android.content.Context;
-import android.view.View;
-
-import com.android.systemui.shared.rotation.RotationButton;
-import com.android.systemui.shared.rotation.RotationButtonController;
-
-/** Containing logic for the rotation button in nav bar. */
-public class RotationContextButton extends ContextualButton implements RotationButton {
- public static final boolean DEBUG_ROTATION = false;
-
- private RotationButtonController mRotationButtonController;
-
- /**
- * @param lightContext the context to use to load the icon resource
- */
- public RotationContextButton(@IdRes int buttonResId, Context lightContext,
- @DrawableRes int iconResId) {
- super(buttonResId, lightContext, iconResId);
- }
-
- @Override
- public void setRotationButtonController(RotationButtonController rotationButtonController) {
- mRotationButtonController = rotationButtonController;
- }
-
- @Override
- public void setUpdatesCallback(RotationButtonUpdatesCallback updatesCallback) {
- setListener((button, visible) -> {
- if (updatesCallback != null) {
- updatesCallback.onVisibilityChanged(visible);
- }
- });
- }
-
- @Override
- public void setVisibility(int visibility) {
- super.setVisibility(visibility);
-
- // Start the rotation animation once it becomes visible
- final KeyButtonDrawable currentDrawable = getImageDrawable();
- if (visibility == View.VISIBLE && currentDrawable != null) {
- currentDrawable.resetAnimation();
- currentDrawable.startAnimation();
- }
- }
-
- @Override
- protected KeyButtonDrawable getNewDrawable(int lightIconColor, int darkIconColor) {
- return KeyButtonDrawable.create(mRotationButtonController.getContext(),
- lightIconColor, darkIconColor, mRotationButtonController.getIconResId(),
- false /* shadow */, null /* ovalBackgroundColor */);
- }
-
- @Override
- public boolean acceptRotationProposal() {
- View currentView = getCurrentView();
- return currentView != null && currentView.isAttachedToWindow();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index 30f33a3..f8086f5 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -21,19 +21,20 @@
import android.graphics.Paint
import android.graphics.Point
import android.os.Handler
-import android.os.SystemClock
import android.util.Log
import android.util.MathUtils
import android.view.Gravity
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import android.view.VelocityTracker
+import android.view.View
import android.view.ViewConfiguration
import android.view.WindowManager
import androidx.annotation.VisibleForTesting
import androidx.core.os.postDelayed
import androidx.core.view.isVisible
import androidx.dynamicanimation.animation.DynamicAnimation
+import com.android.internal.jank.Cuj
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.util.LatencyTracker
import com.android.systemui.dagger.qualifiers.Main
@@ -41,6 +42,7 @@
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.ViewController
+import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import javax.inject.Inject
import kotlin.math.abs
@@ -84,6 +86,7 @@
private val windowManager: WindowManager,
private val viewConfiguration: ViewConfiguration,
@Main private val mainHandler: Handler,
+ private val systemClock: SystemClock,
private val vibratorHelper: VibratorHelper,
private val configurationController: ConfigurationController,
private val latencyTracker: LatencyTracker,
@@ -102,6 +105,7 @@
private val windowManager: WindowManager,
private val viewConfiguration: ViewConfiguration,
@Main private val mainHandler: Handler,
+ private val systemClock: SystemClock,
private val vibratorHelper: VibratorHelper,
private val configurationController: ConfigurationController,
private val latencyTracker: LatencyTracker,
@@ -115,6 +119,7 @@
windowManager,
viewConfiguration,
mainHandler,
+ systemClock,
vibratorHelper,
configurationController,
latencyTracker,
@@ -158,9 +163,9 @@
private var gestureInactiveTime = 0L
private val elapsedTimeSinceInactive
- get() = SystemClock.uptimeMillis() - gestureInactiveTime
+ get() = systemClock.uptimeMillis() - gestureInactiveTime
private val elapsedTimeSinceEntry
- get() = SystemClock.uptimeMillis() - gestureEntryTime
+ get() = systemClock.uptimeMillis() - gestureEntryTime
private var pastThresholdWhileEntryOrInactiveTime = 0L
private var entryToActiveDelay = 0F
@@ -178,7 +183,7 @@
// Distance in pixels a drag can be considered for a fling event
private var minFlingDistance = 0
- private val failsafeRunnable = Runnable { onFailsafe() }
+ internal val failsafeRunnable = Runnable { onFailsafe() }
internal enum class GestureState {
/* Arrow is off the screen and invisible */
@@ -370,6 +375,7 @@
// Receiving a CANCEL implies that something else intercepted
// the gesture, i.e., the user did not cancel their gesture.
// Therefore, disappear immediately, with minimum fanfare.
+ interactionJankMonitor.cancel(Cuj.CUJ_BACK_PANEL_ARROW)
updateArrowState(GestureState.GONE)
velocityTracker = null
}
@@ -692,10 +698,10 @@
}
if (isPastThresholdForFirstTime) {
- pastThresholdWhileEntryOrInactiveTime = SystemClock.uptimeMillis()
+ pastThresholdWhileEntryOrInactiveTime = systemClock.uptimeMillis()
entryToActiveDelay = dynamicDelay()
}
- val timePastThreshold = SystemClock.uptimeMillis() - pastThresholdWhileEntryOrInactiveTime
+ val timePastThreshold = systemClock.uptimeMillis() - pastThresholdWhileEntryOrInactiveTime
return timePastThreshold > entryToActiveDelay
}
@@ -881,6 +887,16 @@
previousState = currentState
currentState = newState
+ // First, update the jank tracker
+ when (currentState) {
+ GestureState.ENTRY -> {
+ interactionJankMonitor.cancel(Cuj.CUJ_BACK_PANEL_ARROW)
+ interactionJankMonitor.begin(mView, Cuj.CUJ_BACK_PANEL_ARROW)
+ }
+ GestureState.GONE -> interactionJankMonitor.end(Cuj.CUJ_BACK_PANEL_ARROW)
+ else -> {}
+ }
+
when (currentState) {
GestureState.CANCELLED -> {
backCallback.cancelBack()
@@ -912,7 +928,7 @@
mView.isVisible = true
updateRestingArrowDimens()
- gestureEntryTime = SystemClock.uptimeMillis()
+ gestureEntryTime = systemClock.uptimeMillis()
}
GestureState.ACTIVE -> {
previousXTranslationOnActiveOffset = previousXTranslation
@@ -927,7 +943,7 @@
mView.popOffEdge(popVelocity)
}
GestureState.INACTIVE -> {
- gestureInactiveTime = SystemClock.uptimeMillis()
+ gestureInactiveTime = systemClock.uptimeMillis()
// Typically entering INACTIVE means
// totalTouchDelta <= deactivationSwipeTriggerThreshold
@@ -1041,6 +1057,11 @@
pw.println(" isLeftPanel=${mView.isLeftPanel}")
}
+ @VisibleForTesting
+ internal fun getBackPanelView(): BackPanel {
+ return mView
+ }
+
init {
if (DEBUG)
mView.drawDebugInfo = { canvas ->
diff --git a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
index d863dcc..710142b6 100644
--- a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
@@ -96,7 +96,7 @@
if (messages2 == null) {
return -1;
}
- return (int) (n2.when - n1.when);
+ return (int) (n2.getWhen() - n1.getWhen());
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
index d40112f..3907a72 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
@@ -16,10 +16,16 @@
package com.android.systemui.qrcodescanner.dagger
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.qs.tiles.QRCodeScannerTile
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
+import com.android.systemui.res.R
import dagger.Binds
import dagger.Module
+import dagger.Provides
import dagger.multibindings.IntoMap
import dagger.multibindings.StringKey
@@ -31,4 +37,22 @@
@IntoMap
@StringKey(QRCodeScannerTile.TILE_SPEC)
fun bindQRCodeScannerTile(qrCodeScannerTile: QRCodeScannerTile): QSTileImpl<*>
+
+ companion object {
+ const val QR_CODE_SCANNER_TILE_SPEC = "qr_code_scanner"
+
+ @Provides
+ @IntoMap
+ @StringKey(QR_CODE_SCANNER_TILE_SPEC)
+ fun provideQRCodeScannerTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(QR_CODE_SCANNER_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = R.drawable.ic_qr_code_scanner,
+ labelRes = R.string.qr_code_scanner_title,
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 042fb63f..4ee2db7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -75,10 +75,6 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- // set layer to make alpha animation of brightness slider nicer - otherwise elements
- // of slider are animated separately and it doesn't look good. See b/329244723
- setLayerType(LAYER_TYPE_HARDWARE, null);
-
mQSPanelContainer = findViewById(R.id.expanded_qs_scroll_view);
mQSPanel = findViewById(R.id.quick_settings_panel);
mHeader = findViewById(R.id.header);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 58858df..829c419 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -332,6 +332,14 @@
return mTiles.size();
}
+ public int getItemCountForAccessibility() {
+ if (mAccessibilityAction == ACTION_MOVE) {
+ return mEditIndex;
+ } else {
+ return getItemCount();
+ }
+ }
+
@Override
public boolean onFailedToRecycleView(Holder holder) {
holder.stopDrag();
@@ -406,6 +414,10 @@
} else if (selectable && mAccessibilityAction == ACTION_MOVE) {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_tile_move_to_position, position);
+ } else if (!selectable && (mAccessibilityAction == ACTION_MOVE
+ || mAccessibilityAction == ACTION_ADD)) {
+ info.state.contentDescription = mContext.getString(
+ R.string.accessibilit_qs_edit_tile_add_move_invalid_position);
} else {
info.state.contentDescription = info.state.label;
}
@@ -424,14 +436,15 @@
holder.mTileView.setOnClickListener(null);
holder.mTileView.setFocusable(true);
holder.mTileView.setFocusableInTouchMode(true);
+ holder.mTileView.setAccessibilityTraversalBefore(View.NO_ID);
if (mAccessibilityAction != ACTION_NONE) {
holder.mTileView.setClickable(selectable);
holder.mTileView.setFocusable(selectable);
holder.mTileView.setFocusableInTouchMode(selectable);
- holder.mTileView.setImportantForAccessibility(selectable
- ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
- : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+// holder.mTileView.setImportantForAccessibility(selectable
+// ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
+// : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
if (selectable) {
holder.mTileView.setOnClickListener(new OnClickListener() {
@Override
@@ -911,4 +924,5 @@
int estimatedTileViewHeight = mTempTextView.getMeasuredHeight() * 2 + padding * 2;
mMinTileViewHeight = Math.max(minHeight, estimatedTileViewHeight);
}
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
index 2077d73..ba45d17 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
@@ -29,6 +29,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
@@ -109,6 +110,7 @@
private val falsingManager: FalsingManager,
private val footerActionsInteractor: FooterActionsInteractor,
private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>,
+ private val activityStarter: ActivityStarter,
@Named(PM_LITE_ENABLED) private val showPowerButton: Boolean,
) {
/** Create a [FooterActionsViewModel] bound to the lifecycle of [lifecycleOwner]. */
@@ -134,6 +136,7 @@
footerActionsInteractor,
falsingManager,
globalActionsDialogLite,
+ activityStarter,
showPowerButton,
)
}
@@ -145,6 +148,7 @@
footerActionsInteractor: FooterActionsInteractor,
falsingManager: FalsingManager,
globalActionsDialogLite: GlobalActionsDialogLite,
+ activityStarter: ActivityStarter,
showPowerButton: Boolean,
): FooterActionsViewModel {
suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) {
@@ -169,7 +173,14 @@
return
}
- footerActionsInteractor.showForegroundServicesDialog(expandable)
+ activityStarter.dismissKeyguardThenExecute(
+ {
+ footerActionsInteractor.showForegroundServicesDialog(expandable)
+ false /* if the dismiss should be deferred */
+ },
+ null /* cancelAction */,
+ true /* afterKeyguardGone */
+ )
}
fun onUserSwitcherClicked(expandable: Expandable) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt
index 4a8e33a..2e52845 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt
@@ -60,6 +60,7 @@
companion object {
/** Create a [TileSpec] from the string [spec]. */
+ @JvmStatic
fun create(spec: String): TileSpec {
return if (TextUtils.isEmpty(spec)) {
Invalid
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index d5b05ef..60469c0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -116,8 +116,6 @@
public class InternetDialogController implements AccessPointController.AccessPointCallback {
private static final String TAG = "InternetDialogController";
- private static final String ACTION_NETWORK_PROVIDER_SETTINGS =
- "android.settings.NETWORK_PROVIDER_SETTINGS";
private static final String ACTION_WIFI_SCANNING_SETTINGS =
"android.settings.WIFI_SCANNING_SETTINGS";
/**
@@ -361,7 +359,8 @@
@VisibleForTesting
protected Intent getSettingsIntent() {
- return new Intent(ACTION_NETWORK_PROVIDER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return new Intent(Settings.ACTION_NETWORK_PROVIDER_SETTINGS).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK);
}
@Nullable
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt
index fdc596b..eec5d3d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt
@@ -26,6 +26,7 @@
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.Text
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel
@@ -38,7 +39,9 @@
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
+import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
@@ -48,6 +51,7 @@
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
@OptIn(ExperimentalCoroutinesApi::class)
/** Observes internet state changes providing the [InternetTileModel]. */
@@ -55,6 +59,7 @@
@Inject
constructor(
private val context: Context,
+ @Main private val mainCoroutineContext: CoroutineContext,
@Application private val scope: CoroutineScope,
airplaneModeRepository: AirplaneModeRepository,
private val connectivityRepository: ConnectivityRepository,
@@ -111,42 +116,48 @@
notConnectedFlow
} else {
combine(
- it.networkName,
- it.signalLevelIcon,
- mobileDataContentName,
- ) { networkNameModel, signalIcon, dataContentDescription ->
- when (signalIcon) {
- is SignalIconModel.Cellular -> {
- val secondary =
- mobileDataContentConcat(
- networkNameModel.name,
- dataContentDescription
+ it.networkName,
+ it.signalLevelIcon,
+ mobileDataContentName,
+ ) { networkNameModel, signalIcon, dataContentDescription ->
+ Triple(networkNameModel, signalIcon, dataContentDescription)
+ }
+ .mapLatestConflated { (networkNameModel, signalIcon, dataContentDescription) ->
+ when (signalIcon) {
+ is SignalIconModel.Cellular -> {
+ val secondary =
+ mobileDataContentConcat(
+ networkNameModel.name,
+ dataContentDescription
+ )
+
+ val drawable =
+ withContext(mainCoroutineContext) { SignalDrawable(context) }
+ drawable.setLevel(signalIcon.level)
+ val loadedIcon = Icon.Loaded(drawable, null)
+
+ InternetTileModel.Active(
+ secondaryTitle = secondary,
+ icon = loadedIcon,
+ stateDescription =
+ ContentDescription.Loaded(secondary.toString()),
+ contentDescription = ContentDescription.Loaded(internetLabel),
)
-
- val stateLevel = signalIcon.level
- val drawable = SignalDrawable(context)
- drawable.setLevel(stateLevel)
- val loadedIcon = Icon.Loaded(drawable, null)
-
- InternetTileModel.Active(
- secondaryTitle = secondary,
- icon = loadedIcon,
- stateDescription = ContentDescription.Loaded(secondary.toString()),
- contentDescription = ContentDescription.Loaded(internetLabel),
- )
- }
- is SignalIconModel.Satellite -> {
- val secondary =
- signalIcon.icon.contentDescription.loadContentDescription(context)
- InternetTileModel.Active(
- secondaryTitle = secondary,
- iconId = signalIcon.icon.res,
- stateDescription = ContentDescription.Loaded(secondary),
- contentDescription = ContentDescription.Loaded(internetLabel),
- )
+ }
+ is SignalIconModel.Satellite -> {
+ val secondary =
+ signalIcon.icon.contentDescription.loadContentDescription(
+ context
+ )
+ InternetTileModel.Active(
+ secondaryTitle = secondary,
+ iconId = signalIcon.icon.res,
+ stateDescription = ContentDescription.Loaded(secondary),
+ contentDescription = ContentDescription.Loaded(internetLabel),
+ )
+ }
}
}
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
index 22146ce..257c4d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
@@ -29,6 +29,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
@@ -62,6 +63,7 @@
private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
private val footerActionsController: FooterActionsController,
sceneBackInteractor: SceneBackInteractor,
+ val mediaDataManager: MediaDataManager,
) {
private val backScene: StateFlow<SceneKey> =
sceneBackInteractor.backScene
@@ -141,4 +143,9 @@
}
return footerActionsViewModelFactory.create(lifecycleOwner)
}
+
+ fun isMediaVisible(): Boolean {
+ // TODO(b/328207006): use new pipeline to handle updates while visible
+ return mediaDataManager.hasAnyMediaOrRecommendation()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
index d67cf4d..26af9a7 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
@@ -16,10 +16,16 @@
package com.android.systemui.recordissue
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.qs.tiles.RecordIssueTile
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
+import com.android.systemui.res.R
import dagger.Binds
import dagger.Module
+import dagger.Provides
import dagger.multibindings.IntoMap
import dagger.multibindings.StringKey
@@ -30,4 +36,23 @@
@IntoMap
@StringKey(RecordIssueTile.TILE_SPEC)
fun bindRecordIssueTile(recordIssueTile: RecordIssueTile): QSTileImpl<*>
+
+ companion object {
+
+ const val RECORD_ISSUE_TILE_SPEC = "record_issue"
+
+ @Provides
+ @IntoMap
+ @StringKey(RECORD_ISSUE_TILE_SPEC)
+ fun provideRecordIssueTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(RECORD_ISSUE_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = R.drawable.qs_record_issue_icon_off,
+ labelRes = R.string.qs_record_issue_label
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 2a73b53..063a52c 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -16,10 +16,16 @@
package com.android.systemui.scene
+import com.android.systemui.CoreStartable
+import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
+import com.android.systemui.scene.domain.startable.SceneContainerStartable
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
+import dagger.Binds
import dagger.Module
import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
/** Scene framework Dagger module suitable for variants that want to exclude "keyguard" scenes. */
@Module(
@@ -31,28 +37,41 @@
ShadeSceneModule::class,
],
)
-object KeyguardlessSceneContainerFrameworkModule {
+interface KeyguardlessSceneContainerFrameworkModule {
- // TODO(b/298234162): provide a SceneContainerStartable without lockscreen and bouncer.
+ @Binds
+ @IntoMap
+ @ClassKey(SceneContainerStartable::class)
+ fun containerStartable(impl: SceneContainerStartable): CoreStartable
- @Provides
- fun containerConfig(): SceneContainerConfig {
- return SceneContainerConfig(
- // Note that this list is in z-order. The first one is the bottom-most and the
- // last one is top-most.
- sceneKeys =
- listOf(
- Scenes.Gone,
- Scenes.QuickSettings,
- Scenes.Shade,
- ),
- initialSceneKey = Scenes.Gone,
- navigationDistances =
- mapOf(
- Scenes.Gone to 0,
- Scenes.Shade to 1,
- Scenes.QuickSettings to 2,
- ),
- )
+ @Binds
+ @IntoMap
+ @ClassKey(WindowRootViewVisibilityInteractor::class)
+ fun bindWindowRootViewVisibilityInteractor(
+ impl: WindowRootViewVisibilityInteractor
+ ): CoreStartable
+
+ companion object {
+
+ @Provides
+ fun containerConfig(): SceneContainerConfig {
+ return SceneContainerConfig(
+ // Note that this list is in z-order. The first one is the bottom-most and the
+ // last one is top-most.
+ sceneKeys =
+ listOf(
+ Scenes.Gone,
+ Scenes.QuickSettings,
+ Scenes.Shade,
+ ),
+ initialSceneKey = Scenes.Gone,
+ navigationDistances =
+ mapOf(
+ Scenes.Gone to 0,
+ Scenes.Shade to 1,
+ Scenes.QuickSettings to 2,
+ ),
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index 994b012..5748ad4 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -81,14 +81,6 @@
toScene: SceneKey,
transitionKey: TransitionKey? = null,
) {
- check(allSceneKeys().contains(toScene)) {
- """
- Cannot set the desired scene key to "$toScene". The configuration does not
- contain a scene with that key.
- """
- .trimIndent()
- }
-
dataSource.changeScene(
toScene = toScene,
transitionKey = transitionKey,
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 2ccd3b9..93cef61 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -162,6 +162,10 @@
loggingReason: String,
transitionKey: TransitionKey? = null,
) {
+ if (!repository.allSceneKeys().contains(toScene)) {
+ return
+ }
+
check(
toScene != Scenes.Gone || deviceUnlockedInteractor.deviceUnlockStatus.value.isUnlocked
) {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 39ec12f..d5de28a3 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -57,12 +57,14 @@
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
import com.android.systemui.util.asIndenting
+import com.android.systemui.util.kotlin.getOrNull
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.printSection
import com.android.systemui.util.println
import dagger.Lazy
import java.io.PrintWriter
+import java.util.Optional
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -107,7 +109,7 @@
private val authenticationInteractor: Lazy<AuthenticationInteractor>,
private val windowController: NotificationShadeWindowController,
private val deviceProvisioningInteractor: DeviceProvisioningInteractor,
- private val centralSurfaces: CentralSurfaces,
+ private val centralSurfacesOptLazy: Lazy<Optional<CentralSurfaces>>,
private val headsUpInteractor: HeadsUpNotificationInteractor,
private val occlusionInteractor: SceneContainerOcclusionInteractor,
private val faceUnlockInteractor: DeviceEntryFaceAuthInteractor,
@@ -115,6 +117,8 @@
private val uiEventLogger: UiEventLogger,
private val sceneBackInteractor: SceneBackInteractor,
) : CoreStartable {
+ private val centralSurfaces: CentralSurfaces?
+ get() = centralSurfacesOptLazy.get().getOrNull()
override fun start() {
if (SceneContainerFlag.isEnabled) {
@@ -542,7 +546,7 @@
}
.collect { isInteractingOrNull ->
isInteractingOrNull?.let { isInteracting ->
- centralSurfaces.setInteracting(
+ centralSurfaces?.setInteracting(
StatusBarManager.WINDOW_STATUS_BAR,
isInteracting,
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
index 234eda8..cf33c4a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
@@ -27,8 +27,6 @@
import com.android.systemui.keyguard.KeyguardWmStateRefactor
import com.android.systemui.keyguard.MigrateClocksToBlueprint
import com.android.systemui.keyguard.shared.ComposeLockscreen
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
-import com.android.systemui.media.controls.util.MediaInSceneContainerFlag
import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor
import com.android.systemui.statusbar.phone.PredictiveBackSysUiFlag
@@ -44,12 +42,10 @@
ComposeLockscreen.isEnabled &&
KeyguardBottomAreaRefactor.isEnabled &&
KeyguardWmStateRefactor.isEnabled &&
- MediaInSceneContainerFlag.isEnabled &&
MigrateClocksToBlueprint.isEnabled &&
NotificationsHeadsUpRefactor.isEnabled &&
PredictiveBackSysUiFlag.isEnabled &&
- DeviceEntryUdfpsRefactor.isEnabled &&
- RefactorKeyguardDismissIntent.isEnabled
+ DeviceEntryUdfpsRefactor.isEnabled
// NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
/** The main aconfig flag. */
@@ -61,12 +57,10 @@
ComposeLockscreen.token,
KeyguardBottomAreaRefactor.token,
KeyguardWmStateRefactor.token,
- MediaInSceneContainerFlag.token,
MigrateClocksToBlueprint.token,
NotificationsHeadsUpRefactor.token,
PredictiveBackSysUiFlag.token,
DeviceEntryUdfpsRefactor.token,
- RefactorKeyguardDismissIntent.token,
// NOTE: Changes should also be made in isEnabled and @EnableSceneContainer
)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
index 864f29a..d4e711e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
@@ -229,6 +229,8 @@
return CallbackToFutureAdapter.getFuture(
(completer) -> {
executor.execute(() -> {
+ // save images as quickly as possible on the background thread
+ Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
try {
completer.set(task.execute());
} catch (ImageExportException | InterruptedException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
index 7130fa1..5960462 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
@@ -3,15 +3,19 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
-import android.os.UserHandle
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import android.view.ViewTreeObserver
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.constraintlayout.widget.Guideline
+import com.android.systemui.Flags.screenshotPrivateProfileBehaviorFix
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.res.R
+import com.android.systemui.screenshot.message.ProfileMessageController
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
/**
* MessageContainerController controls the display of content in the screenshot message container.
@@ -20,7 +24,9 @@
@Inject
constructor(
private val workProfileMessageController: WorkProfileMessageController,
+ private val profileMessageController: ProfileMessageController,
private val screenshotDetectionController: ScreenshotDetectionController,
+ @Application private val mainScope: CoroutineScope,
) {
private lateinit var container: ViewGroup
private lateinit var guideline: Guideline
@@ -42,43 +48,52 @@
detectionNoticeView.visibility = View.GONE
}
- // Minimal implementation for use when Flags.SCREENSHOT_METADATA isn't turned on.
- fun onScreenshotTaken(userHandle: UserHandle) {
- val workProfileData = workProfileMessageController.onScreenshotTaken(userHandle)
- if (workProfileData != null) {
- workProfileFirstRunView.visibility = View.VISIBLE
- detectionNoticeView.visibility = View.GONE
-
- workProfileMessageController.populateView(
- workProfileFirstRunView,
- workProfileData,
- this::animateOutMessageContainer
- )
- animateInMessageContainer()
- }
- }
-
fun onScreenshotTaken(screenshot: ScreenshotData) {
- val workProfileData = workProfileMessageController.onScreenshotTaken(screenshot.userHandle)
- var notifiedApps: List<CharSequence> =
- screenshotDetectionController.maybeNotifyOfScreenshot(screenshot)
+ if (screenshotPrivateProfileBehaviorFix()) {
+ mainScope.launch {
+ val profileData = profileMessageController.onScreenshotTaken(screenshot.userHandle)
+ var notifiedApps: List<CharSequence> =
+ screenshotDetectionController.maybeNotifyOfScreenshot(screenshot)
- // If work profile first run needs to show, bias towards that, otherwise show screenshot
- // detection notification if needed.
- if (workProfileData != null) {
- workProfileFirstRunView.visibility = View.VISIBLE
- detectionNoticeView.visibility = View.GONE
- workProfileMessageController.populateView(
- workProfileFirstRunView,
- workProfileData,
- this::animateOutMessageContainer
- )
- animateInMessageContainer()
- } else if (notifiedApps.isNotEmpty()) {
- detectionNoticeView.visibility = View.VISIBLE
- workProfileFirstRunView.visibility = View.GONE
- screenshotDetectionController.populateView(detectionNoticeView, notifiedApps)
- animateInMessageContainer()
+ // If profile first run needs to show, bias towards that, otherwise show screenshot
+ // detection notification if needed.
+ if (profileData != null) {
+ workProfileFirstRunView.visibility = View.VISIBLE
+ detectionNoticeView.visibility = View.GONE
+ profileMessageController.bindView(workProfileFirstRunView, profileData) {
+ animateOutMessageContainer()
+ }
+ animateInMessageContainer()
+ } else if (notifiedApps.isNotEmpty()) {
+ detectionNoticeView.visibility = View.VISIBLE
+ workProfileFirstRunView.visibility = View.GONE
+ screenshotDetectionController.populateView(detectionNoticeView, notifiedApps)
+ animateInMessageContainer()
+ }
+ }
+ } else {
+ val workProfileData =
+ workProfileMessageController.onScreenshotTaken(screenshot.userHandle)
+ var notifiedApps: List<CharSequence> =
+ screenshotDetectionController.maybeNotifyOfScreenshot(screenshot)
+
+ // If work profile first run needs to show, bias towards that, otherwise show screenshot
+ // detection notification if needed.
+ if (workProfileData != null) {
+ workProfileFirstRunView.visibility = View.VISIBLE
+ detectionNoticeView.visibility = View.GONE
+ workProfileMessageController.populateView(
+ workProfileFirstRunView,
+ workProfileData,
+ this::animateOutMessageContainer
+ )
+ animateInMessageContainer()
+ } else if (notifiedApps.isNotEmpty()) {
+ detectionNoticeView.visibility = View.VISIBLE
+ workProfileFirstRunView.visibility = View.GONE
+ screenshotDetectionController.populateView(detectionNoticeView, notifiedApps)
+ animateInMessageContainer()
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
index afb0280..d1b08f1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
@@ -35,4 +35,10 @@
@Binds
ScreenshotActionsProvider.Factory bindScreenshotActionsProviderFactory(
DefaultScreenshotActionsProvider.Factory defaultScreenshotActionsProviderFactory);
+
+ /** */
+ @Provides
+ static ThumbnailObserver providesThumbnailObserver() {
+ return new ThumbnailObserver();
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
index 12a3daa..9b754f3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
@@ -32,6 +32,7 @@
import android.window.OnBackInvokedCallback
import android.window.OnBackInvokedDispatcher
import androidx.core.animation.doOnEnd
+import androidx.core.animation.doOnStart
import com.android.internal.logging.UiEventLogger
import com.android.systemui.log.DebugLogger.debugLog
import com.android.systemui.res.R
@@ -56,6 +57,7 @@
private val logger: UiEventLogger,
private val viewModel: ScreenshotViewModel,
private val windowManager: WindowManager,
+ private val thumbnailObserver: ThumbnailObserver,
@Assisted private val context: Context,
@Assisted private val displayId: Int
) : ScreenshotViewProxy {
@@ -85,6 +87,7 @@
onDismissalRequested = { event, velocity -> requestDismissal(event, velocity) },
onDismissalCancelled = { animationController.getSwipeReturnAnimation().start() }
)
+ view.updateInsets(windowManager.currentWindowMetrics.windowInsets)
addPredictiveBackListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
setOnKeyListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
debugLog(DEBUG_WINDOW) { "adding OnComputeInternalInsetsListener" }
@@ -99,6 +102,10 @@
info.touchableRegion.set(touchableRegion)
}
screenshotPreview = view.screenshotPreview
+ thumbnailObserver.setViews(
+ view.screenshotPreview,
+ view.requireViewById(R.id.screenshot_preview_border)
+ )
}
override fun reset() {
@@ -106,13 +113,19 @@
isPendingSharedTransition = false
viewModel.reset()
}
- override fun updateInsets(insets: WindowInsets) {}
+ override fun updateInsets(insets: WindowInsets) {
+ view.updateInsets(insets)
+ }
override fun updateOrientation(insets: WindowInsets) {}
override fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator {
val entrance = animationController.getEntranceAnimation(screenRect, showFlash)
- // reset the timeout when animation finishes
- entrance.doOnEnd { callbacks?.onUserInteraction() }
+ entrance.doOnStart { thumbnailObserver.onEntranceStarted() }
+ entrance.doOnEnd {
+ // reset the timeout when animation finishes
+ callbacks?.onUserInteraction()
+ thumbnailObserver.onEntranceComplete()
+ }
return entrance
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ThumbnailObserver.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ThumbnailObserver.kt
new file mode 100644
index 0000000..cf62a14
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ThumbnailObserver.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot
+
+import android.view.View
+import android.widget.ImageView
+
+/** An observer of thumbnail UI and entrance state that can be overridden if needed. */
+open class ThumbnailObserver {
+ /** Thumbnail image and border views. */
+ open fun setViews(image: ImageView, border: View) {}
+
+ /** Entrance animation has begun. */
+ open fun onEntranceStarted() {}
+
+ /** Entrance animation has completed/stopped. */
+ open fun onEntranceComplete() {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
index c801ca5..b93aedd 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
@@ -53,8 +53,9 @@
if (userManager.isManagedProfile(userHandle.identifier) && !messageAlreadyDismissed()) {
var badgedIcon: Drawable? = null
var label: CharSequence? = null
- val fileManager = fileManagerComponentName()
- ?: return WorkProfileFirstRunData(defaultFileAppName(), null)
+ val fileManager =
+ fileManagerComponentName()
+ ?: return WorkProfileFirstRunData(defaultFileAppName(), null)
try {
val info = packageManager.getActivityInfo(fileManager, ComponentInfoFlags.of(0L))
val icon = packageManager.getActivityIcon(fileManager)
@@ -103,9 +104,7 @@
context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
private fun fileManagerComponentName() =
- ComponentName.unflattenFromString(
- context.getString(R.string.config_sceenshotWorkProfileFilesApp)
- )
+ ComponentName.unflattenFromString(context.getString(R.string.config_screenshotFilesApp))
private fun defaultFileAppName() = context.getString(R.string.screenshot_default_files_app_name)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index 9b8d047..8235325 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -38,6 +38,7 @@
import com.android.systemui.screenshot.TakeScreenshotService;
import com.android.systemui.screenshot.appclips.AppClipsScreenshotHelperService;
import com.android.systemui.screenshot.appclips.AppClipsService;
+import com.android.systemui.screenshot.message.MessageModule;
import com.android.systemui.screenshot.policy.ScreenshotPolicyModule;
import com.android.systemui.screenshot.proxy.SystemUiProxyModule;
import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel;
@@ -51,7 +52,7 @@
/**
* Defines injectable resources for Screenshots
*/
-@Module(includes = {ScreenshotPolicyModule.class, SystemUiProxyModule.class})
+@Module(includes = {ScreenshotPolicyModule.class, SystemUiProxyModule.class, MessageModule.class})
public abstract class ScreenshotModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/message/MessageModule.kt b/packages/SystemUI/src/com/android/systemui/screenshot/message/MessageModule.kt
new file mode 100644
index 0000000..9d0f87f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/message/MessageModule.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.message
+
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
+
+@Module
+interface MessageModule {
+ @Binds
+ @SysUISingleton
+ fun bindProfileFirstRunResources(
+ impl: ProfileFirstRunFileResourcesImpl
+ ): ProfileFirstRunFileResources
+
+ @Binds
+ @SysUISingleton
+ fun bindPackageLabelIconProvider(impl: PackageLabelIconProviderImpl): PackageLabelIconProvider
+
+ @Binds
+ @SysUISingleton
+ fun bindProfileFirstRunSettings(impl: ProfileFirstRunSettingsImpl): ProfileFirstRunSettings
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/message/PackageLabelIconProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/message/PackageLabelIconProvider.kt
new file mode 100644
index 0000000..fd073ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/message/PackageLabelIconProvider.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.message
+
+import android.content.ComponentName
+import android.content.pm.PackageManager
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import javax.inject.Inject
+
+data class LabeledIcon(
+ val label: CharSequence,
+ val badgedIcon: Drawable?,
+)
+
+/** An object that can fetch a label and icon for a given component. */
+interface PackageLabelIconProvider {
+ /**
+ * @return the label and icon for the given component.
+ * @throws PackageManager.NameNotFoundException if the component was not found.
+ */
+ suspend fun getPackageLabelIcon(
+ componentName: ComponentName,
+ userHandle: UserHandle
+ ): LabeledIcon
+}
+
+class PackageLabelIconProviderImpl @Inject constructor(private val packageManager: PackageManager) :
+ PackageLabelIconProvider {
+
+ override suspend fun getPackageLabelIcon(
+ componentName: ComponentName,
+ userHandle: UserHandle
+ ): LabeledIcon {
+ val info =
+ packageManager.getActivityInfo(componentName, PackageManager.ComponentInfoFlags.of(0L))
+ val icon = packageManager.getActivityIcon(componentName)
+ val badgedIcon = packageManager.getUserBadgedIcon(icon, userHandle)
+ val label = info.loadLabel(packageManager)
+ return LabeledIcon(label, badgedIcon)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileFirstRunFileResources.kt b/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileFirstRunFileResources.kt
new file mode 100644
index 0000000..e58c76d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileFirstRunFileResources.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.message
+
+import android.content.ComponentName
+import android.content.Context
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+/** Provides various configuration resource values for the profile first run flow. */
+interface ProfileFirstRunFileResources {
+ /** @return the ComponentName for the Files app, if available. */
+ fun fileManagerComponentName(): ComponentName?
+
+ /** @return a default LabeledIcon describing the files app */
+ fun defaultFileApp(): LabeledIcon
+}
+
+class ProfileFirstRunFileResourcesImpl @Inject constructor(private val context: Context) :
+ ProfileFirstRunFileResources {
+ override fun fileManagerComponentName() =
+ ComponentName.unflattenFromString(context.getString(R.string.config_screenshotFilesApp))
+
+ override fun defaultFileApp() =
+ LabeledIcon(
+ context.getString(R.string.screenshot_default_files_app_name),
+ badgedIcon = null
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileFirstRunSettings.kt b/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileFirstRunSettings.kt
new file mode 100644
index 0000000..5ec14a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileFirstRunSettings.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.message
+
+import android.content.Context
+import javax.inject.Inject
+
+/**
+ * An interfaces for the settings related to the profile first run experience, storing a bit
+ * indicating whether the user has already dismissed the message for the given profile.
+ */
+interface ProfileFirstRunSettings {
+ /** @return true if the user has already dismissed the first run message for this profile. */
+ fun messageAlreadyDismissed(profileType: ProfileMessageController.FirstRunProfile): Boolean
+ /**
+ * Update storage to reflect the fact that the user has dismissed a first run message for the
+ * given profile.
+ */
+ fun onMessageDismissed(profileType: ProfileMessageController.FirstRunProfile)
+}
+
+class ProfileFirstRunSettingsImpl @Inject constructor(private val context: Context) :
+ ProfileFirstRunSettings {
+
+ override fun messageAlreadyDismissed(
+ profileType: ProfileMessageController.FirstRunProfile
+ ): Boolean {
+ val preferenceKey = preferenceKey(profileType)
+ return sharedPreference().getBoolean(preferenceKey, false)
+ }
+
+ override fun onMessageDismissed(profileType: ProfileMessageController.FirstRunProfile) {
+ val preferenceKey = preferenceKey(profileType)
+ val editor = sharedPreference().edit()
+ editor.putBoolean(preferenceKey, true)
+ editor.apply()
+ }
+
+ private fun preferenceKey(profileType: ProfileMessageController.FirstRunProfile): String {
+ return when (profileType) {
+ ProfileMessageController.FirstRunProfile.WORK -> WORK_PREFERENCE_KEY
+ ProfileMessageController.FirstRunProfile.PRIVATE -> PRIVATE_PREFERENCE_KEY
+ }
+ }
+
+ private fun sharedPreference() =
+ context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
+
+ companion object {
+ const val SHARED_PREFERENCES_NAME = "com.android.systemui.screenshot"
+ const val WORK_PREFERENCE_KEY = "work_profile_first_run"
+ const val PRIVATE_PREFERENCE_KEY = "private_profile_first_run"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileMessageController.kt
new file mode 100644
index 0000000..9212a6a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/message/ProfileMessageController.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.message
+
+import android.os.UserHandle
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import com.android.systemui.res.R
+import com.android.systemui.screenshot.data.model.ProfileType
+import com.android.systemui.screenshot.data.repository.ProfileTypeRepository
+import javax.inject.Inject
+
+/**
+ * Handles work profile and private profile first run, determining whether a first run UI should be
+ * shown and populating that UI if needed.
+ */
+class ProfileMessageController
+@Inject
+constructor(
+ private val packageLabelIconProvider: PackageLabelIconProvider,
+ private val fileResources: ProfileFirstRunFileResources,
+ private val firstRunSettings: ProfileFirstRunSettings,
+ private val profileTypes: ProfileTypeRepository,
+) {
+
+ /**
+ * @return a populated ProfileFirstRunData object if a profile first run message should be
+ * shown, otherwise null.
+ */
+ suspend fun onScreenshotTaken(userHandle: UserHandle?): ProfileFirstRunData? {
+ if (userHandle == null) return null
+ val profileType =
+ when (profileTypes.getProfileType(userHandle.identifier)) {
+ ProfileType.WORK -> FirstRunProfile.WORK
+ ProfileType.PRIVATE -> FirstRunProfile.PRIVATE
+ else -> return null
+ }
+
+ if (firstRunSettings.messageAlreadyDismissed(profileType)) {
+ return null
+ }
+
+ val fileApp =
+ runCatching {
+ fileResources.fileManagerComponentName()?.let { fileManager ->
+ packageLabelIconProvider.getPackageLabelIcon(fileManager, userHandle)
+ }
+ }
+ .getOrNull() ?: fileResources.defaultFileApp()
+
+ return ProfileFirstRunData(fileApp, profileType)
+ }
+
+ /**
+ * Use the provided ProfileFirstRunData to populate the profile first run UI in the given view.
+ */
+ fun bindView(view: ViewGroup, data: ProfileFirstRunData, animateOut: () -> Unit) {
+ if (data.labeledIcon.badgedIcon != null) {
+ // Replace the default icon if one is provided.
+ val imageView = view.requireViewById<ImageView>(R.id.screenshot_message_icon)
+ imageView.setImageDrawable(data.labeledIcon.badgedIcon)
+ }
+ val messageContent = view.requireViewById<TextView>(R.id.screenshot_message_content)
+ messageContent.text =
+ view.context.getString(messageTemplate(data.profileType), data.labeledIcon.label)
+ view.requireViewById<View>(R.id.message_dismiss_button).setOnClickListener {
+ animateOut()
+ firstRunSettings.onMessageDismissed(data.profileType)
+ }
+ }
+
+ private fun messageTemplate(profile: FirstRunProfile): Int {
+ return when (profile) {
+ FirstRunProfile.WORK -> R.string.screenshot_work_profile_notification
+ FirstRunProfile.PRIVATE -> R.string.screenshot_private_profile_notification
+ }
+ }
+
+ data class ProfileFirstRunData(
+ val labeledIcon: LabeledIcon,
+ val profileType: FirstRunProfile,
+ )
+
+ enum class FirstRunProfile {
+ WORK,
+ PRIVATE
+ }
+
+ companion object {
+ const val TAG = "PrivateProfileMessageCtrl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
index 3f4f74b..4eceb17 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
@@ -25,6 +25,7 @@
import android.util.MathUtils
import android.view.View
import android.view.animation.AnimationUtils
+import android.widget.ImageView
import androidx.core.animation.doOnEnd
import androidx.core.animation.doOnStart
import com.android.systemui.res.R
@@ -34,7 +35,7 @@
class ScreenshotAnimationController(private val view: ScreenshotShelfView) {
private var animator: Animator? = null
- private val screenshotPreview = view.requireViewById<View>(R.id.screenshot_preview)
+ private val screenshotPreview = view.requireViewById<ImageView>(R.id.screenshot_preview)
private val flashView = view.requireViewById<View>(R.id.screenshot_flash)
private val actionContainer = view.requireViewById<View>(R.id.actions_container_background)
private val fastOutSlowIn =
@@ -155,6 +156,12 @@
val previewAnimator = AnimatorSet()
previewAnimator.play(previewXAndScaleAnimator).with(previewYAnimator)
+ previewAnimator.doOnEnd {
+ screenshotPreview.scaleX = 1f
+ screenshotPreview.scaleY = 1f
+ screenshotPreview.x = endPos.x - screenshotPreview.width / 2f
+ screenshotPreview.y = endPos.y - screenshotPreview.height / 2f
+ }
previewAnimator.doOnStart { screenshotPreview.visibility = View.VISIBLE }
return previewAnimator
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
index f9af4b9..4437bf5 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
@@ -17,20 +17,25 @@
package com.android.systemui.screenshot.ui
import android.content.Context
+import android.content.res.Configuration
import android.graphics.Insets
import android.graphics.Rect
import android.graphics.Region
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
+import android.view.ViewGroup
+import android.view.WindowInsets
+import android.widget.FrameLayout
import android.widget.ImageView
-import androidx.constraintlayout.widget.ConstraintLayout
import com.android.systemui.res.R
import com.android.systemui.screenshot.FloatingWindowUtil
+import kotlin.math.max
class ScreenshotShelfView(context: Context, attrs: AttributeSet? = null) :
- ConstraintLayout(context, attrs) {
+ FrameLayout(context, attrs) {
lateinit var screenshotPreview: ImageView
+ private lateinit var screenshotStatic: ViewGroup
var onTouchInterceptListener: ((MotionEvent) -> Boolean)? = null
private val displayMetrics = context.resources.displayMetrics
@@ -43,6 +48,7 @@
// Get focus so that the key events go to the layout.
isFocusableInTouchMode = true
screenshotPreview = requireViewById(R.id.screenshot_preview)
+ screenshotStatic = requireViewById(R.id.screenshot_static)
actionsContainerBackground = requireViewById(R.id.actions_container_background)
dismissButton = requireViewById(R.id.screenshot_dismiss_button)
}
@@ -66,6 +72,40 @@
return region
}
+ fun updateInsets(insets: WindowInsets) {
+ val orientation = mContext.resources.configuration.orientation
+ val inPortrait = orientation == Configuration.ORIENTATION_PORTRAIT
+ val p = screenshotStatic.layoutParams as LayoutParams
+ val cutout = insets.displayCutout
+ val navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars())
+ if (cutout == null) {
+ p.setMargins(0, 0, 0, navBarInsets.bottom)
+ } else {
+ val waterfall = cutout.waterfallInsets
+ if (inPortrait) {
+ p.setMargins(
+ waterfall.left,
+ max(cutout.safeInsetTop.toDouble(), waterfall.top.toDouble()).toInt(),
+ waterfall.right,
+ max(
+ cutout.safeInsetBottom.toDouble(),
+ max(navBarInsets.bottom.toDouble(), waterfall.bottom.toDouble())
+ )
+ .toInt()
+ )
+ } else {
+ p.setMargins(
+ max(cutout.safeInsetLeft.toDouble(), waterfall.left.toDouble()).toInt(),
+ waterfall.top,
+ max(cutout.safeInsetRight.toDouble(), waterfall.right.toDouble()).toInt(),
+ max(navBarInsets.bottom.toDouble(), waterfall.bottom.toDouble()).toInt()
+ )
+ }
+ }
+ screenshotStatic.layoutParams = p
+ screenshotStatic.requestLayout()
+ }
+
private fun getSwipeRegion(): Region {
val swipeRegion = Region()
val padding = FloatingWindowUtil.dpToPx(displayMetrics, -1 * TOUCH_PADDING_DP).toInt()
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
index 3376b8c..734a530 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
@@ -16,8 +16,11 @@
package com.android.systemui.screenshot.ui.binder
+import android.graphics.Bitmap
import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.lifecycle.Lifecycle
@@ -68,7 +71,7 @@
launch {
viewModel.preview.collect { bitmap ->
if (bitmap != null) {
- previewView.setImageBitmap(bitmap)
+ setScreenshotBitmap(previewView, bitmap)
previewView.visibility = View.VISIBLE
previewBorder.visibility = View.VISIBLE
} else {
@@ -128,4 +131,23 @@
}
}
}
+
+ private fun setScreenshotBitmap(screenshotPreview: ImageView, bitmap: Bitmap) {
+ screenshotPreview.setImageBitmap(bitmap)
+ val hasPortraitAspectRatio = bitmap.width < bitmap.height
+ val fixedSize = screenshotPreview.resources.getDimensionPixelSize(R.dimen.overlay_x_scale)
+ val params: ViewGroup.LayoutParams = screenshotPreview.layoutParams
+ if (hasPortraitAspectRatio) {
+ params.width = fixedSize
+ params.height = FrameLayout.LayoutParams.WRAP_CONTENT
+ screenshotPreview.scaleType = ImageView.ScaleType.FIT_START
+ } else {
+ params.width = FrameLayout.LayoutParams.WRAP_CONTENT
+ params.height = fixedSize
+ screenshotPreview.scaleType = ImageView.ScaleType.FIT_END
+ }
+
+ screenshotPreview.layoutParams = params
+ screenshotPreview.requestLayout()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index e051dab..92006a4 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -63,6 +63,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ setLayerType(LAYER_TYPE_HARDWARE, null);
mSlider = requireViewById(R.id.slider);
mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 67211b1..4d4d177 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -244,6 +244,7 @@
import kotlinx.coroutines.CoroutineDispatcher;
import kotlinx.coroutines.flow.Flow;
+import kotlinx.coroutines.flow.StateFlow;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -3991,7 +3992,12 @@
mExpandLatencyTracking = false;
}
float maxPanelHeight = getMaxPanelTransitionDistance();
- if (mHeightAnimator == null) {
+ if (mHeightAnimator == null && !MigrateClocksToBlueprint.isEnabled()) {
+ // MigrateClocksToBlueprint - There is an edge case where swiping up slightly,
+ // and then swiping down will trigger overscroll logic. Even without this flag
+ // enabled, the notifications can then run into UDFPS. At this point it is
+ // safer to remove overscroll for this one case to prevent overlap.
+
// Split shade has its own overscroll logic
if (isTracking()) {
float overExpansionPixels = Math.max(0, h - maxPanelHeight);
@@ -4055,6 +4061,11 @@
}
@Override
+ public StateFlow<Float> getUdfpsTransitionToFullShadeProgress() {
+ return mShadeRepository.getUdfpsTransitionToFullShadeProgress();
+ }
+
+ @Override
public Flow<Float> getLegacyPanelExpansion() {
return mShadeRepository.getLegacyShadeExpansion();
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 8b7e11c..4a636d2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -68,7 +68,6 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -131,7 +130,6 @@
mCallbacks = new ArrayList<>();
private final SysuiColorExtractor mColorExtractor;
- private final ScreenOffAnimationController mScreenOffAnimationController;
/**
* Layout params would be aggregated and dispatched all at once if this is > 0.
*
@@ -159,7 +157,6 @@
SysuiColorExtractor colorExtractor,
DumpManager dumpManager,
KeyguardStateController keyguardStateController,
- ScreenOffAnimationController screenOffAnimationController,
AuthController authController,
Lazy<ShadeInteractor> shadeInteractorLazy,
ShadeWindowLogger logger,
@@ -179,7 +176,6 @@
mKeyguardBypassController = keyguardBypassController;
mBackgroundExecutor = backgroundExecutor;
mColorExtractor = colorExtractor;
- mScreenOffAnimationController = screenOffAnimationController;
// prefix with {slow} to make sure this dumps at the END of the critical section.
dumpManager.registerCriticalDumpable("{slow}NotificationShadeWindowControllerImpl", this);
mAuthController = authController;
@@ -441,14 +437,8 @@
private void applyFocusableFlag(NotificationShadeWindowState state) {
boolean panelFocusable = state.notificationShadeFocusable && state.shadeOrQsExpanded;
if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput)
- || ENABLE_REMOTE_INPUT && state.remoteInputActive
- // Make the panel focusable if we're doing the screen off animation, since the light
- // reveal scrim is drawing in the panel and should consume touch events so that they
- // don't go to the app behind.
- || mScreenOffAnimationController.shouldIgnoreKeyguardTouches()) {
- mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
- mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- } else if (state.glanceableHubShowing) {
+ || (ENABLE_REMOTE_INPUT && state.remoteInputActive)
+ || state.glanceableHubShowing) {
mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
index 0c41efd..9322d31 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
@@ -25,6 +25,7 @@
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
import java.util.function.Consumer
import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
/** Empty implementation of ShadeViewController for variants with no shade. */
@@ -92,6 +93,7 @@
override val shadeFoldAnimator = ShadeFoldAnimatorEmptyImpl()
@Deprecated("Use SceneInteractor.currentScene instead.")
override val legacyPanelExpansion = flowOf(0f)
+ override val udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
}
class ShadeHeadsUpTrackerEmptyImpl : ShadeHeadsUpTracker {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
index e3d2f7d..4b6dd8d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
@@ -199,7 +199,7 @@
for (int i = 0; i < SIM_SLOTS; i++) {
mInfos[i] = new CellSignalState(
- true,
+ false,
R.drawable.ic_shade_no_calling_sms,
context.getText(AccessibilityContentDescriptions.NO_CALLING).toString(),
"",
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index 5c79e1e..b934d63 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -28,7 +28,7 @@
* Amount qs has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded. Quick
* Settings can be expanded without the full shade expansion.
*/
- val qsExpansion: StateFlow<Float>
+ @Deprecated("Use ShadeInteractor.qsExpansion instead") val qsExpansion: StateFlow<Float>
/** Amount shade has expanded with regard to the UDFPS location */
val udfpsTransitionToFullShadeProgress: StateFlow<Float>
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
index 2611092..987c016 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
@@ -15,9 +15,14 @@
*/
package com.android.systemui.shade.domain.interactor
+import kotlinx.coroutines.flow.StateFlow
+
/** Allows the lockscreen to control the shade. */
interface ShadeLockscreenInteractor {
+ /** Amount shade has expanded with regard to the UDFPS location */
+ val udfpsTransitionToFullShadeProgress: StateFlow<Float>
+
/**
* Expand shade so that notifications are visible. Non-split shade: just expanding shade or
* collapsing QS when they're expanded. Split shade: only expanding shade, notifications are
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
index 318da55..6a8b9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
@@ -20,6 +20,7 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.data.repository.ShadeRepository
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
@@ -32,7 +33,12 @@
private val shadeInteractor: ShadeInteractor,
private val sceneInteractor: SceneInteractor,
private val lockIconViewController: LockIconViewController,
+ shadeRepository: ShadeRepository,
) : ShadeLockscreenInteractor {
+
+ override val udfpsTransitionToFullShadeProgress =
+ shadeRepository.udfpsTransitionToFullShadeProgress
+
override fun expandToNotifications() {
changeToShadeScene()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt b/packages/SystemUI/src/com/android/systemui/shade/shared/flag/DualShade.kt
similarity index 70%
rename from packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt
rename to packages/SystemUI/src/com/android/systemui/shade/shared/flag/DualShade.kt
index a43eb71..4db4058 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/shared/flag/DualShade.kt
@@ -14,26 +14,29 @@
* limitations under the License.
*/
-package com.android.systemui.keyguard.shared
+package com.android.systemui.shade.shared.flag
import com.android.systemui.Flags
import com.android.systemui.flags.FlagToken
import com.android.systemui.flags.RefactorFlagUtils
-/** Helper for reading or using the refactor_keyguard_dismiss_intent flag. */
-@Suppress("NOTHING_TO_INLINE")
-object RefactorKeyguardDismissIntent {
- /** The aconfig flag name */
- const val FLAG_NAME = Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
+/** Helper for reading and using the Dual Shade feature flag. */
+object DualShade {
- /** A token used for dependency declaration */
+ /** The aconfig flag name. */
+ const val FLAG_NAME = Flags.FLAG_DUAL_SHADE
+
+ /** The flag description -- not an aconfig flag name. */
+ const val DESCRIPTION = "DualShadeFlag"
+
+ /** A token used for dependency declaration. */
val token: FlagToken
get() = FlagToken(FLAG_NAME, isEnabled)
- /** Is the refactor enabled */
+ /** Whether the feature is enabled. */
@JvmStatic
inline val isEnabled
- get() = Flags.refactorKeyguardDismissIntent()
+ get() = Flags.dualShade()
/**
* Called to ensure code is only run when the flag is enabled. This protects users from the
@@ -41,13 +44,13 @@
* build to ensure that the refactor author catches issues in testing.
*/
@JvmStatic
- inline fun isUnexpectedlyInLegacyMode() =
- RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+ fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, DESCRIPTION)
/**
* Called to ensure code is only run when the flag is disabled. This will throw an exception if
* the flag is enabled to ensure that the refactor author catches issues in testing.
*/
@JvmStatic
- inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+ fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, DESCRIPTION)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index acb00d5..90567d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -33,7 +33,6 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
-import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
@@ -636,8 +635,7 @@
TextView categoryTitle = (TextView) inflater.inflate(
R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false);
categoryTitle.setText(group.getLabel());
- categoryTitle.setTextColor(group.isSystemGroup() ? Utils.getColorAccent(mContext) :
- ColorStateList.valueOf(mContext.getColor(R.color.ksh_application_group_color)));
+ categoryTitle.setTextColor(Utils.getColorAccent(mContext));
keyboardShortcutsLayout.addView(categoryTitle);
LinearLayout shortcutContainer = (LinearLayout) inflater.inflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 09985f8..7983db1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -21,6 +21,7 @@
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_MANAGEMENT_DISCLOSURE;
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
import static android.hardware.biometrics.BiometricSourceType.FACE;
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.view.View.GONE;
@@ -60,7 +61,6 @@
import android.content.res.Resources;
import android.graphics.Color;
import android.hardware.biometrics.BiometricSourceType;
-import android.hardware.face.FaceManager;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Looper;
@@ -1404,7 +1404,7 @@
mKeyguardLogger.logBiometricMessage("KIC suppressingFaceError", msgId, errString);
return;
}
- if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
+ if (msgId == FACE_ERROR_TIMEOUT) {
handleFaceAuthTimeoutError(deferredFaceMessage);
} else if (mIndicationHelper.isFaceLockoutErrorMsg(msgId)) {
handleFaceLockoutError(errString);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index d465973..4d7dacd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -29,6 +29,7 @@
import android.util.Log;
import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
import com.android.systemui.media.controls.shared.model.MediaData;
@@ -47,6 +48,7 @@
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
+import java.util.concurrent.Executor;
/**
* Handles tasks and state related to media notifications. For example, there is a 'current' media
@@ -75,6 +77,8 @@
private final Context mContext;
private final ArrayList<MediaListener> mMediaListeners;
+ private final Executor mBackgroundExecutor;
+
protected NotificationPresenter mPresenter;
private MediaController mMediaController;
private String mMediaNotificationKey;
@@ -115,13 +119,15 @@
NotifPipeline notifPipeline,
NotifCollection notifCollection,
MediaDataManager mediaDataManager,
- DumpManager dumpManager) {
+ DumpManager dumpManager,
+ @Background Executor backgroundExecutor) {
mContext = context;
mMediaListeners = new ArrayList<>();
mVisibilityProvider = visibilityProvider;
mMediaDataManager = mediaDataManager;
mNotifPipeline = notifPipeline;
mNotifCollection = notifCollection;
+ mBackgroundExecutor = backgroundExecutor;
setupNotifPipeline();
@@ -381,9 +387,11 @@
Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
+ mMediaController.getPackageName());
}
- mMediaController.unregisterCallback(mMediaListener);
+ mBackgroundExecutor.execute(() -> {
+ mMediaController.unregisterCallback(mMediaListener);
+ mMediaController = null;
+ });
}
- mMediaController = null;
}
public interface MediaListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
index 7a7cb7d..c7952b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
@@ -95,6 +95,9 @@
const val AIRPLANE_MODE_TILE_SPEC = "airplane"
const val DATA_SAVER_TILE_SPEC = "saver"
const val INTERNET_TILE_SPEC = "internet"
+ const val HOTSPOT_TILE_SPEC = "hotspot"
+ const val CAST_TILE_SPEC = "cast"
+ const val BLUETOOTH_TILE_SPEC = "bt"
/** Inject InternetTile or InternetTileNewImpl into tileMap in QSModule */
@Provides
@@ -204,5 +207,47 @@
stateInteractor,
mapper,
)
+
+ @Provides
+ @IntoMap
+ @StringKey(HOTSPOT_TILE_SPEC)
+ fun provideHotspotTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(HOTSPOT_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = R.drawable.ic_hotspot,
+ labelRes = R.string.quick_settings_hotspot_label,
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
+
+ @Provides
+ @IntoMap
+ @StringKey(CAST_TILE_SPEC)
+ fun provideCastTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(CAST_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = R.drawable.ic_cast,
+ labelRes = R.string.quick_settings_cast_title,
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
+
+ @Provides
+ @IntoMap
+ @StringKey(BLUETOOTH_TILE_SPEC)
+ fun provideBluetoothTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(BLUETOOTH_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = R.drawable.qs_bluetooth_icon_off,
+ labelRes = R.string.quick_settings_bluetooth_label,
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 8a53e0c..c17da4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -31,6 +31,7 @@
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dump.DumpHandler;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
@@ -68,6 +69,8 @@
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
+import java.util.concurrent.Executor;
+
import javax.inject.Provider;
/**
@@ -94,14 +97,16 @@
NotifPipeline notifPipeline,
NotifCollection notifCollection,
MediaDataManager mediaDataManager,
- DumpManager dumpManager) {
+ DumpManager dumpManager,
+ @Background Executor backgroundExecutor) {
return new NotificationMediaManager(
context,
visibilityProvider,
notifPipeline,
notifCollection,
mediaDataManager,
- dumpManager);
+ dumpManager,
+ backgroundExecutor);
}
/** */
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 240ae0c..9c1d073 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
@@ -1243,8 +1243,9 @@
if (cmp != 0) return cmp;
cmp = -1 * Long.compare(
- o1.getRepresentativeEntry().getSbn().getNotification().when,
- o2.getRepresentativeEntry().getSbn().getNotification().when);
+ o1.getRepresentativeEntry().getSbn().getNotification().getWhen(),
+ o2.getRepresentativeEntry().getSbn().getNotification().getWhen());
+
return cmp;
};
@@ -1256,8 +1257,8 @@
if (cmp != 0) return cmp;
cmp = -1 * Long.compare(
- o1.getRepresentativeEntry().getSbn().getNotification().when,
- o2.getRepresentativeEntry().getSbn().getNotification().when);
+ o1.getRepresentativeEntry().getSbn().getNotification().getWhen(),
+ o2.getRepresentativeEntry().getSbn().getNotification().getWhen());
return cmp;
};
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 5ce1db2..f253100 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
@@ -89,7 +89,7 @@
var futureTime = Long.MAX_VALUE
groupEntry.children
.asSequence()
- .mapNotNull { child -> child.sbn.notification.`when`.takeIf { it > 0 } }
+ .mapNotNull { child -> child.sbn.notification.getWhen().takeIf { it > 0 } }
.forEach { time ->
val isInThePast = currentTimeMillis - time > 0
if (isInThePast) {
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 fb67f7c..f98f77e 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
@@ -296,7 +296,9 @@
locationLookupByKey: (String) -> GroupLocation,
): NotificationEntry? = postedEntries.asSequence()
.filter { posted -> !posted.entry.sbn.notification.isGroupSummary }
- .sortedBy { posted -> -posted.entry.sbn.notification.`when` }
+ .sortedBy { posted ->
+ -posted.entry.sbn.notification.getWhen()
+ }
.firstOrNull()
?.let { posted ->
posted.entry.takeIf { entry ->
@@ -317,7 +319,7 @@
.filter { locationLookupByKey(it.key) != GroupLocation.Detached }
.sortedWith(compareBy(
{ !mPostedEntries.contains(it.key) },
- { -it.sbn.notification.`when` },
+ { -it.sbn.notification.getWhen() },
))
.firstOrNull()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
index 2fdd2c6..6b5642a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
@@ -35,12 +35,13 @@
// view-model (which, at the time of this writing, does not yet exist).
suspend fun bindColor(view: StatusBarIconView, color: Flow<Int>) {
- // Don't change the icon color if an app icon experiment is enabled.
- if (!android.app.Flags.notificationsUseAppIcon()) {
- color.collectTracingEach("SBIV#bindColor") { color ->
+ color.collectTracingEach("SBIV#bindColor") { color ->
+ // Don't change the icon color if an app icon experiment is enabled.
+ if (!android.app.Flags.notificationsUseAppIcon()) {
view.staticDrawableColor = color
- view.setDecorColor(color)
}
+ // Continue changing the overflow dot color
+ view.setDecorColor(color)
}
}
@@ -57,15 +58,16 @@
iconColors: Flow<NotificationIconColors>,
contrastColorUtil: ContrastColorUtil,
) {
- // Don't change the icon color if an app icon experiment is enabled.
- if (!android.app.Flags.notificationsUseAppIcon()) {
- iconColors.collectTracingEach("SBIV#bindIconColors") { colors ->
+ iconColors.collectTracingEach("SBIV#bindIconColors") { colors ->
+ // Don't change the icon color if an app icon experiment is enabled.
+ if (!android.app.Flags.notificationsUseAppIcon()) {
val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L)
val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil)
view.staticDrawableColor =
if (isColorized) colors.staticDrawableColor(view.viewBounds) else NO_COLOR
- view.setDecorColor(colors.tint)
}
+ // Continue changing the overflow dot color
+ view.setDecorColor(colors.tint)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
index 9619aca..bfc5932 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
@@ -153,12 +153,12 @@
uiEventId = HUN_SUPPRESSED_OLD_WHEN
) {
private fun whenAge(entry: NotificationEntry) =
- systemClock.currentTimeMillis() - entry.sbn.notification.`when`
+ systemClock.currentTimeMillis() - entry.sbn.notification.getWhen()
override fun shouldSuppress(entry: NotificationEntry): Boolean =
when {
// Ignore a "when" of 0, as it is unlikely to be a meaningful timestamp.
- entry.sbn.notification.`when` <= 0L -> false
+ entry.sbn.notification.getWhen() <= 0L -> false
// Assume all HUNs with FSIs, foreground services, or user-initiated jobs are
// time-sensitive, regardless of their "when".
@@ -278,7 +278,7 @@
private fun calculateState(entry: NotificationEntry): State {
if (
entry.ranking.isConversation &&
- entry.sbn.notification.`when` > avalancheProvider.startTime
+ entry.sbn.notification.getWhen() > avalancheProvider.startTime
) {
return State.ALLOW_CONVERSATION_AFTER_AVALANCHE
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index d591114..9c6a423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -623,7 +623,7 @@
return false;
}
- final long when = notification.when;
+ final long when = notification.getWhen();
final long now = mSystemClock.currentTimeMillis();
final long age = now - when;
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 bdeaabf..5e3df7b 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
@@ -2769,7 +2769,7 @@
}
if (!mIsSummaryWithChildren && wasSummary) {
// Reset the 'when' once the row stops being a summary
- mPublicLayout.setNotificationWhen(mEntry.getSbn().getNotification().when);
+ mPublicLayout.setNotificationWhen(mEntry.getSbn().getNotification().getWhen());
}
getShowingLayout().updateBackgroundColor(false /* animate */);
mPrivateLayout.updateExpandButtons(isExpandable());
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 de0f247..57504b2 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
@@ -2399,12 +2399,13 @@
private void updateContentHeight() {
final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
final int shelfIntrinsicHeight = mShelf != null ? mShelf.getIntrinsicHeight() : 0;
+ final int footerIntrinsicHeight = mFooterView != null ? mFooterView.getIntrinsicHeight() : 0;
final float height =
(int) scrimTopPadding + (int) mNotificationStackSizeCalculator.computeHeight(
/* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications,
shelfIntrinsicHeight);
mIntrinsicContentHeight = height;
- mScrollViewFields.sendStackHeight(height);
+ mScrollViewFields.sendStackHeight(height + footerIntrinsicHeight);
// The topPadding can be bigger than the regular padding when qs is expanded, in that
// state the maxPanelHeight and the contentHeight should be bigger
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 37bbbd0..ac4bd09 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
@@ -41,6 +41,7 @@
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
+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.BurnInParameters
@@ -106,6 +107,7 @@
private val notificationStackAppearanceInteractor: NotificationStackAppearanceInteractor,
private val alternateBouncerToGoneTransitionViewModel:
AlternateBouncerToGoneTransitionViewModel,
+ private val aodToGoneTransitionViewModel: AodToGoneTransitionViewModel,
private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
private val aodToOccludedTransitionViewModel: AodToOccludedTransitionViewModel,
private val dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
@@ -464,6 +466,7 @@
val alphaTransitions =
merge(
alternateBouncerToGoneTransitionViewModel.notificationAlpha(viewState),
+ aodToGoneTransitionViewModel.notificationAlpha(viewState),
aodToLockscreenTransitionViewModel.notificationAlpha,
aodToOccludedTransitionViewModel.lockscreenAlpha(viewState),
dozingToLockscreenTransitionViewModel.lockscreenAlpha,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index b2b2cea..7630d43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -855,6 +855,7 @@
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
mBubblesOptional.ifPresent(this::initBubbles);
+ mKeyguardBypassController.listenForQsExpandedChange();
mStatusBarSignalPolicy.init();
mKeyguardIndicationController.init();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ComponentSystemUIDialog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ComponentSystemUIDialog.kt
index f3a4f0e..fe5a02b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ComponentSystemUIDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ComponentSystemUIDialog.kt
@@ -24,7 +24,6 @@
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
-import androidx.annotation.GravityInt
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
@@ -57,7 +56,7 @@
sysUiState: SysUiState,
broadcastDispatcher: BroadcastDispatcher,
dialogTransitionAnimator: DialogTransitionAnimator,
- @GravityInt private val dialogGravity: Int?,
+ delegate: DialogDelegate<SystemUIDialog>,
) :
SystemUIDialog(
context,
@@ -66,7 +65,8 @@
dialogManager,
sysUiState,
broadcastDispatcher,
- dialogTransitionAnimator
+ dialogTransitionAnimator,
+ delegate,
),
LifecycleOwner,
SavedStateRegistryOwner,
@@ -92,7 +92,6 @@
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- dialogGravity?.let { window?.setGravity(it) }
onBackPressedDispatcher.setOnBackInvokedDispatcher(onBackInvokedDispatcher)
savedStateRegistryController.performRestore(savedInstanceState)
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt
index b56baee..25d1f05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt
@@ -45,4 +45,8 @@
/** Called as part of [ViewRootImpl.ConfigChangedCallback.onConfigurationChanged]. */
fun onConfigurationChanged(dialog: T, configuration: Configuration) {}
+
+ fun getWidth(dialog: T): Int = SystemUIDialog.getDefaultDialogWidth(dialog)
+
+ fun getHeight(dialog: T): Int = SystemUIDialog.getDefaultDialogHeight()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index a8941bb..97791ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -21,7 +21,6 @@
import android.content.res.Resources
import android.hardware.biometrics.BiometricSourceType
import android.provider.Settings
-import androidx.annotation.VisibleForTesting
import com.android.app.tracing.ListenersTracing.forEachTraced
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
@@ -32,7 +31,7 @@
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm
@@ -41,23 +40,24 @@
import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.tuner.TunerService
+import dagger.Lazy
+import java.io.PrintWriter
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
-import java.io.PrintWriter
-import javax.inject.Inject
@SysUISingleton
class KeyguardBypassController @Inject constructor(
@Main resources: Resources,
packageManager: PackageManager,
- @Application applicationScope: CoroutineScope,
+ @Application private val applicationScope: CoroutineScope,
tunerService: TunerService,
private val statusBarStateController: StatusBarStateController,
lockscreenUserManager: NotificationLockscreenUserManager,
private val keyguardStateController: KeyguardStateController,
- private val shadeRepository: ShadeRepository,
+ private val shadeInteractorLazy: Lazy<ShadeInteractor>,
devicePostureController: DevicePostureController,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
dumpManager: DumpManager
@@ -144,7 +144,6 @@
}
}
})
- listenForQsExpandedChange(applicationScope)
val dismissByDefault = if (resources.getBoolean(
com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
tunerService.addTunable({ key, _ ->
@@ -159,10 +158,9 @@
}
}
- @VisibleForTesting
- fun listenForQsExpandedChange(scope: CoroutineScope) =
- scope.launch {
- shadeRepository.qsExpansion.map { it > 0f }.distinctUntilChanged()
+ fun listenForQsExpandedChange() =
+ applicationScope.launch {
+ shadeInteractorLazy.get().qsExpansion.map { it > 0f }.distinctUntilChanged()
.collect { isQsExpanded ->
val changed = qsExpanded != isQsExpanded
qsExpanded = isQsExpanded
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
index 68d54e7..6b68511 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
@@ -131,7 +131,12 @@
val runnable = Runnable {
assistManagerLazy.get().hideAssist()
- intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
+ intent.flags =
+ if (intent.flags and Intent.FLAG_ACTIVITY_REORDER_TO_FRONT != 0) {
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ } else {
+ Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
+ }
intent.addFlags(flags)
val result = intArrayOf(ActivityManager.START_CANCELED)
activityTransitionAnimator.startIntentWithAnimation(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 3c68805..3784132 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -549,12 +549,23 @@
try {
final int userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
final int iconResId = mUserManager.getUserStatusBarIconResId(userId);
- // TODO(b/170249807, b/230779281): Handle non-managed-profile String
- String accessibilityString = getManagedProfileAccessibilityString();
mMainExecutor.execute(() -> {
final boolean showIcon;
if (iconResId != Resources.ID_NULL && (!mKeyguardStateController.isShowing()
|| mKeyguardStateController.isOccluded())) {
+ String accessibilityString = "";
+ if (android.os.Flags.allowPrivateProfile()
+ && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
+ try {
+ accessibilityString =
+ mUserManager.getProfileAccessibilityString(userId);
+ } catch (Resources.NotFoundException nfe) {
+ Log.e(TAG, "Accessibility string not found for userId:"
+ + userId);
+ }
+ } else {
+ accessibilityString = getManagedProfileAccessibilityString();
+ }
showIcon = true;
mIconController.setIcon(mSlotManagedProfile,
iconResId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f35d199..7301b87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -72,7 +72,6 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor;
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent;
import com.android.systemui.keyguard.shared.model.DismissAction;
import com.android.systemui.keyguard.shared.model.KeyguardDone;
import com.android.systemui.keyguard.shared.model.KeyguardState;
@@ -800,7 +799,7 @@
public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
boolean afterKeyguardGone, String message) {
- if (RefactorKeyguardDismissIntent.isEnabled()) {
+ if (SceneContainerFlag.isEnabled()) {
if (r == null) {
return;
}
@@ -852,7 +851,7 @@
return;
}
- if (!RefactorKeyguardDismissIntent.isEnabled()) {
+ if (!SceneContainerFlag.isEnabled()) {
mAfterKeyguardGoneAction = r;
mKeyguardGoneCancelAction = cancelAction;
mDismissActionWillAnimateOnKeyguard = r != null
@@ -920,7 +919,7 @@
* Adds a {@param runnable} to be executed after Keyguard is gone.
*/
public void addAfterKeyguardGoneRunnable(Runnable runnable) {
- if (RefactorKeyguardDismissIntent.isEnabled()) {
+ if (SceneContainerFlag.isEnabled()) {
if (runnable != null) {
mKeyguardDismissActionInteractor.get().runAfterKeyguardGone(runnable);
}
@@ -1112,7 +1111,7 @@
// We update the state (which will show the keyguard) only if an animation will run on
// the keyguard. If there is no animation, we wait before updating the state so that we
// go directly from bouncer to launcher/app.
- if (RefactorKeyguardDismissIntent.isEnabled()) {
+ if (SceneContainerFlag.isEnabled()) {
if (mKeyguardDismissActionInteractor.get().runDismissAnimationOnKeyguard()) {
updateStates();
}
@@ -1239,7 +1238,7 @@
}
private void executeAfterKeyguardGoneAction() {
- if (RefactorKeyguardDismissIntent.isEnabled()) {
+ if (SceneContainerFlag.isEnabled()) {
return;
}
if (mAfterKeyguardGoneAction != null) {
@@ -1629,8 +1628,8 @@
pw.println(" isBouncerShowing(): " + isBouncerShowing());
pw.println(" bouncerIsOrWillBeShowing(): " + primaryBouncerIsOrWillBeShowing());
pw.println(" Registered KeyguardViewManagerCallbacks:");
- pw.println(" refactorKeyguardDismissIntent enabled:"
- + RefactorKeyguardDismissIntent.isEnabled());
+ pw.println(" SceneContainerFlag enabled:"
+ + SceneContainerFlag.isEnabled());
for (KeyguardViewManagerCallback callback : mCallbacks) {
pw.println(" " + callback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 2a921dc..c74dde5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -80,7 +80,8 @@
private final Context mContext;
private final DialogDelegate<SystemUIDialog> mDelegate;
- @Nullable private final DismissReceiver mDismissReceiver;
+ @Nullable
+ private final DismissReceiver mDismissReceiver;
private final Handler mHandler = new Handler();
private final SystemUIDialogManager mDialogManager;
private final SysUiState mSysUiState;
@@ -94,7 +95,7 @@
/**
* @deprecated Don't subclass SystemUIDialog. Please subclass {@link Delegate} and pass it to
- * {@link Factory#create(Delegate)} to create a custom dialog.
+ * {@link Factory#create(Delegate)} to create a custom dialog.
*/
@Deprecated
public SystemUIDialog(Context context) {
@@ -137,20 +138,24 @@
mDialogTransitionAnimator = dialogTransitionAnimator;
}
- /** Creates a new instance of {@link SystemUIDialog} with no customized behavior.
+ /**
+ * Creates a new instance of {@link SystemUIDialog} with no customized behavior.
*
* When you just need a dialog, call this.
*/
public SystemUIDialog create() {
- return create(new DialogDelegate<>(){}, mContext, DEFAULT_THEME);
+ return create(new DialogDelegate<>() {
+ }, mContext, DEFAULT_THEME);
}
- /** Creates a new instance of {@link SystemUIDialog} with no customized behavior.
+ /**
+ * Creates a new instance of {@link SystemUIDialog} with no customized behavior.
*
* When you just need a dialog created with a specific {@link Context}, call this.
*/
public SystemUIDialog create(Context context) {
- return create(new DialogDelegate<>(){}, context, DEFAULT_THEME);
+ return create(new DialogDelegate<>() {
+ }, context, DEFAULT_THEME);
}
/**
@@ -162,6 +167,7 @@
public SystemUIDialog create(Delegate delegate, Context context) {
return create(delegate, context, DEFAULT_THEME);
}
+
public SystemUIDialog create(Delegate delegate, Context context, @StyleRes int theme) {
return create((DialogDelegate<SystemUIDialog>) delegate, context, theme);
}
@@ -200,7 +206,8 @@
sysUiState,
broadcastDispatcher,
dialogTransitionAnimator,
- new DialogDelegate<>(){});
+ new DialogDelegate<>() {
+ });
}
public SystemUIDialog(
@@ -305,7 +312,7 @@
* the device configuration changes, and the result will be used to resize this dialog window.
*/
protected int getWidth() {
- return getDefaultDialogWidth(this);
+ return mDelegate.getWidth(this);
}
/**
@@ -313,7 +320,7 @@
* the device configuration changes, and the result will be used to resize this dialog window.
*/
protected int getHeight() {
- return getDefaultDialogHeight();
+ return mDelegate.getHeight(this);
}
@Override
@@ -496,7 +503,7 @@
* <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
* calling this because it causes a leak of BroadcastReceiver.
*
- * @param dialog The dialog to be associated with the listener.
+ * @param dialog The dialog to be associated with the listener.
* @param dismissAction An action to run when the dialog is dismissed.
*/
public static void registerDismissListener(Dialog dialog, @Nullable Runnable dismissAction) {
@@ -519,7 +526,7 @@
dialog.getWindow().setLayout(getDefaultDialogWidth(dialog), getDefaultDialogHeight());
}
- private static int getDefaultDialogWidth(Dialog dialog) {
+ static int getDefaultDialogWidth(Dialog dialog) {
Context context = dialog.getContext();
int flagValue = SystemProperties.getInt(FLAG_TABLET_DIALOG_WIDTH, 0);
if (flagValue == -1) {
@@ -570,12 +577,13 @@
return insets.left + insets.right;
}
- private static int getDefaultDialogHeight() {
+ static int getDefaultDialogHeight() {
return ViewGroup.LayoutParams.WRAP_CONTENT;
}
private static class DismissReceiver extends BroadcastReceiver {
private static final IntentFilter INTENT_FILTER = new IntentFilter();
+
static {
INTENT_FILTER.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt
index 1edd4d1..9ecb212 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone
import android.content.Context
-import androidx.annotation.GravityInt
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Application
@@ -44,14 +43,12 @@
* @param context the [Context] in which the dialog will be constructed.
* @param dismissOnDeviceLock whether the dialog should be automatically dismissed when the
* device is locked (true by default).
- * @param dialogGravity is one of the [android.view.Gravity] and determines dialog position on
- * the screen.
*/
fun create(
context: Context = this.applicationContext,
theme: Int = SystemUIDialog.DEFAULT_THEME,
dismissOnDeviceLock: Boolean = SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK,
- @GravityInt dialogGravity: Int? = null,
+ dialogDelegate: DialogDelegate<SystemUIDialog> = object : DialogDelegate<SystemUIDialog> {},
): ComponentSystemUIDialog {
Assert.isMainThread()
@@ -63,7 +60,7 @@
sysUiState,
broadcastDispatcher,
dialogTransitionAnimator,
- dialogGravity,
+ dialogDelegate,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index a20468f..ec88b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -98,7 +98,7 @@
(entry.sbn.key == callNotificationInfo?.key)) {
val newOngoingCallInfo = CallNotificationInfo(
entry.sbn.key,
- entry.sbn.notification.`when`,
+ entry.sbn.notification.getWhen(),
entry.sbn.notification.contentIntent,
entry.sbn.uid,
entry.sbn.notification.extras.getInt(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
index 4f702d7..d4b2dbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
@@ -102,6 +102,15 @@
)
}
+ fun logOnCarrierRoamingNtnModeChanged(active: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ { bool1 = active },
+ { "onCarrierRoamingNtnModeChanged: $bool1" }
+ )
+ }
+
fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) {
buffer.log(
TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index b3885d2..6803a9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -142,21 +142,33 @@
val callback =
object :
TelephonyCallback(),
- TelephonyCallback.ServiceStateListener,
- TelephonyCallback.SignalStrengthsListener,
- TelephonyCallback.DataConnectionStateListener,
- TelephonyCallback.DataActivityListener,
TelephonyCallback.CarrierNetworkListener,
+ TelephonyCallback.CarrierRoamingNtnModeListener,
+ TelephonyCallback.DataActivityListener,
+ TelephonyCallback.DataConnectionStateListener,
+ TelephonyCallback.DataEnabledListener,
TelephonyCallback.DisplayInfoListener,
- TelephonyCallback.DataEnabledListener {
- override fun onServiceStateChanged(serviceState: ServiceState) {
- logger.logOnServiceStateChanged(serviceState, subId)
- trySend(CallbackEvent.OnServiceStateChanged(serviceState))
+ TelephonyCallback.ServiceStateListener,
+ TelephonyCallback.SignalStrengthsListener {
+
+ override fun onCarrierNetworkChange(active: Boolean) {
+ logger.logOnCarrierNetworkChange(active, subId)
+ trySend(CallbackEvent.OnCarrierNetworkChange(active))
}
- override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
- logger.logOnSignalStrengthsChanged(signalStrength, subId)
- trySend(CallbackEvent.OnSignalStrengthChanged(signalStrength))
+ override fun onCarrierRoamingNtnModeChanged(active: Boolean) {
+ logger.logOnCarrierRoamingNtnModeChanged(active)
+ trySend(CallbackEvent.OnCarrierRoamingNtnModeChanged(active))
+ }
+
+ override fun onDataActivity(direction: Int) {
+ logger.logOnDataActivity(direction, subId)
+ trySend(CallbackEvent.OnDataActivity(direction))
+ }
+
+ override fun onDataEnabledChanged(enabled: Boolean, reason: Int) {
+ logger.logOnDataEnabledChanged(enabled, subId)
+ trySend(CallbackEvent.OnDataEnabledChanged(enabled))
}
override fun onDataConnectionStateChanged(
@@ -167,16 +179,6 @@
trySend(CallbackEvent.OnDataConnectionStateChanged(dataState))
}
- override fun onDataActivity(direction: Int) {
- logger.logOnDataActivity(direction, subId)
- trySend(CallbackEvent.OnDataActivity(direction))
- }
-
- override fun onCarrierNetworkChange(active: Boolean) {
- logger.logOnCarrierNetworkChange(active, subId)
- trySend(CallbackEvent.OnCarrierNetworkChange(active))
- }
-
override fun onDisplayInfoChanged(
telephonyDisplayInfo: TelephonyDisplayInfo
) {
@@ -184,9 +186,14 @@
trySend(CallbackEvent.OnDisplayInfoChanged(telephonyDisplayInfo))
}
- override fun onDataEnabledChanged(enabled: Boolean, reason: Int) {
- logger.logOnDataEnabledChanged(enabled, subId)
- trySend(CallbackEvent.OnDataEnabledChanged(enabled))
+ override fun onServiceStateChanged(serviceState: ServiceState) {
+ logger.logOnServiceStateChanged(serviceState, subId)
+ trySend(CallbackEvent.OnServiceStateChanged(serviceState))
+ }
+
+ override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
+ logger.logOnSignalStrengthsChanged(signalStrength, subId)
+ trySend(CallbackEvent.OnSignalStrengthChanged(signalStrength))
}
}
telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
@@ -229,8 +236,8 @@
override val isNonTerrestrial =
callbackEvents
- .mapNotNull { it.onServiceStateChanged }
- .map { it.serviceState.isUsingNonTerrestrialNetwork }
+ .mapNotNull { it.onCarrierRoamingNtnModeChanged }
+ .map { it.active }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val isGsm =
@@ -502,6 +509,8 @@
sealed interface CallbackEvent {
data class OnCarrierNetworkChange(val active: Boolean) : CallbackEvent
+ data class OnCarrierRoamingNtnModeChanged(val active: Boolean) : CallbackEvent
+
data class OnDataActivity(val direction: Int) : CallbackEvent
data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent
@@ -522,6 +531,7 @@
data class TelephonyCallbackState(
val onDataActivity: CallbackEvent.OnDataActivity? = null,
val onCarrierNetworkChange: CallbackEvent.OnCarrierNetworkChange? = null,
+ val onCarrierRoamingNtnModeChanged: CallbackEvent.OnCarrierRoamingNtnModeChanged? = null,
val onDataConnectionStateChanged: CallbackEvent.OnDataConnectionStateChanged? = null,
val onDataEnabledChanged: CallbackEvent.OnDataEnabledChanged? = null,
val onDisplayInfoChanged: CallbackEvent.OnDisplayInfoChanged? = null,
@@ -531,6 +541,9 @@
fun applyEvent(event: CallbackEvent): TelephonyCallbackState {
return when (event) {
is CallbackEvent.OnCarrierNetworkChange -> copy(onCarrierNetworkChange = event)
+ is CallbackEvent.OnCarrierRoamingNtnModeChanged -> {
+ copy(onCarrierRoamingNtnModeChanged = event)
+ }
is CallbackEvent.OnDataActivity -> copy(onDataActivity = event)
is CallbackEvent.OnDataConnectionStateChanged ->
copy(onDataConnectionStateChanged = event)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
index f2255f3..332c121 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
@@ -126,10 +126,9 @@
) { shouldShow, connectionState ->
if (shouldShow) {
when (connectionState) {
+ SatelliteConnectionState.On,
SatelliteConnectionState.Connected ->
context.getString(R.string.satellite_connected_carrier_text)
- SatelliteConnectionState.On ->
- context.getString(R.string.satellite_not_connected_carrier_text)
SatelliteConnectionState.Off,
SatelliteConnectionState.Unknown -> null
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
index db4e605d..08f973b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
@@ -88,6 +88,7 @@
const val WORK_MODE_TILE_SPEC = "work"
const val CAMERA_TOGGLE_TILE_SPEC = "cameratoggle"
const val MIC_TOGGLE_TILE_SPEC = "mictoggle"
+ const val DND_TILE_SPEC = "dnd"
/** Inject flashlight config */
@Provides
@@ -136,10 +137,7 @@
instanceId = uiEventLogger.getNewInstanceId(),
policy =
QSTilePolicy.Restricted(
- listOf(
- DISALLOW_SHARE_LOCATION,
- DISALLOW_CONFIG_LOCATION
- )
+ listOf(DISALLOW_SHARE_LOCATION, DISALLOW_CONFIG_LOCATION)
)
)
@@ -321,6 +319,21 @@
stateInteractor.create(MICROPHONE),
mapper.create(SensorPrivacyTileResources.MicrophonePrivacyTileResources),
)
+
+ /** Inject microphone toggle config */
+ @Provides
+ @IntoMap
+ @StringKey(DND_TILE_SPEC)
+ fun provideDndTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+ QSTileConfig(
+ tileSpec = TileSpec.create(DND_TILE_SPEC),
+ uiConfig =
+ QSTileUIConfig.Resource(
+ iconRes = R.drawable.qs_dnd_icon_off,
+ labelRes = R.string.quick_settings_dnd_label,
+ ),
+ instanceId = uiEventLogger.getNewInstanceId(),
+ )
}
/** Inject FlashlightTile into tileMap in QSModule */
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt
index 1e65566..b3ea9dc 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt
@@ -6,8 +6,8 @@
import android.os.Vibrator
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.updates.FoldProvider
-import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -18,6 +18,7 @@
constructor(
unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider,
foldProvider: FoldProvider,
+ transitionConfig: UnfoldTransitionConfig,
@Main private val mainExecutor: Executor,
private val vibrator: Vibrator?
) : TransitionProgressListener {
@@ -27,22 +28,17 @@
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK)
init {
- if (vibrator != null) {
+ if (vibrator != null && transitionConfig.isHapticsEnabled) {
// We don't need to remove the callback because we should listen to it
// the whole time when SystemUI process is alive
unfoldTransitionProgressProvider.addCallback(this)
- }
- foldProvider.registerCallback(
- object : FoldCallback {
- override fun onFoldUpdated(isFolded: Boolean) {
- if (isFolded) {
- isFirstAnimationAfterUnfold = true
- }
+ foldProvider.registerCallback({ isFolded ->
+ if (isFolded) {
+ isFirstAnimationAfterUnfold = true
}
- },
- mainExecutor
- )
+ }, mainExecutor)
+ }
}
private var lastTransitionProgress = TRANSITION_PROGRESS_FULL_OPEN
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt
index 382bc03..9339651 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt
@@ -76,6 +76,7 @@
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
@@ -164,81 +165,87 @@
val actions: Flow<List<UserActionModel>>
get() =
combine(
- repository.selectedUserInfo,
- userInfos,
- repository.userSwitcherSettings,
- keyguardInteractor.isKeyguardShowing,
- ) { _, userInfos, settings, isDeviceLocked ->
- buildList {
- val canAccessUserSwitcher = !isDeviceLocked || settings.isAddUsersFromLockscreen
- if (canAccessUserSwitcher) {
- // The device is locked and our setting to allow actions that add users
- // from the lock-screen is not enabled. We can finish building the list
- // here.
- val isFullScreen = featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)
+ repository.selectedUserInfo,
+ userInfos,
+ repository.userSwitcherSettings,
+ keyguardInteractor.isKeyguardShowing,
+ ) { _, userInfos, settings, isDeviceLocked ->
+ buildList {
+ val canAccessUserSwitcher =
+ !isDeviceLocked || settings.isAddUsersFromLockscreen
+ if (canAccessUserSwitcher) {
+ // The device is locked and our setting to allow actions that add users
+ // from the lock-screen is not enabled. We can finish building the list
+ // here.
+ val isFullScreen =
+ featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)
- val actionList: List<UserActionModel> =
- if (isFullScreen) {
- listOf(
- UserActionModel.ADD_USER,
- UserActionModel.ADD_SUPERVISED_USER,
- UserActionModel.ENTER_GUEST_MODE,
- )
- } else {
- listOf(
- UserActionModel.ENTER_GUEST_MODE,
- UserActionModel.ADD_USER,
- UserActionModel.ADD_SUPERVISED_USER,
- )
- }
- actionList.map {
- when (it) {
- UserActionModel.ENTER_GUEST_MODE -> {
- val hasGuestUser = userInfos.any { it.isGuest }
- if (
- !hasGuestUser &&
- canCreateGuestUser(settings, canAccessUserSwitcher)
- ) {
- add(UserActionModel.ENTER_GUEST_MODE)
- }
+ val actionList: List<UserActionModel> =
+ if (isFullScreen) {
+ listOf(
+ UserActionModel.ADD_USER,
+ UserActionModel.ADD_SUPERVISED_USER,
+ UserActionModel.ENTER_GUEST_MODE,
+ )
+ } else {
+ listOf(
+ UserActionModel.ENTER_GUEST_MODE,
+ UserActionModel.ADD_USER,
+ UserActionModel.ADD_SUPERVISED_USER,
+ )
}
- UserActionModel.ADD_USER -> {
- val canCreateUsers =
- UserActionsUtil.canCreateUser(
- manager,
- repository,
- settings.isUserSwitcherEnabled,
- canAccessUserSwitcher
- )
+ actionList.map {
+ when (it) {
+ UserActionModel.ENTER_GUEST_MODE -> {
+ val hasGuestUser = userInfos.any { it.isGuest }
+ if (
+ !hasGuestUser &&
+ canCreateGuestUser(settings, canAccessUserSwitcher)
+ ) {
+ add(UserActionModel.ENTER_GUEST_MODE)
+ }
+ }
+ UserActionModel.ADD_USER -> {
+ val canCreateUsers =
+ UserActionsUtil.canCreateUser(
+ manager,
+ repository,
+ settings.isUserSwitcherEnabled,
+ canAccessUserSwitcher
+ )
- if (canCreateUsers) {
- add(UserActionModel.ADD_USER)
+ if (canCreateUsers) {
+ add(UserActionModel.ADD_USER)
+ }
}
- }
- UserActionModel.ADD_SUPERVISED_USER -> {
- if (
- UserActionsUtil.canCreateSupervisedUser(
- manager,
- repository,
- settings.isUserSwitcherEnabled,
- canAccessUserSwitcher,
- supervisedUserPackageName,
- )
- ) {
- add(UserActionModel.ADD_SUPERVISED_USER)
+ UserActionModel.ADD_SUPERVISED_USER -> {
+ if (
+ UserActionsUtil.canCreateSupervisedUser(
+ manager,
+ repository,
+ settings.isUserSwitcherEnabled,
+ canAccessUserSwitcher,
+ supervisedUserPackageName,
+ )
+ ) {
+ add(UserActionModel.ADD_SUPERVISED_USER)
+ }
}
+ else -> Unit
}
- else -> Unit
}
}
- }
- if (
- UserActionsUtil.canManageUsers(repository, settings.isUserSwitcherEnabled)
- ) {
- add(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
+ if (
+ UserActionsUtil.canManageUsers(
+ repository,
+ settings.isUserSwitcherEnabled
+ )
+ ) {
+ add(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
+ }
}
}
- }
+ .flowOn(backgroundDispatcher)
val userRecords: StateFlow<ArrayList<UserRecord>> =
combine(
diff --git a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
index 0dcbe9b2..229bdce 100644
--- a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
@@ -26,8 +26,9 @@
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.WorkerThread;
-import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.util.annotations.WeaklyReferencedCallback;
@@ -118,7 +119,7 @@
private final Intent mServiceIntent;
private final UserTracker mUserTracker;
private final int mFlags;
- private final Executor mExecutor;
+ private final Executor mBgExecutor;
private final ServiceTransformer<T> mTransformer;
private final ArrayList<WeakReference<Callback<T>>> mCallbacks;
private Optional<Integer> mLastDisconnectReason;
@@ -130,30 +131,34 @@
* Default constructor for {@link ObservableServiceConnection}.
* @param context The context from which the service will be bound with.
* @param serviceIntent The intent to bind service with.
- * @param executor The executor for connection callbacks to be delivered on
+ * @param bgExecutor The executor for connection callbacks to be delivered on
* @param transformer A {@link ServiceTransformer} for transforming the resulting service
* into a desired type.
*/
@Inject
public ObservableServiceConnection(Context context, Intent serviceIntent,
UserTracker userTracker,
- @Main Executor executor,
+ @Background Executor bgExecutor,
ServiceTransformer<T> transformer) {
mContext = context;
mServiceIntent = serviceIntent;
mUserTracker = userTracker;
mFlags = Context.BIND_AUTO_CREATE;
- mExecutor = executor;
+ mBgExecutor = bgExecutor;
mTransformer = transformer;
mCallbacks = new ArrayList<>();
mLastDisconnectReason = Optional.empty();
}
/**
- * Initiate binding to the service.
- * @return {@code true} if initiating binding succeed, {@code false} otherwise.
+ * Initiate binding to the service in the background.
*/
- public boolean bind() {
+ public void bind() {
+ mBgExecutor.execute(this::bindInternal);
+ }
+
+ @WorkerThread
+ private void bindInternal() {
boolean bindResult = false;
try {
bindResult = mContext.bindServiceAsUser(mServiceIntent, this, mFlags,
@@ -166,18 +171,17 @@
if (DEBUG) {
Log.d(TAG, "bind. bound:" + bindResult);
}
- return bindResult;
}
/**
* Disconnect from the service if bound.
*/
public void unbind() {
- onDisconnected(DISCONNECT_REASON_UNBIND);
+ mBgExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_UNBIND));
}
/**
- * Adds a callback for receiving connection updates.
+ * Adds a callback for receiving connection updates. The callback is executed in the background.
* @param callback The {@link Callback} to receive future updates.
*/
public void addCallback(Callback<T> callback) {
@@ -185,7 +189,7 @@
Log.d(TAG, "addCallback:" + callback);
}
- mExecutor.execute(() -> {
+ mBgExecutor.execute(() -> {
final Iterator<WeakReference<Callback<T>>> iterator = mCallbacks.iterator();
while (iterator.hasNext()) {
@@ -210,14 +214,15 @@
* Removes previously added callback from receiving future connection updates.
* @param callback The {@link Callback} to be removed.
*/
- public void removeCallback(Callback callback) {
+ public void removeCallback(Callback<T> callback) {
if (DEBUG) {
Log.d(TAG, "removeCallback:" + callback);
}
- mExecutor.execute(() -> mCallbacks.removeIf(el-> el.get() == callback));
+ mBgExecutor.execute(() -> mCallbacks.removeIf(el-> el.get() == callback));
}
+ @WorkerThread
private void onDisconnected(@DisconnectReason int reason) {
if (DEBUG) {
Log.d(TAG, "onDisconnected:" + reason);
@@ -240,7 +245,7 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- mExecutor.execute(() -> {
+ mBgExecutor.execute(() -> {
if (DEBUG) {
Log.d(TAG, "onServiceConnected");
}
@@ -268,7 +273,7 @@
final Iterator<WeakReference<Callback<T>>> iterator = mCallbacks.iterator();
while (iterator.hasNext()) {
- final Callback cb = iterator.next().get();
+ final Callback<T> cb = iterator.next().get();
if (cb != null) {
applicator.accept(cb);
} else {
@@ -279,16 +284,16 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- mExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_DISCONNECTED));
+ mBgExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_DISCONNECTED));
}
@Override
public void onBindingDied(ComponentName name) {
- mExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_BINDING_DIED));
+ mBgExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_BINDING_DIED));
}
@Override
public void onNullBinding(ComponentName name) {
- mExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_NULL_BINDING));
+ mBgExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_NULL_BINDING));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java b/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java
index 5979f3e..64f8246 100644
--- a/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/util/service/PersistentConnectionManager.java
@@ -48,7 +48,7 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final SystemClock mSystemClock;
- private final DelayableExecutor mMainExecutor;
+ private final DelayableExecutor mBgExecutor;
private final int mBaseReconnectDelayMs;
private final int mMaxReconnectAttempts;
private final int mMinConnectionDuration;
@@ -71,8 +71,8 @@
private final Observer.Callback mObserverCallback = () -> initiateConnectionAttempt();
- private final ObservableServiceConnection.Callback mConnectionCallback =
- new ObservableServiceConnection.Callback() {
+ private final ObservableServiceConnection.Callback<T> mConnectionCallback =
+ new ObservableServiceConnection.Callback<>() {
private long mStartTime;
@Override
@@ -95,12 +95,10 @@
}
};
- // TODO: b/326449074 - Ensure the DelayableExecutor is on the correct thread, and update the
- // qualifier (to @Main) or name (to bgExecutor) to be consistent with that.
@Inject
public PersistentConnectionManager(
SystemClock clock,
- @Background DelayableExecutor mainExecutor,
+ @Background DelayableExecutor bgExecutor,
DumpManager dumpManager,
@Named(DUMPSYS_NAME) String dumpsysName,
@Named(SERVICE_CONNECTION) ObservableServiceConnection<T> serviceConnection,
@@ -109,7 +107,7 @@
@Named(MIN_CONNECTION_DURATION_MS) int minConnectionDurationMs,
@Named(OBSERVER) Observer observer) {
mSystemClock = clock;
- mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
mConnection = serviceConnection;
mObserver = observer;
mDumpManager = dumpManager;
@@ -195,7 +193,7 @@
"scheduling connection attempt in " + reconnectDelayMs + "milliseconds");
}
- mCurrentReconnectCancelable = mMainExecutor.executeDelayed(mConnectRunnable,
+ mCurrentReconnectCancelable = mBgExecutor.executeDelayed(mConnectRunnable,
reconnectDelayMs);
mReconnectAttempts++;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
index f11d5d1..0968bde 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
@@ -21,26 +21,29 @@
import android.content.Intent
import android.provider.Settings
import android.text.TextUtils
-import android.util.Log
+import com.android.systemui.volume.domain.interactor.VolumePanelNavigationInteractor
+import com.android.systemui.volume.ui.navigation.VolumeNavigator
import javax.inject.Inject
-private const val TAG = "VolumePanelDialogReceiver"
-private const val LAUNCH_ACTION = "com.android.systemui.action.LAUNCH_VOLUME_PANEL_DIALOG"
-private const val DISMISS_ACTION = "com.android.systemui.action.DISMISS_VOLUME_PANEL_DIALOG"
-
-/**
- * BroadcastReceiver for handling volume panel dialog intent
- */
-class VolumePanelDialogReceiver @Inject constructor(
- private val volumePanelFactory: VolumePanelFactory
+/** [BroadcastReceiver] for handling volume panel dialog intent */
+class VolumePanelDialogReceiver
+@Inject
+constructor(
+ private val volumeNavigator: VolumeNavigator,
+ private val volumePanelNavigationInteractor: VolumePanelNavigationInteractor,
) : BroadcastReceiver() {
+
override fun onReceive(context: Context, intent: Intent) {
- Log.d(TAG, "onReceive intent" + intent.action)
- if (TextUtils.equals(LAUNCH_ACTION, intent.action) ||
- TextUtils.equals(Settings.Panel.ACTION_VOLUME, intent.action)) {
- volumePanelFactory.create(true, null)
- } else if (TextUtils.equals(DISMISS_ACTION, intent.action)) {
- volumePanelFactory.dismiss()
+ if (
+ TextUtils.equals(LAUNCH_ACTION, intent.action) ||
+ TextUtils.equals(Settings.Panel.ACTION_VOLUME, intent.action)
+ ) {
+ volumeNavigator.openVolumePanel(volumePanelNavigationInteractor.getVolumePanelRoute())
}
}
+
+ companion object {
+ const val LAUNCH_ACTION = "com.android.systemui.action.LAUNCH_VOLUME_PANEL_DIALOG"
+ const val DISMISS_ACTION = "com.android.systemui.action.DISMISS_VOLUME_PANEL_DIALOG"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
index 1f87ec8..dc1e8cf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
@@ -16,7 +16,7 @@
package com.android.systemui.volume.dagger;
-import android.app.Activity;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.media.AudioManager;
import android.os.Looper;
@@ -38,11 +38,11 @@
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.volume.VolumeDialogComponent;
import com.android.systemui.volume.VolumeDialogImpl;
+import com.android.systemui.volume.VolumePanelDialogReceiver;
import com.android.systemui.volume.VolumeUI;
import com.android.systemui.volume.domain.interactor.VolumePanelNavigationInteractor;
import com.android.systemui.volume.panel.dagger.VolumePanelComponent;
import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory;
-import com.android.systemui.volume.panel.ui.activity.VolumePanelActivity;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;
import dagger.Binds;
@@ -67,6 +67,15 @@
}
)
public interface VolumeModule {
+
+ /**
+ * Binds [VolumePanelDialogReceiver]
+ */
+ @Binds
+ @IntoMap
+ @ClassKey(VolumePanelDialogReceiver.class)
+ BroadcastReceiver bindVolumePanelDialogReceiver(VolumePanelDialogReceiver receiver);
+
/** Starts VolumeUI. */
@Binds
@IntoMap
@@ -82,12 +91,6 @@
@Binds
VolumeComponent provideVolumeComponent(VolumeDialogComponent volumeDialogComponent);
- /** Inject into VolumePanelActivity. */
- @Binds
- @IntoMap
- @ClassKey(VolumePanelActivity.class)
- Activity bindVolumePanelActivity(VolumePanelActivity activity);
-
/** */
@Binds
VolumePanelComponentFactory bindVolumePanelComponentFactory(VolumePanelComponent.Factory impl);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
index ed44699..19d9c3f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
@@ -32,6 +32,7 @@
import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
@@ -69,6 +70,7 @@
}
} else {
mediaOutputInteractor.defaultActiveMediaSession
+ .filterData()
.flatMapLatest {
localMediaRepositoryFactory
.create(it?.packageName)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt
deleted file mode 100644
index bac7d15..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.mediaoutput.domain
-
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
-import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
-import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-
-/** Determines if the Media Output Volume Panel component is available. */
-@VolumePanelScope
-class MediaOutputAvailabilityCriteria
-@Inject
-constructor(
- private val audioModeInteractor: AudioModeInteractor,
-) : ComponentAvailabilityCriteria {
-
- override fun isAvailable(): Flow<Boolean> = audioModeInteractor.isOngoingCall.map { !it }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index 83b8029..b974f90 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -28,6 +28,9 @@
import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaDeviceSessions
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.panel.shared.model.filterData
+import com.android.systemui.volume.panel.shared.model.wrapInResult
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
@@ -72,7 +75,7 @@
}
/** Returns the default [MediaDeviceSession] from [activeMediaDeviceSessions] */
- val defaultActiveMediaSession: StateFlow<MediaDeviceSession?> =
+ val defaultActiveMediaSession: StateFlow<Result<MediaDeviceSession?>> =
activeMediaControllers
.map {
when {
@@ -82,11 +85,13 @@
else -> null
}
}
+ .wrapInResult()
.flowOn(backgroundCoroutineContext)
- .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+ .stateIn(coroutineScope, SharingStarted.Eagerly, Result.Loading())
private val localMediaRepository: SharedFlow<LocalMediaRepository> =
defaultActiveMediaSession
+ .filterData()
.map { it?.packageName }
.distinctUntilChanged()
.map { localMediaRepositoryFactory.create(it) }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
index d60d981..192e0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
@@ -18,16 +18,21 @@
import android.content.Context
import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Color
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.res.R
+import com.android.systemui.volume.domain.interactor.AudioOutputInteractor
+import com.android.systemui.volume.domain.model.AudioOutputDevice
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.panel.shared.model.filterData
+import com.android.systemui.volume.panel.shared.model.wrapInResult
import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -35,6 +40,7 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapNotNull
@@ -50,25 +56,25 @@
@VolumePanelScope private val coroutineScope: CoroutineScope,
private val actionsInteractor: MediaOutputActionsInteractor,
private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
+ audioOutputInteractor: AudioOutputInteractor,
+ audioModeInteractor: AudioModeInteractor,
interactor: MediaOutputInteractor,
private val uiEventLogger: UiEventLogger,
) {
private val sessionWithPlaybackState: StateFlow<Result<SessionWithPlaybackState?>> =
interactor.defaultActiveMediaSession
+ .filterData()
.flatMapLatest { session ->
if (session == null) {
- flowOf(Result.Data<SessionWithPlaybackState?>(null))
+ flowOf(null)
} else {
mediaDeviceSessionInteractor.playbackState(session).mapNotNull { playback ->
- playback?.let {
- Result.Data<SessionWithPlaybackState?>(
- SessionWithPlaybackState(session, playback.isActive())
- )
- }
+ playback?.let { SessionWithPlaybackState(session, playback.isActive) }
}
}
}
+ .wrapInResult()
.stateIn(
coroutineScope,
SharingStarted.Eagerly,
@@ -76,23 +82,24 @@
)
val connectedDeviceViewModel: StateFlow<ConnectedDeviceViewModel?> =
- combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
- mediaDeviceSession,
- currentConnectedDevice ->
- if (mediaDeviceSession !is Result.Data) {
- return@combine null
- }
- ConnectedDeviceViewModel(
- if (mediaDeviceSession.data?.isPlaybackActive == true) {
- context.getString(
- R.string.media_output_label_title,
- mediaDeviceSession.data.session.appLabel
- )
- } else {
- context.getString(R.string.media_output_title_without_playing)
- },
- currentConnectedDevice?.name,
- )
+ combine(
+ sessionWithPlaybackState.filterData(),
+ audioModeInteractor.isOngoingCall,
+ audioOutputInteractor.currentAudioDevice.filter {
+ it !is AudioOutputDevice.Unknown
+ },
+ ) { mediaDeviceSession, isOngoingCall, currentConnectedDevice ->
+ val label =
+ when {
+ isOngoingCall -> context.getString(R.string.media_output_title_ongoing_call)
+ mediaDeviceSession?.isPlaybackActive == true ->
+ context.getString(
+ R.string.media_output_label_title,
+ mediaDeviceSession.session.appLabel
+ )
+ else -> context.getString(R.string.media_output_title_without_playing)
+ }
+ ConnectedDeviceViewModel(label, currentConnectedDevice.name)
}
.stateIn(
coroutineScope,
@@ -101,16 +108,16 @@
)
val deviceIconViewModel: StateFlow<DeviceIconViewModel?> =
- combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
+ combine(sessionWithPlaybackState.filterData(), audioOutputInteractor.currentAudioDevice) {
mediaDeviceSession,
currentConnectedDevice ->
- if (mediaDeviceSession !is Result.Data) {
- return@combine null
- }
val icon: Icon =
- currentConnectedDevice?.icon?.let { Icon.Loaded(it, null) }
+ currentConnectedDevice
+ .takeIf { currentConnectedDevice !is AudioOutputDevice.Unknown }
+ ?.icon
+ ?.let { Icon.Loaded(it, null) }
?: Icon.Resource(R.drawable.ic_media_home_devices, null)
- if (mediaDeviceSession.data?.isPlaybackActive == true) {
+ if (mediaDeviceSession?.isPlaybackActive == true) {
DeviceIconViewModel.IsPlaying(
icon = icon,
iconColor =
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
index ac8092c..fa40059 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
@@ -25,6 +25,7 @@
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession
import com.android.systemui.volume.panel.component.volume.domain.model.SliderType
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
@@ -46,7 +47,7 @@
val volumePanelSliders: StateFlow<List<SliderType>> =
combineTransform(
mediaOutputInteractor.activeMediaDeviceSessions,
- mediaOutputInteractor.defaultActiveMediaSession,
+ mediaOutputInteractor.defaultActiveMediaSession.filterData(),
audioRepository.communicationDevice,
) { activeSessions, defaultSession, communicationDevice ->
coroutineScope {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
index ee642a6..0386338 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
@@ -18,6 +18,7 @@
import android.content.Context
import android.media.AudioManager
+import android.util.Log
import com.android.internal.logging.UiEventLogger
import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor
import com.android.settingslib.volume.shared.model.AudioStream
@@ -144,6 +145,7 @@
if (isMutedOrNoVolume) {
when (audioStream.value) {
AudioManager.STREAM_MUSIC -> R.drawable.ic_volume_off
+ AudioManager.STREAM_BLUETOOTH_SCO -> R.drawable.ic_volume_off
AudioManager.STREAM_VOICE_CALL -> R.drawable.ic_volume_off
AudioManager.STREAM_RING ->
if (ringerMode.value == AudioManager.RINGER_MODE_VIBRATE) {
@@ -158,12 +160,18 @@
R.drawable.ic_volume_off
}
AudioManager.STREAM_ALARM -> R.drawable.ic_volume_off
- else -> null
+ else -> {
+ Log.wtf(TAG, "No icon for the stream: $audioStream")
+ R.drawable.ic_volume_off
+ }
}
} else {
iconsByStream[audioStream]
+ ?: run {
+ Log.wtf(TAG, "No icon for the stream: $audioStream")
+ R.drawable.ic_music_note
+ }
}
- ?: error("No icon for the stream: $audioStream")
return Icon.Resource(iconRes, null)
}
@@ -196,4 +204,8 @@
* when using [AudioStream] directly because it expects another type.
*/
class FactoryAudioStreamWrapper(val audioStream: AudioStream)
+
+ private companion object {
+ const val TAG = "AudioStreamSliderViewModel"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
index 741f5cf..26d6a9a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
@@ -26,6 +26,7 @@
import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel
import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -80,9 +81,13 @@
val isExpanded: StateFlow<Boolean> =
merge(
mutableIsExpanded,
- mediaOutputInteractor.defaultActiveMediaSession.flatMapLatest {
- if (it == null) flowOf(true)
- else mediaDeviceSessionInteractor.playbackState(it).map { it?.isActive != true }
+ mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session
+ ->
+ if (session == null) flowOf(true)
+ else
+ mediaDeviceSessionInteractor.playbackState(session).map {
+ it?.isActive != true
+ }
},
)
.stateIn(scope, SharingStarted.Eagerly, false)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/CoroutineModule.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/CoroutineModule.kt
deleted file mode 100644
index 3ce0bac..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/CoroutineModule.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.dagger
-
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
-import dagger.Module
-import dagger.Provides
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.SupervisorJob
-
-/** Provides Volume Panel coroutine tools. */
-@Module
-interface CoroutineModule {
-
- companion object {
-
- /**
- * Provides a coroutine scope to use inside [VolumePanelScope].
- * [com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel] manages the
- * lifecycle of this scope. It's cancelled when the View Model is destroyed. This helps to
- * free occupied resources when volume panel is not shown.
- */
- @VolumePanelScope
- @Provides
- fun provideCoroutineScope(@Application applicationScope: CoroutineScope): CoroutineScope =
- CoroutineScope(applicationScope.coroutineContext + SupervisorJob())
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
index ec64f3d9..30d865b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
@@ -45,7 +45,6 @@
modules =
[
// Volume Panel infra modules
- CoroutineModule::class,
DefaultMultibindsModule::class,
DomainModule::class,
UiModule::class,
@@ -61,6 +60,12 @@
)
interface VolumePanelComponent {
+ /**
+ * Provides a coroutine scope to use inside [VolumePanelScope].
+ * [com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel] manages the lifecycle
+ * of this scope. It's cancelled when the View Model is destroyed. This helps to free occupied
+ * resources when volume panel is not shown.
+ */
fun coroutineScope(): CoroutineScope
fun componentsInteractor(): ComponentsInteractor
@@ -74,6 +79,9 @@
@Subcomponent.Factory
interface Factory : VolumePanelComponentFactory {
- override fun create(@BindsInstance viewModel: VolumePanelViewModel): VolumePanelComponent
+ override fun create(
+ @BindsInstance viewModel: VolumePanelViewModel,
+ @BindsInstance scope: CoroutineScope,
+ ): VolumePanelComponent
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/factory/VolumePanelComponentFactory.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/factory/VolumePanelComponentFactory.kt
index e470c3f..5c36b01 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/factory/VolumePanelComponentFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/factory/VolumePanelComponentFactory.kt
@@ -19,6 +19,7 @@
import com.android.systemui.volume.panel.dagger.VolumePanelComponent
import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
import dagger.BindsInstance
+import kotlinx.coroutines.CoroutineScope
/**
* Common interface for all [dagger.Subcomponent.Factory] providing [VolumePanelComponent].
@@ -26,5 +27,8 @@
*/
interface VolumePanelComponentFactory {
- fun create(@BindsInstance viewModel: VolumePanelViewModel): VolumePanelComponent
+ fun create(
+ @BindsInstance viewModel: VolumePanelViewModel,
+ @BindsInstance scope: CoroutineScope,
+ ): VolumePanelComponent
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
index 8793538..5daed99 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
@@ -16,6 +16,10 @@
package com.android.systemui.volume.panel.shared.model
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
+
/** Models a loadable result */
sealed interface Result<T> {
@@ -25,3 +29,9 @@
/** The data is loaded successfully */
data class Data<T>(val data: T) : Result<T>
}
+
+/** Wraps flow into [Result]. */
+fun <T> Flow<T>.wrapInResult(): Flow<Result<T>> = map { Result.Data(it) }
+
+/** Filters only [Result.Data] from the flow. */
+fun <T> Flow<Result<T>>.filterData(): Flow<T> = mapNotNull { it as? Result.Data<T> }.map { it.data }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
deleted file mode 100644
index ccb91ac..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.ui.activity
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.activity.enableEdgeToEdge
-import androidx.activity.viewModels
-import com.android.internal.logging.UiEventLogger
-import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag
-import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
-import com.android.systemui.volume.panel.ui.composable.VolumePanelRoot
-import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
-import javax.inject.Inject
-import javax.inject.Provider
-
-class VolumePanelActivity
-@Inject
-constructor(
- private val volumePanelViewModelFactory: Provider<VolumePanelViewModel.Factory>,
- private val volumePanelFlag: VolumePanelFlag,
- private val configurationController: ConfigurationController,
- private val uiEventLogger: UiEventLogger,
-) : ComponentActivity() {
-
- private val viewModel: VolumePanelViewModel by
- viewModels(factoryProducer = { volumePanelViewModelFactory.get() })
-
- override fun onCreate(savedInstanceState: Bundle?) {
- enableEdgeToEdge()
- super.onCreate(savedInstanceState)
- volumePanelFlag.assertNewVolumePanel()
- uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_SHOWN)
- setContent {
- VolumePanelRoot(
- viewModel = viewModel,
- onDismiss = {
- uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_GONE)
- finish()
- }
- )
- }
- }
-
- override fun onContentChanged() {
- super.onContentChanged()
- configurationController.onConfigurationChanged(resources.configuration)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
index 1de4fd1..a30de1b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
@@ -17,13 +17,14 @@
package com.android.systemui.volume.panel.ui.viewmodel
import android.content.Context
+import android.content.IntentFilter
import android.content.res.Resources
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.ViewModelProvider
+import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.onConfigChanged
+import com.android.systemui.volume.VolumePanelDialogReceiver
import com.android.systemui.volume.panel.dagger.VolumePanelComponent
import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory
import com.android.systemui.volume.panel.domain.VolumePanelStartable
@@ -33,25 +34,31 @@
import com.android.systemui.volume.panel.ui.layout.ComponentsLayoutManager
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
+// Can't inject a constructor here because VolumePanelComponent provides this view model for its
+// components.
class VolumePanelViewModel(
resources: Resources,
+ coroutineScope: CoroutineScope,
daggerComponentFactory: VolumePanelComponentFactory,
configurationController: ConfigurationController,
-) : ViewModel() {
+ broadcastDispatcher: BroadcastDispatcher,
+) {
- private val volumePanelComponent: VolumePanelComponent = daggerComponentFactory.create(this)
+ private val volumePanelComponent: VolumePanelComponent =
+ daggerComponentFactory.create(this, coroutineScope)
private val scope: CoroutineScope
get() = volumePanelComponent.coroutineScope()
@@ -112,34 +119,33 @@
init {
volumePanelComponent.volumePanelStartables().onEach(VolumePanelStartable::start)
+ broadcastDispatcher
+ .broadcastFlow(IntentFilter(VolumePanelDialogReceiver.DISMISS_ACTION))
+ .onEach { dismissPanel() }
+ .launchIn(scope)
}
fun dismissPanel() {
mutablePanelVisibility.update { false }
}
- override fun onCleared() {
- scope.cancel()
- super.onCleared()
- }
-
class Factory
@Inject
constructor(
@Application private val context: Context,
private val daggerComponentFactory: VolumePanelComponentFactory,
private val configurationController: ConfigurationController,
- ) : ViewModelProvider.Factory {
+ private val broadcastDispatcher: BroadcastDispatcher,
+ ) {
- @Suppress("UNCHECKED_CAST")
- override fun <T : ViewModel> create(modelClass: Class<T>): T {
- check(modelClass == VolumePanelViewModel::class.java)
+ fun create(coroutineScope: CoroutineScope): VolumePanelViewModel {
return VolumePanelViewModel(
context.resources,
+ coroutineScope,
daggerComponentFactory,
configurationController,
+ broadcastDispatcher
)
- as T
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt b/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
index 790638c..eae33af 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
@@ -16,37 +16,41 @@
package com.android.systemui.volume.ui.navigation
-import android.content.Context
import android.content.Intent
import android.provider.Settings
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.rememberCoroutineScope
+import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.phone.SystemUIDialogFactory
+import com.android.systemui.statusbar.phone.createBottomSheet
import com.android.systemui.volume.VolumePanelFactory
import com.android.systemui.volume.domain.model.VolumePanelRoute
-import com.android.systemui.volume.panel.ui.activity.VolumePanelActivity
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
+import com.android.systemui.volume.panel.ui.composable.VolumePanelRoot
+import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
class VolumeNavigator
@Inject
constructor(
- @Application private val context: Context,
+ @Application private val applicationScope: CoroutineScope,
+ @Main private val mainContext: CoroutineContext,
private val volumePanelFactory: VolumePanelFactory,
private val activityStarter: ActivityStarter,
+ private val viewModelFactory: VolumePanelViewModel.Factory,
+ private val dialogFactory: SystemUIDialogFactory,
+ private val uiEventLogger: UiEventLogger,
) {
fun openVolumePanel(route: VolumePanelRoute) {
when (route) {
- VolumePanelRoute.COMPOSE_VOLUME_PANEL ->
- activityStarter.startActivityDismissingKeyguard(
- /* intent = */ Intent(context, VolumePanelActivity::class.java),
- /* onlyProvisioned = */ false,
- /* dismissShade= */ true,
- /* disallowEnterPictureInPictureWhileLaunching = */ true,
- /* callback= */ null,
- /* flags= */ 0,
- /* animationController= */ null,
- /* userHandle= */ null,
- )
+ VolumePanelRoute.COMPOSE_VOLUME_PANEL -> showNewVolumePanel()
VolumePanelRoute.SETTINGS_VOLUME_PANEL ->
activityStarter.startActivity(
/* intent= */ Intent(Settings.Panel.ACTION_VOLUME),
@@ -56,4 +60,25 @@
volumePanelFactory.create(aboveStatusBar = true, view = null)
}
}
+
+ private fun showNewVolumePanel() {
+ applicationScope.launch(mainContext) {
+ dialogFactory
+ .createBottomSheet(
+ content = { dialog ->
+ LaunchedEffect(dialog) {
+ dialog.setOnDismissListener {
+ uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_GONE)
+ }
+ }
+
+ VolumePanelRoot(
+ viewModel = viewModelFactory.create(rememberCoroutineScope()),
+ onDismiss = { dialog.dismiss() },
+ )
+ },
+ )
+ .show()
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index d354fa2..d6f0ef8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -19,6 +19,7 @@
import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
import static android.hardware.biometrics.SensorProperties.STRENGTH_CONVENIENCE;
@@ -82,7 +83,6 @@
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
-import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -2276,8 +2276,7 @@
private void faceAuthLockOut() {
when(mFaceAuthInteractor.isLockedOut()).thenReturn(true);
mFaceAuthenticationListener.getValue().onAuthenticationStatusChanged(
- new ErrorFaceAuthenticationStatus(FaceManager.FACE_ERROR_LOCKOUT_PERMANENT, "",
- 0L));
+ new ErrorFaceAuthenticationStatus(FACE_ERROR_LOCKOUT_PERMANENT, "", 0L));
}
private void statusBarShadeIsNotLocked() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
index 1e3b556..d01d57e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
@@ -24,26 +24,35 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
+import android.hardware.display.DisplayManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.testing.AndroidTestingRunner;
-import android.util.Pair;
+import android.testing.TestableLooper;
import android.view.GestureDetector;
import android.view.IWindowManager;
import android.view.InputEvent;
import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
-import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
import androidx.test.filters.SmallTest;
+import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.display.DisplayHelper;
@@ -67,31 +76,58 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class TouchMonitorTest extends SysuiTestCase {
+ private KosmosJavaAdapter mKosmos;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ mKosmos = new KosmosJavaAdapter(this);
+ }
+
+ private static class SimpleLifecycleOwner implements LifecycleOwner {
+ LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycle;
+ }
+
+ public void setState(Lifecycle.State state) {
+ mLifecycle.setCurrentState(state);
+ }
}
private static class Environment {
private final InputSessionComponent.Factory mInputFactory;
private final InputSession mInputSession;
- private final Lifecycle mLifecycle;
- private final LifecycleOwner mLifecycleOwner;
+ private final SimpleLifecycleOwner mLifecycleOwner;
+
+ private final LifecycleRegistry mLifecycleRegistry;
private final TouchMonitor mMonitor;
- private final DefaultLifecycleObserver mLifecycleObserver;
private final InputChannelCompat.InputEventListener mEventListener;
private final GestureDetector.OnGestureListener mGestureListener;
private final DisplayHelper mDisplayHelper;
+ private final DisplayManager mDisplayManager;
+ private final WindowManager mWindowManager;
+ private final WindowMetrics mWindowMetrics;
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
+
private final Rect mDisplayBounds = Mockito.mock(Rect.class);
private final IWindowManager mIWindowManager;
- Environment(Set<TouchHandler> handlers) {
- mLifecycle = Mockito.mock(Lifecycle.class);
- mLifecycleOwner = Mockito.mock(LifecycleOwner.class);
+ private final KosmosJavaAdapter mKosmos;
+
+
+ Environment(Set<TouchHandler> handlers, KosmosJavaAdapter kosmos) {
+ mLifecycleOwner = new SimpleLifecycleOwner();
+ mLifecycleRegistry = spy(new LifecycleRegistry(mLifecycleOwner));
+
mIWindowManager = Mockito.mock(IWindowManager.class);
+ mDisplayManager = Mockito.mock(DisplayManager.class);
+ mWindowManager = Mockito.mock(WindowManager.class);
+ mKosmos = kosmos;
mInputFactory = Mockito.mock(InputSessionComponent.Factory.class);
final InputSessionComponent inputComponent = Mockito.mock(InputSessionComponent.class);
@@ -104,18 +140,16 @@
mDisplayHelper = Mockito.mock(DisplayHelper.class);
when(mDisplayHelper.getMaxBounds(anyInt(), anyInt()))
.thenReturn(mDisplayBounds);
- mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor,
- mLifecycle, mInputFactory, mDisplayHelper, handlers, mIWindowManager, 0);
+
+ mWindowMetrics = Mockito.mock(WindowMetrics.class);
+ when(mWindowMetrics.getBounds()).thenReturn(mDisplayBounds);
+ when(mWindowManager.getMaximumWindowMetrics()).thenReturn(mWindowMetrics);
+ mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor, mLifecycleRegistry,
+ mInputFactory, mDisplayHelper, mKosmos.getConfigurationInteractor(),
+ handlers, mIWindowManager, 0);
mMonitor.init();
- final ArgumentCaptor<LifecycleObserver> lifecycleObserverCaptor =
- ArgumentCaptor.forClass(LifecycleObserver.class);
- verify(mLifecycle).addObserver(lifecycleObserverCaptor.capture());
- assertThat(lifecycleObserverCaptor.getValue() instanceof DefaultLifecycleObserver)
- .isTrue();
- mLifecycleObserver = (DefaultLifecycleObserver) lifecycleObserverCaptor.getValue();
-
- updateLifecycle(observer -> observer.first.onResume(observer.second));
+ updateLifecycle(Lifecycle.State.RESUMED);
// Capture creation request.
final ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
@@ -145,8 +179,8 @@
listenerConsumer.accept(mGestureListener);
}
- void updateLifecycle(Consumer<Pair<DefaultLifecycleObserver, LifecycleOwner>> consumer) {
- consumer.accept(Pair.create(mLifecycleObserver, mLifecycleOwner));
+ void updateLifecycle(Lifecycle.State state) {
+ mLifecycleRegistry.setCurrentState(state);
}
void verifyInputSessionDispose() {
@@ -156,10 +190,33 @@
}
@Test
+ @EnableFlags(Flags.FLAG_AMBIENT_TOUCH_MONITOR_LISTEN_TO_DISPLAY_CHANGES)
+ public void testConfigurationListenerUpdatesBounds() {
+ final TouchHandler touchHandler = createTouchHandler();
+ final Environment environment = new Environment(Stream.of(touchHandler)
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
+ ArgumentCaptor<DisplayManager.DisplayListener> listenerCaptor =
+ ArgumentCaptor.forClass(DisplayManager.DisplayListener.class);
+ final Rect testRect = new Rect(0, 0, 2, 2);
+ final Configuration configuration = new Configuration();
+ configuration.windowConfiguration.setMaxBounds(testRect);
+
+ mKosmos.getConfigurationRepository().onConfigurationChange(configuration);
+ final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
+ when(initialEvent.getX()).thenReturn(0.0f);
+ when(initialEvent.getY()).thenReturn(0.0f);
+ environment.publishInputEvent(initialEvent);
+
+ // Verify display bounds passed into TouchHandler#getTouchInitiationRegion
+ verify(touchHandler).getTouchInitiationRegion(eq(testRect), any(), any());
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_AMBIENT_TOUCH_MONITOR_LISTEN_TO_DISPLAY_CHANGES)
public void testReportedDisplayBounds() {
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
when(initialEvent.getX()).thenReturn(0.0f);
@@ -190,7 +247,7 @@
}).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
// Ensure touch outside specified region is not delivered.
final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
@@ -219,7 +276,7 @@
}).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
final Environment environment = new Environment(Stream.of(touchHandler, unzonedTouchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
// Ensure touch outside specified region is delivered to unzoned touch handler.
final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
@@ -261,7 +318,7 @@
when(touchHandler.isEnabled()).thenReturn(false);
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
when(initialEvent.getX()).thenReturn(5.0f);
when(initialEvent.getY()).thenReturn(5.0f);
@@ -277,7 +334,7 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -297,7 +354,7 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -321,7 +378,7 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -340,7 +397,7 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -365,7 +422,7 @@
when(touchHandler2.isEnabled()).thenReturn(true);
final Environment environment = new Environment(Stream.of(touchHandler, touchHandler2)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -389,7 +446,7 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -435,7 +492,7 @@
Mockito.mock(TouchHandler.TouchSession.Callback.class);
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -453,11 +510,9 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
- environment.updateLifecycle(observerOwnerPair -> {
- observerOwnerPair.first.onPause(observerOwnerPair.second);
- });
+ environment.updateLifecycle(Lifecycle.State.STARTED);
environment.verifyInputSessionDispose();
}
@@ -467,7 +522,7 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -486,9 +541,7 @@
verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
- environment.updateLifecycle(observerOwnerPair -> {
- observerOwnerPair.first.onPause(observerOwnerPair.second);
- });
+ environment.updateLifecycle(Lifecycle.State.STARTED);
verify(environment.mInputSession, never()).dispose();
@@ -505,7 +558,7 @@
final TouchHandler touchHandler = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -524,9 +577,7 @@
verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
- environment.updateLifecycle(observerOwnerPair -> {
- observerOwnerPair.first.onDestroy(observerOwnerPair.second);
- });
+ environment.updateLifecycle(Lifecycle.State.DESTROYED);
// Check to make sure the input session is now disposed.
environment.verifyInputSessionDispose();
@@ -538,7 +589,7 @@
final TouchHandler touchHandler1 = createTouchHandler();
final TouchHandler touchHandler2 = createTouchHandler();
final Environment environment = new Environment(Stream.of(touchHandler1, touchHandler2)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -574,7 +625,7 @@
Mockito.mock(TouchHandler.TouchSession.Callback.class);
final Environment environment = new Environment(Stream.of(touchHandler)
- .collect(Collectors.toCollection(HashSet::new)));
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
environment.publishInputEvent(initialEvent);
@@ -584,9 +635,7 @@
environment.executeAll();
- environment.updateLifecycle(observerOwnerPair -> {
- observerOwnerPair.first.onDestroy(observerOwnerPair.second);
- });
+ environment.updateLifecycle(Lifecycle.State.DESTROYED);
environment.executeAll();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
index 9e007e9..63b4ff7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
@@ -91,7 +91,7 @@
@Test
fun maxBoundsChange_emitsMaxBoundsChange() =
testScope.runTest {
- val values by collectValues(underTest.naturalMaxBounds)
+ val values by collectValues(underTest.maxBounds)
updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
runCurrent()
@@ -109,7 +109,7 @@
@Test
fun maxBoundsSameOnConfigChange_doesNotEmitMaxBoundsChange() =
testScope.runTest {
- val values by collectValues(underTest.naturalMaxBounds)
+ val values by collectValues(underTest.maxBounds)
updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
runCurrent()
@@ -122,6 +122,48 @@
@Test
fun firstMaxBoundsChange_emitsMaxBoundsChange() =
testScope.runTest {
+ val values by collectValues(underTest.maxBounds)
+
+ updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+ runCurrent()
+
+ assertThat(values).containsExactly(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT))
+ }
+
+ @Test
+ fun maxBoundsChange_emitsNaturalMaxBoundsChange() =
+ testScope.runTest {
+ val values by collectValues(underTest.naturalMaxBounds)
+
+ updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+ runCurrent()
+ updateDisplay(width = DISPLAY_WIDTH * 2, height = DISPLAY_HEIGHT * 3)
+ runCurrent()
+
+ assertThat(values)
+ .containsExactly(
+ Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
+ Rect(0, 0, DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 3),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun maxBoundsSameOnConfigChange_doesNotEmitNaturalMaxBoundsChange() =
+ testScope.runTest {
+ val values by collectValues(underTest.naturalMaxBounds)
+
+ updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+ runCurrent()
+ updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+ runCurrent()
+
+ assertThat(values).containsExactly(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT))
+ }
+
+ @Test
+ fun firstMaxBoundsChange_emitsNaturalMaxBoundsChange() =
+ testScope.runTest {
val values by collectValues(underTest.naturalMaxBounds)
updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
@@ -131,7 +173,7 @@
}
@Test
- fun displayRotatedButMaxBoundsTheSame_doesNotEmitNewMaxBoundsChange() =
+ fun displayRotatedButMaxBoundsTheSame_doesNotEmitNewNaturalMaxBoundsChange() =
testScope.runTest {
val values by collectValues(underTest.naturalMaxBounds)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
index 5581f0c..431fef6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
@@ -17,7 +17,9 @@
package com.android.systemui.deviceentry.domain.interactor
import android.content.res.mainResources
-import android.hardware.face.FaceManager
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT
import android.hardware.fingerprint.FingerprintManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -266,7 +268,7 @@
faceAuthRepository.setAuthenticationStatus(
HelpFaceAuthenticationStatus(
msg = "Move left",
- msgId = FaceManager.FACE_ACQUIRED_TOO_RIGHT,
+ msgId = FACE_ACQUIRED_TOO_RIGHT,
)
)
@@ -293,7 +295,7 @@
faceAuthRepository.setAuthenticationStatus(
HelpFaceAuthenticationStatus(
msg = "Move left",
- msgId = FaceManager.FACE_ACQUIRED_TOO_RIGHT,
+ msgId = FACE_ACQUIRED_TOO_RIGHT,
)
)
@@ -318,7 +320,7 @@
faceAuthRepository.setAuthenticationStatus(
HelpFaceAuthenticationStatus(
msg = "Move left",
- msgId = FaceManager.FACE_ACQUIRED_TOO_RIGHT,
+ msgId = FACE_ACQUIRED_TOO_RIGHT,
)
)
@@ -333,10 +335,7 @@
// WHEN authentication status error is FACE_ERROR_HW_UNAVAILABLE
faceAuthRepository.setAuthenticationStatus(
- ErrorFaceAuthenticationStatus(
- msgId = FaceManager.FACE_ERROR_HW_UNAVAILABLE,
- msg = "test"
- )
+ ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_HW_UNAVAILABLE, msg = "test")
)
// THEN faceErrorMessage isn't updated - it's still null since it was suppressed
@@ -350,10 +349,7 @@
// WHEN authentication status error is FACE_ERROR_HW_UNAVAILABLE
faceAuthRepository.setAuthenticationStatus(
- ErrorFaceAuthenticationStatus(
- msgId = FaceManager.FACE_ERROR_HW_UNAVAILABLE,
- msg = "test"
- )
+ ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_HW_UNAVAILABLE, msg = "test")
)
// GIVEN face is allowed
@@ -370,7 +366,7 @@
// WHEN authentication status error is FACE_ERROR_TIMEOUT
faceAuthRepository.setAuthenticationStatus(
- ErrorFaceAuthenticationStatus(msgId = FaceManager.FACE_ERROR_TIMEOUT, msg = "test")
+ ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_TIMEOUT, msg = "test")
)
// GIVEN face is allowed
@@ -389,7 +385,7 @@
// WHEN authentication status error is FACE_ERROR_TIMEOUT
faceAuthRepository.setAuthenticationStatus(
- ErrorFaceAuthenticationStatus(msgId = FaceManager.FACE_ERROR_TIMEOUT, msg = "test")
+ ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_TIMEOUT, msg = "test")
)
// GIVEN face is allowed
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
index 4684b80..79e312f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
@@ -27,9 +27,11 @@
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus
import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.ActivityStarter.OnDismissAction
@@ -229,6 +231,11 @@
givenOnOccludingApp(true)
givenFingerprintAllowed(true)
keyguardRepository.setIsDozing(true)
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.DOZING,
+ testScope
+ )
runCurrent()
// ERROR message
@@ -254,7 +261,7 @@
assertThat(message).isNull()
}
- private fun givenOnOccludingApp(isOnOccludingApp: Boolean) {
+ private suspend fun givenOnOccludingApp(isOnOccludingApp: Boolean) {
powerRepository.setInteractive(true)
keyguardRepository.setIsDozing(false)
keyguardRepository.setKeyguardOccluded(isOnOccludingApp)
@@ -262,6 +269,20 @@
keyguardRepository.setDreaming(false)
bouncerRepository.setPrimaryShow(!isOnOccludingApp)
bouncerRepository.setAlternateVisible(!isOnOccludingApp)
+
+ if (isOnOccludingApp) {
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ testScope
+ )
+ } else {
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.LOCKSCREEN,
+ testScope
+ )
+ }
}
private fun givenFingerprintAllowed(allowed: Boolean) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index 77b3040..cfe37ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -67,6 +67,7 @@
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.globalactions.domain.interactor.GlobalActionsInteractor;
import com.android.systemui.kosmos.KosmosJavaAdapter;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.settings.UserTracker;
@@ -114,6 +115,7 @@
private SecureSettings mSecureSettings;
@Mock private Resources mResources;
@Mock private ConfigurationController mConfigurationController;
+ @Mock private ActivityStarter mActivityStarter;
@Mock private UserTracker mUserTracker;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private UserManager mUserManager;
@@ -173,6 +175,7 @@
mVibratorHelper,
mResources,
mConfigurationController,
+ mActivityStarter,
mUserTracker,
mKeyguardStateController,
mUserManager,
@@ -458,6 +461,18 @@
}
}
+ private static <T> void assertNoItemsOfType(List<T> stuff, Class<? extends T> klass) {
+ for (int i = 0; i < stuff.size(); i++) {
+ assertThat(stuff.get(i)).isNotInstanceOf(klass);
+ }
+ }
+
+ private static <T> void assertOneItemOfType(List<T> stuff, Class<? extends T> klass) {
+ List<?> classes = stuff.stream().map((item) -> item.getClass()).toList();
+ assertThat(classes).containsNoDuplicates();
+ assertThat(classes).contains(klass);
+ }
+
@Test
public void testCreateActionItems_lockdownEnabled_doesShowLockdown() {
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
@@ -641,6 +656,113 @@
assertThat(mInteractor.isVisible().getValue()).isFalse();
}
+ @Test
+ public void testShouldLogSystemUpdatePress() {
+ GlobalActionsDialogLite.SystemUpdateAction systemUpdateAction =
+ mGlobalActionsDialogLite.new SystemUpdateAction();
+ systemUpdateAction.onPress();
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_SYSTEM_UPDATE_PRESS);
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateEnabled_doesShowSystemUpdate() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_SYSTEM_UPDATE
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+ mGlobalActionsDialogLite.createActionItems();
+
+ assertItemsOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.EmergencyAction.class,
+ GlobalActionsDialogLite.LockDownAction.class,
+ GlobalActionsDialogLite.ShutDownAction.class,
+ GlobalActionsDialogLite.RestartAction.class,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+ assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
+ assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateDisabled_doesntShowSystemUpdateAction() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+ mGlobalActionsDialogLite.createActionItems();
+
+ assertNoItemsOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+ assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
+ assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateEnabled_locked_showsSystemUpdate() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_SYSTEM_UPDATE
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+
+ // Show dialog with keyguard showing
+ mGlobalActionsDialogLite.showOrHideDialog(true, true, null);
+
+ assertOneItemOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+
+ // Hide dialog
+ mGlobalActionsDialogLite.showOrHideDialog(true, true, null);
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateEnabled_notProvisioned_noSystemUpdate() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_SYSTEM_UPDATE
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+
+ // Show dialog with keyguard showing
+ mGlobalActionsDialogLite.showOrHideDialog(false, false, null);
+
+ assertNoItemsOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+
+ // Hide dialog
+ mGlobalActionsDialogLite.showOrHideDialog(false, false, null);
+ }
+
private UserInfo mockCurrentUser(int flags) {
return new UserInfo(10, "A User", flags);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 59f7d61..325e7bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -262,7 +262,6 @@
mColorExtractor,
mDumpManager,
mKeyguardStateController,
- mScreenOffAnimationController,
mAuthController,
() -> mShadeInteractor,
mShadeWindowLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
index 96b7596..35659c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dock.DockManagerFake
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
@@ -83,6 +84,7 @@
)
@SmallTest
@RunWith(Parameterized::class)
+@DisableSceneContainer
class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
new file mode 100644
index 0000000..ef3183a8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.app.admin.DevicePolicyManager
+import android.content.Intent
+import android.os.UserHandle
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SmallTest
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dock.DockManagerFake
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
+import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceProviderClientFactory
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.settings.FakeSettings
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.Parameterized.Parameter
+import org.junit.runners.Parameterized.Parameters
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.ArgumentMatchers.same
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@FlakyTest(
+ bugId = 292574995,
+ detail = "on certain architectures all permutations with startActivity=true is causing failures"
+)
+@SmallTest
+@RunWith(Parameterized::class)
+@EnableSceneContainer
+class KeyguardQuickAffordanceInteractorSceneContainerTest : SysuiTestCase() {
+
+ companion object {
+ private val INTENT = Intent("some.intent.action")
+ private val DRAWABLE =
+ mock<Icon> {
+ whenever(this.contentDescription)
+ .thenReturn(
+ ContentDescription.Resource(
+ res = CONTENT_DESCRIPTION_RESOURCE_ID,
+ )
+ )
+ }
+ private const val CONTENT_DESCRIPTION_RESOURCE_ID = 1337
+
+ @Parameters(
+ name =
+ "needStrongAuthAfterBoot={0}, canShowWhileLocked={1}," +
+ " keyguardIsUnlocked={2}, needsToUnlockFirst={3}, startActivity={4}"
+ )
+ @JvmStatic
+ fun data() =
+ listOf(
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ false,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ false,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ false,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ false,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ true,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ false,
+ /* startActivity= */ true,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ false,
+ /* startActivity= */ true,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ false,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ false,
+ /* startActivity= */ true,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ true,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ false,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ true,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ false,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ true,
+ ),
+ arrayOf(
+ /* needStrongAuthAfterBoot= */ true,
+ /* canShowWhileLocked= */ true,
+ /* keyguardIsUnlocked= */ true,
+ /* needsToUnlockFirst= */ true,
+ /* startActivity= */ true,
+ ),
+ )
+
+ private val IMMEDIATE = Dispatchers.Main.immediate
+ }
+
+ @Mock private lateinit var lockPatternUtils: LockPatternUtils
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var activityStarter: ActivityStarter
+ @Mock private lateinit var animationController: ActivityTransitionAnimator.Controller
+ @Mock private lateinit var expandable: Expandable
+ @Mock private lateinit var launchAnimator: DialogTransitionAnimator
+ @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+ @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
+
+ private lateinit var underTest: KeyguardQuickAffordanceInteractor
+ private lateinit var testScope: TestScope
+
+ @JvmField @Parameter(0) var needStrongAuthAfterBoot: Boolean = false
+ @JvmField @Parameter(1) var canShowWhileLocked: Boolean = false
+ @JvmField @Parameter(2) var keyguardIsUnlocked: Boolean = false
+ @JvmField @Parameter(3) var needsToUnlockFirst: Boolean = false
+ @JvmField @Parameter(4) var startActivity: Boolean = false
+ private lateinit var homeControls: FakeKeyguardQuickAffordanceConfig
+ private lateinit var dockManager: DockManagerFake
+ private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
+ private lateinit var userTracker: UserTracker
+
+ private val kosmos = testKosmos()
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(expandable.activityTransitionController()).thenReturn(animationController)
+
+ userTracker = FakeUserTracker()
+ homeControls =
+ FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
+ dockManager = DockManagerFake()
+ biometricSettingsRepository = FakeBiometricSettingsRepository()
+ val quickAccessWallet =
+ FakeKeyguardQuickAffordanceConfig(
+ BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
+ )
+ val qrCodeScanner =
+ FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
+ val scope = CoroutineScope(IMMEDIATE)
+ val localUserSelectionManager =
+ KeyguardQuickAffordanceLocalUserSelectionManager(
+ context = context,
+ userFileManager =
+ mock<UserFileManager>().apply {
+ whenever(
+ getSharedPreferences(
+ anyString(),
+ anyInt(),
+ anyInt(),
+ )
+ )
+ .thenReturn(FakeSharedPreferences())
+ },
+ userTracker = userTracker,
+ broadcastDispatcher = fakeBroadcastDispatcher,
+ )
+ val remoteUserSelectionManager =
+ KeyguardQuickAffordanceRemoteUserSelectionManager(
+ scope = scope,
+ userTracker = userTracker,
+ clientFactory = FakeKeyguardQuickAffordanceProviderClientFactory(userTracker),
+ userHandle = UserHandle.SYSTEM,
+ )
+ val quickAffordanceRepository =
+ KeyguardQuickAffordanceRepository(
+ appContext = context,
+ scope = scope,
+ localUserSelectionManager = localUserSelectionManager,
+ remoteUserSelectionManager = remoteUserSelectionManager,
+ userTracker = userTracker,
+ legacySettingSyncer =
+ KeyguardQuickAffordanceLegacySettingSyncer(
+ scope = scope,
+ backgroundDispatcher = IMMEDIATE,
+ secureSettings = FakeSettings(),
+ selectionsManager = localUserSelectionManager,
+ ),
+ configs = setOf(homeControls, quickAccessWallet, qrCodeScanner),
+ dumpManager = mock(),
+ userHandle = UserHandle.SYSTEM,
+ )
+ val featureFlags = FakeFeatureFlags()
+ val testDispatcher = StandardTestDispatcher()
+ testScope = TestScope(testDispatcher)
+ underTest =
+ KeyguardQuickAffordanceInteractor(
+ keyguardInteractor =
+ KeyguardInteractorFactory.create(
+ featureFlags = featureFlags,
+ )
+ .keyguardInteractor,
+ shadeInteractor = kosmos.shadeInteractor,
+ lockPatternUtils = lockPatternUtils,
+ keyguardStateController = keyguardStateController,
+ userTracker = userTracker,
+ activityStarter = activityStarter,
+ featureFlags = featureFlags,
+ repository = { quickAffordanceRepository },
+ launchAnimator = launchAnimator,
+ logger = logger,
+ devicePolicyManager = devicePolicyManager,
+ dockManager = dockManager,
+ biometricSettingsRepository = biometricSettingsRepository,
+ backgroundDispatcher = testDispatcher,
+ appContext = mContext,
+ sceneInteractor = { kosmos.sceneInteractor },
+ )
+ }
+
+ @Test
+ fun onQuickAffordanceTriggered() =
+ testScope.runTest {
+ val key = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS
+ setUpMocks(
+ needStrongAuthAfterBoot = needStrongAuthAfterBoot,
+ keyguardIsUnlocked = keyguardIsUnlocked,
+ )
+
+ homeControls.setState(
+ lockScreenState =
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ icon = DRAWABLE,
+ )
+ )
+ homeControls.onTriggeredResult =
+ if (startActivity) {
+ KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity(
+ intent = INTENT,
+ canShowWhileLocked = canShowWhileLocked,
+ )
+ } else {
+ KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+ }
+
+ underTest.onQuickAffordanceTriggered(
+ configKey = "${KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId()}::$key",
+ expandable = expandable,
+ slotId = "",
+ )
+
+ if (startActivity) {
+ if (needsToUnlockFirst) {
+ verify(activityStarter)
+ .postStartActivityDismissingKeyguard(
+ any(),
+ /* delay= */ eq(0),
+ same(animationController),
+ )
+ } else {
+ verify(activityStarter)
+ .startActivity(
+ any(),
+ /* dismissShade= */ eq(true),
+ same(animationController),
+ /* showOverLockscreenWhenLocked= */ eq(true),
+ )
+ }
+ } else {
+ verifyZeroInteractions(activityStarter)
+ }
+ }
+
+ private fun setUpMocks(
+ needStrongAuthAfterBoot: Boolean = true,
+ keyguardIsUnlocked: Boolean = false,
+ ) {
+ whenever(lockPatternUtils.getStrongAuthForUser(any()))
+ .thenReturn(
+ if (needStrongAuthAfterBoot) {
+ LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+ } else {
+ LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
+ }
+ )
+ whenever(keyguardStateController.isUnlocked).thenReturn(keyguardIsUnlocked)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 6b317ea..1881a9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -19,6 +19,7 @@
import android.app.admin.DevicePolicyManager
import android.content.Intent
import android.os.UserHandle
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.internal.widget.LockPatternUtils
@@ -32,6 +33,7 @@
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceProviderClientFactory
@@ -75,17 +77,18 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(JUnit4::class)
-class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class KeyguardBottomAreaViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
@Mock private lateinit var expandable: Expandable
@Mock private lateinit var burnInHelperWrapper: BurnInHelperWrapper
@@ -111,6 +114,10 @@
private val kosmos = testKosmos()
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -750,5 +757,11 @@
companion object {
private const val DEFAULT_BURN_IN_OFFSET = 5
private const val RETURNED_BURN_IN_OFFSET = 3
+
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
index 1d98dc3..0c98cff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
@@ -18,11 +18,12 @@
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
import com.android.systemui.keyguard.data.repository.keyguardClockRepository
import com.android.systemui.keyguard.data.repository.keyguardRepository
@@ -45,14 +46,14 @@
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.Mock
import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(JUnit4::class)
-@DisableSceneContainer
-class KeyguardClockViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class KeyguardClockViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
val kosmos = testKosmos()
val testScope = kosmos.testScope
val underTest = kosmos.keyguardClockViewModel
@@ -65,6 +66,10 @@
var config = ClockConfig("TEST", "Test", "")
var faceConfig = ClockFaceConfig()
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -276,5 +281,11 @@
companion object {
private const val KEYGUARD_STATUS_BAR_HEIGHT = 20
+
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
index b3cfcf2..857af66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
@@ -27,6 +27,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.media.controls.MediaTestUtils
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME
import com.android.systemui.media.controls.shared.model.MediaCommonModel
import com.android.systemui.media.controls.shared.model.MediaData
@@ -38,6 +39,7 @@
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
@@ -77,6 +79,7 @@
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
class MediaDataFilterImplTest : SysuiTestCase() {
+ val kosmos = testKosmos()
@Mock private lateinit var listener: MediaDataProcessor.Listener
@Mock private lateinit var userTracker: UserTracker
@@ -91,12 +94,12 @@
@Mock private lateinit var cardAction: SmartspaceAction
private lateinit var mediaDataFilter: MediaDataFilterImpl
- private lateinit var repository: MediaFilterRepository
private lateinit var testScope: TestScope
private lateinit var dataMain: MediaData
private lateinit var dataGuest: MediaData
private lateinit var dataPrivateProfile: MediaData
private val clock = FakeSystemClock()
+ private val repository: MediaFilterRepository = kosmos.mediaFilterRepository
@Before
fun setup() {
@@ -104,7 +107,6 @@
MediaPlayerData.clear()
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
testScope = TestScope()
- repository = MediaFilterRepository(FakeSystemClock())
mediaDataFilter =
MediaDataFilterImpl(
context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index ffb50c1..1de7ee3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -54,6 +54,7 @@
import com.android.systemui.dump.DumpManager
import com.android.systemui.media.controls.data.repository.MediaDataRepository
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.domain.resume.MediaResumeListener
import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
@@ -68,6 +69,7 @@
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.SbnBuilder
+import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
@@ -125,6 +127,7 @@
@RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner::class)
class MediaDataProcessorTest : SysuiTestCase() {
+ val kosmos = testKosmos()
@JvmField @Rule val mockito = MockitoJUnit.rule()
@Mock lateinit var mediaControllerFactory: MediaControllerFactory
@@ -168,7 +171,6 @@
@Mock private lateinit var ugm: IUriGrantsManager
@Mock private lateinit var imageSource: ImageDecoder.Source
private lateinit var mediaDataRepository: MediaDataRepository
- private lateinit var mediaFilterRepository: MediaFilterRepository
private lateinit var testScope: TestScope
private lateinit var testDispatcher: TestDispatcher
private lateinit var testableLooper: TestableLooper
@@ -183,6 +185,7 @@
Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
1
)
+ private val mediaFilterRepository: MediaFilterRepository = kosmos.mediaFilterRepository
private lateinit var staticMockSession: MockitoSession
@@ -210,7 +213,6 @@
)
testDispatcher = UnconfinedTestDispatcher()
testScope = TestScope(testDispatcher)
- mediaFilterRepository = MediaFilterRepository(clock)
mediaDataRepository = MediaDataRepository(mediaFlags, dumpManager)
mediaDataProcessor =
MediaDataProcessor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
index c3daf84..0a5aace 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
@@ -36,6 +36,7 @@
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.MediaTestUtils
import com.android.systemui.media.controls.domain.pipeline.EMPTY_SMARTSPACE_MEDIA_DATA
@@ -44,6 +45,7 @@
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QS
import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.media.controls.ui.view.MediaScrollView
+import com.android.systemui.media.controls.ui.viewmodel.mediaCarouselViewModel
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.plugins.ActivityStarter
@@ -100,6 +102,7 @@
val kosmos = testKosmos()
@Mock lateinit var mediaControlPanelFactory: Provider<MediaControlPanel>
+ @Mock lateinit var mediaViewControllerFactory: Provider<MediaViewController>
@Mock lateinit var panel: MediaControlPanel
@Mock lateinit var visualStabilityProvider: VisualStabilityProvider
@Mock lateinit var mediaHostStatesManager: MediaHostStatesManager
@@ -148,6 +151,7 @@
mediaHostStatesManager,
activityStarter,
clock,
+ kosmos.testDispatcher,
executor,
bgExecutor,
testDispatcher,
@@ -162,6 +166,8 @@
kosmos.keyguardTransitionInteractor,
globalSettings,
secureSettings,
+ kosmos.mediaCarouselViewModel,
+ mediaViewControllerFactory,
)
verify(configurationController).addCallback(capture(configListener))
verify(mediaDataManager).addListener(capture(listener))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
index cb4ab64..e1c2d3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
@@ -29,12 +29,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.Classifier
-import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.media.controls.util.MediaFlags
-import com.android.systemui.media.controls.util.mediaFlags
import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.concurrency.FakeRepeatableExecutor
import com.android.systemui.util.time.FakeSystemClock
@@ -61,7 +56,6 @@
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class SeekBarViewModelTest : SysuiTestCase() {
- val kosmos = testKosmos()
private lateinit var viewModel: SeekBarViewModel
private lateinit var fakeExecutor: FakeExecutor
@@ -81,7 +75,6 @@
@Mock private lateinit var mockTransport: MediaController.TransportControls
@Mock private lateinit var falsingManager: FalsingManager
@Mock private lateinit var mockBar: SeekBar
- @Mock private lateinit var mediaFlags: MediaFlags
private val token1 = MediaSession.Token(1, null)
private val token2 = MediaSession.Token(2, null)
@@ -90,18 +83,10 @@
@Before
fun setUp() {
fakeExecutor = FakeExecutor(FakeSystemClock())
- viewModel =
- SeekBarViewModel(
- kosmos.applicationCoroutineScope,
- kosmos.testDispatcher,
- FakeRepeatableExecutor(fakeExecutor),
- falsingManager,
- mediaFlags,
- )
+ viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor), falsingManager)
viewModel.logSeek = {}
whenever(mockController.sessionToken).thenReturn(token1)
whenever(mockBar.context).thenReturn(context)
- whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(false)
// LiveData to run synchronously
ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
index e6c259a..f1c97dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.navigationbar.gestural
import android.os.Handler
-import android.os.Looper
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.HapticFeedbackConstants
@@ -28,6 +27,7 @@
import android.view.ViewConfiguration
import android.view.WindowManager
import androidx.test.filters.SmallTest
+import com.android.internal.jank.Cuj
import com.android.internal.util.LatencyTracker
import com.android.systemui.SysuiTestCase
import com.android.systemui.jank.interactionJankMonitor
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.testKosmos
+import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -43,6 +44,7 @@
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -55,6 +57,7 @@
}
private val kosmos = testKosmos()
private lateinit var mBackPanelController: BackPanelController
+ private lateinit var systemClock: FakeSystemClock
private lateinit var testableLooper: TestableLooper
private var triggerThreshold: Float = 0.0f
private val touchSlop = ViewConfiguration.get(context).scaledEdgeSlop
@@ -69,12 +72,15 @@
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
+ systemClock = FakeSystemClock()
mBackPanelController =
BackPanelController(
context,
windowManager,
ViewConfiguration.get(context),
- Handler.createAsync(checkNotNull(Looper.myLooper())),
+ Handler.createAsync(testableLooper.looper),
+ systemClock,
vibratorHelper,
configurationController,
latencyTracker,
@@ -83,7 +89,6 @@
mBackPanelController.setLayoutParams(layoutParams)
mBackPanelController.setBackCallback(backCallback)
mBackPanelController.setIsLeftPanel(true)
- testableLooper = TestableLooper.get(this)
triggerThreshold = mBackPanelController.params.staticTriggerThreshold
}
@@ -103,6 +108,7 @@
assertThat(mBackPanelController.currentState)
.isEqualTo(BackPanelController.GestureState.GONE)
+ verify(interactionJankMonitor, never()).begin(any())
}
@Test
@@ -110,23 +116,37 @@
startTouch()
// Move once to cross the touch slop
continueTouch(START_X + touchSlop.toFloat() + 1)
+ assertThat(mBackPanelController.currentState)
+ .isEqualTo(BackPanelController.GestureState.ENTRY)
+ verify(interactionJankMonitor).cancel(Cuj.CUJ_BACK_PANEL_ARROW)
+ verify(interactionJankMonitor)
+ .begin(mBackPanelController.getBackPanelView(), Cuj.CUJ_BACK_PANEL_ARROW)
// Move again to cross the back trigger threshold
continueTouch(START_X + touchSlop + triggerThreshold + 1)
// Wait threshold duration and hold touch past trigger threshold
- Thread.sleep((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
+ moveTimeForward((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
continueTouch(START_X + touchSlop + triggerThreshold + 1)
assertThat(mBackPanelController.currentState)
.isEqualTo(BackPanelController.GestureState.ACTIVE)
verify(backCallback).setTriggerBack(true)
- testableLooper.moveTimeForward(100)
- testableLooper.processAllMessages()
+ moveTimeForward(100)
verify(vibratorHelper)
.performHapticFeedback(any(), eq(HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE))
finishTouchActionUp(START_X + touchSlop + triggerThreshold + 1)
assertThat(mBackPanelController.currentState)
.isEqualTo(BackPanelController.GestureState.COMMITTED)
verify(backCallback).triggerBack()
+
+ // Because the Handler that is typically used for transitioning the arrow state from
+ // COMMITTED to GONE is used as an animation-end-listener on a SpringAnimation,
+ // there is no way to meaningfully test that the state becomes GONE and that the tracked
+ // jank interaction is ended. So instead, manually trigger the failsafe, which does
+ // the same thing:
+ mBackPanelController.failsafeRunnable.run()
+ assertThat(mBackPanelController.currentState)
+ .isEqualTo(BackPanelController.GestureState.GONE)
+ verify(interactionJankMonitor).end(Cuj.CUJ_BACK_PANEL_ARROW)
}
@Test
@@ -134,19 +154,22 @@
startTouch()
// Move once to cross the touch slop
continueTouch(START_X + touchSlop.toFloat() + 1)
+ assertThat(mBackPanelController.currentState)
+ .isEqualTo(BackPanelController.GestureState.ENTRY)
// Move again to cross the back trigger threshold
continueTouch(
START_X + touchSlop + triggerThreshold -
mBackPanelController.params.deactivationTriggerThreshold
)
// Wait threshold duration and hold touch before trigger threshold
- Thread.sleep((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
+ moveTimeForward((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
continueTouch(
START_X + touchSlop + triggerThreshold -
mBackPanelController.params.deactivationTriggerThreshold
)
clearInvocations(backCallback)
- Thread.sleep(MIN_DURATION_ACTIVE_BEFORE_INACTIVE_ANIMATION)
+ moveTimeForward(MIN_DURATION_ACTIVE_BEFORE_INACTIVE_ANIMATION)
+
// Move in the opposite direction to cross the deactivation threshold and cancel back
continueTouch(START_X)
@@ -175,4 +198,10 @@
private fun createMotionEvent(action: Int, x: Float, y: Float): MotionEvent {
return MotionEvent.obtain(0L, 0L, action, x, y, 0)
}
+
+ private fun moveTimeForward(millis: Long) {
+ systemClock.advanceTime(millis)
+ testableLooper.moveTimeForward(millis)
+ testableLooper.processAllMessages()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
index 72fc65b..924b872 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
@@ -2,6 +2,8 @@
import android.graphics.drawable.Drawable
import android.os.UserHandle
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.testing.AndroidTestingRunner
import android.view.View
import android.view.ViewGroup
@@ -10,10 +12,16 @@
import androidx.constraintlayout.widget.Guideline
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.screenshot.message.LabeledIcon
+import com.android.systemui.screenshot.message.ProfileMessageController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import junit.framework.Assert.assertEquals
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -28,6 +36,7 @@
lateinit var messageContainer: MessageContainerController
@Mock lateinit var workProfileMessageController: WorkProfileMessageController
+ @Mock lateinit var profileMessageController: ProfileMessageController
@Mock lateinit var screenshotDetectionController: ScreenshotDetectionController
@@ -46,12 +55,15 @@
lateinit var workProfileData: WorkProfileMessageController.WorkProfileFirstRunData
@Before
+ @ExperimentalCoroutinesApi
fun setup() {
MockitoAnnotations.initMocks(this)
messageContainer =
MessageContainerController(
workProfileMessageController,
+ profileMessageController,
screenshotDetectionController,
+ TestScope(UnconfinedTestDispatcher())
)
screenshotView = ConstraintLayout(mContext)
workProfileData = WorkProfileMessageController.WorkProfileFirstRunData(appName, icon)
@@ -78,20 +90,11 @@
}
@Test
- fun testOnScreenshotTakenUserHandle_noWorkProfileFirstRun() {
- // (just being explicit here)
- whenever(workProfileMessageController.onScreenshotTaken(eq(userHandle))).thenReturn(null)
-
- messageContainer.onScreenshotTaken(userHandle)
-
- verify(workProfileMessageController, never()).populateView(any(), any(), any())
- }
-
- @Test
+ @DisableFlags(com.android.systemui.Flags.FLAG_SCREENSHOT_PRIVATE_PROFILE_BEHAVIOR_FIX)
fun testOnScreenshotTakenUserHandle_withWorkProfileFirstRun() {
whenever(workProfileMessageController.onScreenshotTaken(eq(userHandle)))
.thenReturn(workProfileData)
- messageContainer.onScreenshotTaken(userHandle)
+ messageContainer.onScreenshotTaken(screenshotData)
verify(workProfileMessageController)
.populateView(eq(workProfileFirstRunView), eq(workProfileData), any())
@@ -100,10 +103,28 @@
}
@Test
+ @EnableFlags(com.android.systemui.Flags.FLAG_SCREENSHOT_PRIVATE_PROFILE_BEHAVIOR_FIX)
+ fun testOnScreenshotTakenUserHandle_withProfileProfileFirstRun() = runTest {
+ val profileData =
+ ProfileMessageController.ProfileFirstRunData(
+ LabeledIcon(appName, icon),
+ ProfileMessageController.FirstRunProfile.PRIVATE
+ )
+ whenever(profileMessageController.onScreenshotTaken(eq(userHandle))).thenReturn(profileData)
+ messageContainer.onScreenshotTaken(screenshotData)
+
+ verify(profileMessageController)
+ .bindView(eq(workProfileFirstRunView), eq(profileData), any())
+ assertEquals(View.VISIBLE, workProfileFirstRunView.visibility)
+ assertEquals(View.GONE, detectionNoticeView.visibility)
+ }
+
+ @Test
fun testOnScreenshotTakenScreenshotData_nothingToShow() {
messageContainer.onScreenshotTaken(screenshotData)
verify(workProfileMessageController, never()).populateView(any(), any(), any())
+ verify(profileMessageController, never()).bindView(any(), any(), any())
verify(screenshotDetectionController, never()).populateView(any(), any())
assertEquals(View.GONE, container.visibility)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
index 4b7d5f0..ebdc49f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
@@ -87,7 +87,7 @@
when(mMockContext.getSharedPreferences(
eq(WorkProfileMessageController.SHARED_PREFERENCES_NAME),
eq(Context.MODE_PRIVATE))).thenReturn(mSharedPreferences);
- when(mMockContext.getString(R.string.config_sceenshotWorkProfileFilesApp))
+ when(mMockContext.getString(R.string.config_screenshotFilesApp))
.thenReturn(FILES_APP_COMPONENT);
when(mMockContext.getString(R.string.screenshot_default_files_app_name))
.thenReturn(DEFAULT_FILES_APP_LABEL);
@@ -149,7 +149,7 @@
@Test
public void testOnScreenshotTaken_noFilesAppComponentDefined() {
- when(mMockContext.getString(R.string.config_sceenshotWorkProfileFilesApp))
+ when(mMockContext.getString(R.string.config_screenshotFilesApp))
.thenReturn("");
WorkProfileMessageController.WorkProfileFirstRunData data =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt
new file mode 100644
index 0000000..ce2facd
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.message
+
+import android.content.ComponentName
+import android.content.pm.PackageManager
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import com.android.systemui.screenshot.data.model.ProfileType
+import com.android.systemui.screenshot.data.repository.ProfileTypeRepository
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class ProfileMessageControllerTest {
+ @Test
+ fun personalScreenshot() = runTest {
+ assertThat(
+ getMessageController()
+ .onScreenshotTaken(UserHandle.of(profileTypeRepository.personalUser))
+ )
+ .isNull()
+ }
+
+ @Test
+ fun communalScreenshot() = runTest {
+ assertThat(
+ getMessageController()
+ .onScreenshotTaken(UserHandle.of(profileTypeRepository.communalUser))
+ )
+ .isNull()
+ }
+
+ @Test
+ fun noUserScreenshot() = runTest {
+ assertThat(getMessageController().onScreenshotTaken(null)).isNull()
+ }
+
+ @Test
+ fun alreadyDismissed() = runTest {
+ val messageController = getMessageController()
+ profileFirstRunSettings.onMessageDismissed(ProfileMessageController.FirstRunProfile.WORK)
+ assertThat(
+ messageController.onScreenshotTaken(UserHandle.of(profileTypeRepository.workUser))
+ )
+ .isNull()
+ }
+
+ @Test
+ fun noFileManager() = runTest {
+ val messageController = getMessageController(fileManagerComponent = null)
+ val data =
+ messageController.onScreenshotTaken(UserHandle.of(profileTypeRepository.workUser))
+ assertThat(data?.profileType).isEqualTo(ProfileMessageController.FirstRunProfile.WORK)
+ assertThat(data?.labeledIcon?.label).isEqualTo(DEFAULT_APP_NAME)
+ assertThat(data?.labeledIcon?.badgedIcon).isNull()
+ }
+
+ @Test
+ fun fileManagerNotFound() = runTest {
+ val messageController =
+ getMessageController(fileManagerComponent = ComponentName("Something", "Random"))
+ val data =
+ messageController.onScreenshotTaken(UserHandle.of(profileTypeRepository.privateUser))
+ assertThat(data?.profileType).isEqualTo(ProfileMessageController.FirstRunProfile.PRIVATE)
+ assertThat(data?.labeledIcon?.label).isEqualTo(DEFAULT_APP_NAME)
+ assertThat(data?.labeledIcon?.badgedIcon).isNull()
+ }
+
+ @Test
+ fun fileManagerFound() = runTest {
+ val messageController = getMessageController()
+ val data =
+ messageController.onScreenshotTaken(UserHandle.of(profileTypeRepository.privateUser))
+ assertThat(data?.profileType).isEqualTo(ProfileMessageController.FirstRunProfile.PRIVATE)
+ assertThat(data?.labeledIcon?.label).isEqualTo(FILE_MANAGER_LABEL)
+ assertThat(data?.labeledIcon?.badgedIcon).isEqualTo(drawable)
+ }
+
+ private val drawable =
+ object : Drawable() {
+ override fun draw(canvas: Canvas) {}
+
+ override fun setAlpha(alpha: Int) {}
+
+ override fun setColorFilter(colorFilter: ColorFilter?) {}
+
+ override fun getOpacity(): Int = 0
+ }
+
+ private val packageLabelIconProvider =
+ object : PackageLabelIconProvider {
+ override suspend fun getPackageLabelIcon(
+ componentName: ComponentName,
+ userHandle: UserHandle
+ ): LabeledIcon {
+ if (componentName.equals(FILE_MANAGER_COMPONENT)) {
+ return LabeledIcon(FILE_MANAGER_LABEL, drawable)
+ } else {
+ throw PackageManager.NameNotFoundException()
+ }
+ }
+ }
+
+ private class FakeProfileFirstRunResources(private val fileManager: ComponentName?) :
+ ProfileFirstRunFileResources {
+ override fun fileManagerComponentName(): ComponentName? {
+ return fileManager
+ }
+
+ override fun defaultFileApp() = LabeledIcon(DEFAULT_APP_NAME, badgedIcon = null)
+ }
+
+ private val profileFirstRunSettings =
+ object : ProfileFirstRunSettings {
+ private val dismissed =
+ mutableMapOf(
+ ProfileMessageController.FirstRunProfile.WORK to false,
+ ProfileMessageController.FirstRunProfile.PRIVATE to false,
+ )
+
+ override fun messageAlreadyDismissed(
+ profileType: ProfileMessageController.FirstRunProfile
+ ): Boolean {
+ return dismissed.getOrDefault(profileType, false)
+ }
+
+ override fun onMessageDismissed(profileType: ProfileMessageController.FirstRunProfile) {
+ dismissed[profileType] = true
+ }
+ }
+
+ private val profileTypeRepository =
+ object : ProfileTypeRepository {
+ override suspend fun getProfileType(userId: Int): ProfileType {
+ return when (userId) {
+ workUser -> ProfileType.WORK
+ privateUser -> ProfileType.PRIVATE
+ communalUser -> ProfileType.COMMUNAL
+ else -> ProfileType.NONE
+ }
+ }
+
+ val personalUser = 0
+ val workUser = 1
+ val privateUser = 2
+ val communalUser = 3
+ }
+
+ private fun getMessageController(
+ fileManagerComponent: ComponentName? = FILE_MANAGER_COMPONENT
+ ) =
+ ProfileMessageController(
+ packageLabelIconProvider,
+ FakeProfileFirstRunResources(fileManagerComponent),
+ profileFirstRunSettings,
+ profileTypeRepository
+ )
+
+ companion object {
+ val FILE_MANAGER_COMPONENT = ComponentName("package", "component")
+ const val DEFAULT_APP_NAME = "default app"
+ const val FILE_MANAGER_LABEL = "file manager"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 0a9bac9..7ade053 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -49,6 +49,7 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.Flags;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.PendingIntent;
@@ -58,6 +59,7 @@
import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.platform.test.annotations.DisableFlags;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
@@ -469,6 +471,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
public void testShouldHeadsUp_oldWhen_whenZero() throws Exception {
ensureStateForHeadsUpWhenAwake();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
index 4dd97bc..9b4f931 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
@@ -17,19 +17,21 @@
package com.android.systemui.statusbar.phone
import android.content.pm.PackageManager
-import android.testing.AndroidTestingRunner
+import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED
@@ -58,15 +60,17 @@
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(ParameterizedAndroidJunit4::class)
@TestableLooper.RunWithLooper
-class KeyguardBypassControllerTest : SysuiTestCase() {
+class KeyguardBypassControllerTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val featureFlags = FakeFeatureFlags()
- private val shadeRepository = FakeShadeRepository()
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
private lateinit var keyguardBypassController: KeyguardBypassController
private lateinit var postureControllerCallback: DevicePostureController.Callback
@@ -79,6 +83,18 @@
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var packageManager: PackageManager
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Captor
private val postureCallbackCaptor =
ArgumentCaptor.forClass(DevicePostureController.Callback::class.java)
@@ -148,7 +164,7 @@
statusBarStateController,
lockscreenUserManager,
keyguardStateController,
- shadeRepository,
+ { kosmos.shadeInteractor },
devicePostureController,
keyguardTransitionInteractor,
dumpManager,
@@ -293,13 +309,13 @@
testScope.runTest {
initKeyguardBypassController()
assertThat(keyguardBypassController.qsExpanded).isFalse()
- val job = keyguardBypassController.listenForQsExpandedChange(this)
- shadeRepository.setQsExpansion(0.5f)
+ val job = keyguardBypassController.listenForQsExpandedChange()
+ shadeTestUtil.setQsExpansion(0.5f)
runCurrent()
assertThat(keyguardBypassController.qsExpanded).isTrue()
- shadeRepository.setQsExpansion(0f)
+ shadeTestUtil.setQsExpansion(0f)
runCurrent()
assertThat(keyguardBypassController.qsExpanded).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index d365663..ba38f87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -314,6 +314,7 @@
private class UnfoldConfig : UnfoldTransitionConfig {
override var isEnabled: Boolean = false
override var isHingeAngleEnabled: Boolean = false
+ override val isHapticsEnabled: Boolean = false
override val halfFoldedTimeoutMillis: Int = 0
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index efd7f99..05464f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -23,6 +23,7 @@
import android.app.PendingIntent
import android.app.Person
import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.service.notification.NotificationListenerService.REASON_USER_STOPPED
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
@@ -194,7 +195,7 @@
/** Regression test for b/192379214. */
@Test
- @DisableFlags(android.app.Flags.FLAG_UPDATE_RANKING_TIME)
+ @DisableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
fun onEntryUpdated_notificationWhenIsZero_timeHidden() {
val notification = NotificationEntryBuilder(createOngoingCallNotifEntry())
notification.modifyNotification(context).setWhen(0)
@@ -210,6 +211,22 @@
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
+ fun onEntryUpdated_notificationWhenIsZero_timeShown() {
+ val notification = NotificationEntryBuilder(createOngoingCallNotifEntry())
+ notification.modifyNotification(context).setWhen(0)
+
+ notifCollectionListener.onEntryUpdated(notification.build())
+ chipView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ )
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_call_chip_time)?.measuredWidth)
+ .isGreaterThan(0)
+ }
+
+ @Test
fun onEntryUpdated_notificationWhenIsValid_timeShown() {
val notification = NotificationEntryBuilder(createOngoingCallNotifEntry())
notification.modifyNotification(context).setWhen(clock.currentTimeMillis())
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 9d14116..3695d8c 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
@@ -35,6 +35,7 @@
import android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX
import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
import android.telephony.TelephonyCallback
+import android.telephony.TelephonyCallback.CarrierRoamingNtnModeListener
import android.telephony.TelephonyCallback.DataActivityListener
import android.telephony.TelephonyCallback.DisplayInfoListener
import android.telephony.TelephonyCallback.ServiceStateListener
@@ -983,26 +984,19 @@
@Test
@EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
- fun isNonTerrestrial_updatesFromServiceState() =
+ fun isNonTerrestrial_updatesFromCallback0() =
testScope.runTest {
val latest by collectLastValue(underTest.isNonTerrestrial)
- // Lambda makes it a little clearer what we are testing IMO
- val serviceStateCreator = { ntn: Boolean ->
- mock<ServiceState>().also {
- whenever(it.isUsingNonTerrestrialNetwork).thenReturn(ntn)
- }
- }
-
// Starts out false
assertThat(latest).isFalse()
- getTelephonyCallbackForType<ServiceStateListener>()
- .onServiceStateChanged(serviceStateCreator(true))
+ val callback = getTelephonyCallbackForType<CarrierRoamingNtnModeListener>()
+
+ callback.onCarrierRoamingNtnModeChanged(true)
assertThat(latest).isTrue()
- getTelephonyCallbackForType<ServiceStateListener>()
- .onServiceStateChanged(serviceStateCreator(false))
+ callback.onCarrierRoamingNtnModeChanged(false)
assertThat(latest).isFalse()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
index 8eea29b..ceaae9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
@@ -587,7 +587,7 @@
advanceTimeBy(10.seconds)
assertThat(latest)
- .isEqualTo(context.getString(R.string.satellite_not_connected_carrier_text))
+ .isEqualTo(context.getString(R.string.satellite_connected_carrier_text))
}
@OptIn(ExperimentalCoroutinesApi::class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
index bdd3d18..cfa734a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
@@ -16,71 +16,69 @@
package com.android.systemui.statusbar.ui.viewmodel
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.fromGoneTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.flags.andSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.kosmos.testScope
-import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.data.repository.FakeKeyguardStatusBarRepository
-import com.android.systemui.statusbar.domain.interactor.KeyguardStatusBarInteractor
-import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
+import com.android.systemui.statusbar.domain.interactor.keyguardStatusBarInteractor
import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.batteryController
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
+import org.junit.runner.RunWith
import org.mockito.Mockito.verify
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
-class KeyguardStatusBarViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class KeyguardStatusBarViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val keyguardRepository = FakeKeyguardRepository()
- private val keyguardInteractor =
- KeyguardInteractor(
- keyguardRepository,
- mock<CommandQueue>(),
- PowerInteractorFactory.create().powerInteractor,
- FakeKeyguardBouncerRepository(),
- ConfigurationInteractor(FakeConfigurationRepository()),
- FakeShadeRepository(),
- kosmos.keyguardTransitionInteractor,
- { kosmos.sceneInteractor },
- { kosmos.fromGoneTransitionInteractor },
- { kosmos.sharedNotificationContainerInteractor },
- testScope,
- )
- private val keyguardStatusBarInteractor =
- KeyguardStatusBarInteractor(
- FakeKeyguardStatusBarRepository(),
- )
- private val batteryController = mock<BatteryController>()
+ private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+ private val keyguardInteractor by lazy { kosmos.keyguardInteractor }
+ private val keyguardStatusBarInteractor by lazy { kosmos.keyguardStatusBarInteractor }
+ private val batteryController = kosmos.batteryController
- private val underTest =
- KeyguardStatusBarViewModel(
- testScope.backgroundScope,
- keyguardInteractor,
- keyguardStatusBarInteractor,
- batteryController,
- )
+ lateinit var underTest: KeyguardStatusBarViewModel
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
+ @Before
+ fun setup() {
+ underTest =
+ KeyguardStatusBarViewModel(
+ testScope.backgroundScope,
+ keyguardInteractor,
+ keyguardStatusBarInteractor,
+ batteryController,
+ )
+ }
@Test
fun isVisible_dozing_false() =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt
deleted file mode 100644
index b1df159..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.revealeffect
-
-import android.graphics.RenderEffect
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.animation.AnimatorTestRule
-import com.android.systemui.model.SysUiStateTest
-import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-class RippleRevealEffectTest : SysUiStateTest() {
-
- @get:Rule val animatorTestRule = AnimatorTestRule(this)
-
- @Test
- fun play_triggersDrawCallback() {
- var effectFromCallback: RenderEffect? = null
- val revealEffectConfig = RippleRevealEffectConfig(duration = 1000f)
- val drawCallback =
- object : RenderEffectDrawCallback {
- override fun onDraw(renderEffect: RenderEffect) {
- effectFromCallback = renderEffect
- }
- }
- val revealEffect = RippleRevealEffect(revealEffectConfig, drawCallback)
- assertThat(effectFromCallback).isNull()
-
- revealEffect.play()
-
- animatorTestRule.advanceTimeBy(500L)
-
- assertThat(effectFromCallback).isNotNull()
- }
-
- @Test
- fun play_triggersStateChangedCallback() {
- val revealEffectConfig = RippleRevealEffectConfig(duration = 1000f)
- val drawCallback =
- object : RenderEffectDrawCallback {
- override fun onDraw(renderEffect: RenderEffect) {}
- }
- var animationStartedCalled = false
- var animationEndedCalled = false
- val stateChangedCallback =
- object : RippleRevealEffect.AnimationStateChangedCallback {
- override fun onAnimationStart() {
- animationStartedCalled = true
- }
-
- override fun onAnimationEnd() {
- animationEndedCalled = true
- }
- }
- val revealEffect =
- RippleRevealEffect(revealEffectConfig, drawCallback, stateChangedCallback)
-
- assertThat(animationStartedCalled).isFalse()
- assertThat(animationEndedCalled).isFalse()
-
- revealEffect.play()
-
- assertThat(animationStartedCalled).isTrue()
-
- animatorTestRule.advanceTimeBy(revealEffectConfig.duration.toLong())
-
- assertThat(animationEndedCalled).isTrue()
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
index fd513c9..06f1a88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
@@ -17,13 +17,12 @@
import android.os.VibrationAttributes
import android.os.VibrationEffect
-import android.os.Vibrator
+import android.os.vibrator
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.util.TestFoldProvider
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -35,15 +34,20 @@
@SmallTest
class UnfoldHapticsPlayerTest : SysuiTestCase() {
- private val progressProvider = FakeUnfoldTransitionProvider()
- private val vibrator: Vibrator = mock()
- private val testFoldProvider = TestFoldProvider()
+ private val kosmos = testKosmos()
+
+ private val progressProvider = kosmos.fakeUnfoldTransitionProgressProvider
+ private val vibrator = kosmos.vibrator
+ private val transitionConfig = kosmos.unfoldTransitionConfig
+ private val testFoldProvider = kosmos.foldProvider
private lateinit var player: UnfoldHapticsPlayer
@Before
fun before() {
- player = UnfoldHapticsPlayer(progressProvider, testFoldProvider, Runnable::run, vibrator)
+ transitionConfig.isHapticsEnabled = true
+ player = UnfoldHapticsPlayer(progressProvider, testFoldProvider, transitionConfig,
+ Runnable::run, vibrator)
}
@Test
@@ -58,6 +62,21 @@
}
@Test
+ fun testHapticsDisabled_unfoldingTransitionFinishing_doesNotPlayHaptics() {
+ transitionConfig.isHapticsEnabled = false
+ player = UnfoldHapticsPlayer(progressProvider, testFoldProvider, transitionConfig,
+ Runnable::run, vibrator)
+
+ testFoldProvider.onFoldUpdate(isFolded = true)
+ testFoldProvider.onFoldUpdate(isFolded = false)
+ progressProvider.onTransitionStarted()
+ progressProvider.onTransitionProgress(0.5f)
+ progressProvider.onTransitionFinishing()
+
+ verify(vibrator).vibrate(any<VibrationEffect>(), any<VibrationAttributes>())
+ }
+
+ @Test
fun testUnfoldingTransitionFinishingLate_doesNotPlayHaptics() {
testFoldProvider.onFoldUpdate(isFolded = true)
testFoldProvider.onFoldUpdate(isFolded = false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTestUtilsKosmos.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTestUtilsKosmos.kt
new file mode 100644
index 0000000..c073903
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTestUtilsKosmos.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold
+
+import com.android.systemui.unfold.util.TestFoldProvider
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.unfold.config.TestUnfoldTransitionConfig
+
+var Kosmos.foldProvider: TestFoldProvider by Kosmos.Fixture { TestFoldProvider() }
+
+var Kosmos.unfoldTransitionConfig: TestUnfoldTransitionConfig
+ by Kosmos.Fixture { TestUnfoldTransitionConfig() }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
index ab450e2..3c53997 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
@@ -47,6 +47,12 @@
}
@Test
+ fun testHapticsEnabled() {
+ assertThat(config.isHapticsEnabled).isEqualTo(mContext.resources
+ .getBoolean(com.android.internal.R.bool.config_unfoldTransitionHapticsEnabled))
+ }
+
+ @Test
fun testHalfFoldedTimeout() {
assertThat(config.halfFoldedTimeoutMillis).isEqualTo(mContext.resources
.getInteger(com.android.internal.R.integer.config_unfoldTransitionHalfFoldedTimeout))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/config/TestUnfoldTransitionConfig.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/TestUnfoldTransitionConfig.kt
new file mode 100644
index 0000000..0586115
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/TestUnfoldTransitionConfig.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold.config
+
+class TestUnfoldTransitionConfig(
+ override var isEnabled: Boolean = false,
+ override var isHingeAngleEnabled: Boolean = false,
+ override var isHapticsEnabled: Boolean = false,
+ override var halfFoldedTimeoutMillis: Int = 1000
+) : UnfoldTransitionConfig
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
index 5d34120..8d26c87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.util.service;
-import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -118,6 +116,7 @@
connection.addCallback(mCallback);
mExecutor.runAllReady();
connection.bind();
+ mExecutor.runAllReady();
when(mTransformer.convert(eq(mBinder))).thenReturn(mResult);
@@ -143,8 +142,8 @@
when(mContext.bindServiceAsUser(eq(mIntent), eq(connection), anyInt(),
eq(UserHandle.of(MAIN_USER_ID)))).thenReturn(true);
connection.bind();
+ mExecutor.runAllReady();
connection.onServiceDisconnected(mComponentName);
-
mExecutor.runAllReady();
// Ensure proper disconnect reason reported back
@@ -157,6 +156,7 @@
clearInvocations(mContext);
// Ensure unbind after disconnect has no effect on the connection
connection.unbind();
+ mExecutor.runAllReady();
verify(mContext, never()).unbindService(eq(connection));
}
@@ -197,7 +197,8 @@
// Verify that the exception was caught and that bind returns false, and we properly
// unbind.
- assertThat(connection.bind()).isFalse();
+ connection.bind();
+ mExecutor.runAllReady();
verify(mContext).unbindService(connection);
}
@@ -212,13 +213,15 @@
.thenThrow(new SecurityException());
// Verify that bind returns false and we properly unbind.
- assertThat(connection.bind()).isFalse();
+ connection.bind();
+ mExecutor.runAllReady();
verify(mContext).unbindService(connection);
clearInvocations(mContext);
// Ensure unbind after the failed bind has no effect.
connection.unbind();
+ mExecutor.runAllReady();
verify(mContext, never()).unbindService(eq(connection));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index db998f3..56e5e29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -77,10 +77,10 @@
import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
import android.service.dreams.IDreamManager;
import android.service.notification.NotificationListenerService;
import android.service.notification.ZenModeConfig;
-import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Pair;
import android.util.SparseArray;
@@ -99,46 +99,28 @@
import com.android.launcher3.icons.BubbleIconFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.SceneContainerFlagParameterizationKt;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.data.repository.FakeCommandQueue;
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor;
-import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.scene.FakeWindowRootViewComponent;
-import com.android.systemui.scene.data.repository.SceneContainerRepository;
-import com.android.systemui.scene.domain.interactor.SceneInteractor;
-import com.android.systemui.scene.shared.logger.SceneLogger;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shade.LargeScreenHeaderHelper;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeWindowLogger;
-import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
-import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl;
-import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.NotificationEntryHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -154,7 +136,6 @@
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProviderTestUtil;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -163,13 +144,10 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository;
-import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.android.systemui.user.domain.interactor.UserSwitcherInteractor;
import com.android.systemui.util.FakeEventLog;
import com.android.systemui.util.settings.FakeGlobalSettings;
import com.android.systemui.util.settings.SystemSettings;
@@ -207,8 +185,6 @@
import com.android.wm.shell.taskview.TaskViewTransitions;
import com.android.wm.shell.transition.Transitions;
-import kotlinx.coroutines.test.TestScope;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -227,8 +203,11 @@
import java.util.Optional;
import java.util.concurrent.Executor;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(ParameterizedAndroidJunit4.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class BubblesTest extends SysuiTestCase {
@Mock
@@ -338,8 +317,6 @@
@Mock
private KeyguardStateController mKeyguardStateController;
@Mock
- private ScreenOffAnimationController mScreenOffAnimationController;
- @Mock
Transitions mTransitions;
@Mock
private Optional<OneHandedController> mOneHandedOptional;
@@ -357,11 +334,8 @@
private Icon mAppBubbleIcon;
@Mock
private Display mDefaultDisplay;
- @Mock
- private LargeScreenHeaderHelper mLargeScreenHeaderHelper;
private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
- private final TestScope mTestScope = mKosmos.getTestScope();
private ShadeInteractor mShadeInteractor;
private ShellTaskOrganizer mShellTaskOrganizer;
private TaskViewTransitions mTaskViewTransitions;
@@ -378,8 +352,16 @@
private UserHandle mUser0;
private FakeBubbleProperties mBubbleProperties;
- private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor;
- private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor;
+
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getParams() {
+ return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag();
+ }
+
+ public BubblesTest(FlagsParameterization flags) {
+ mSetFlagsRule.setFlagsParameterization(flags);
+ }
+
@Before
public void setUp() throws Exception {
@@ -404,77 +386,14 @@
FakeDeviceProvisioningRepository deviceProvisioningRepository =
- new FakeDeviceProvisioningRepository();
+ mKosmos.getFakeDeviceProvisioningRepository();
deviceProvisioningRepository.setDeviceProvisioned(true);
- FakeKeyguardRepository keyguardRepository = new FakeKeyguardRepository();
- FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
- FakeShadeRepository shadeRepository = new FakeShadeRepository();
- FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository();
-
- PowerInteractor powerInteractor = new PowerInteractor(
- mKosmos.getPowerRepository(),
- mKosmos.getFalsingCollector(),
- mock(ScreenOffAnimationController.class),
- mStatusBarStateController);
-
- SceneInteractor sceneInteractor = new SceneInteractor(
- mTestScope.getBackgroundScope(),
- new SceneContainerRepository(
- mTestScope.getBackgroundScope(),
- mKosmos.getFakeSceneContainerConfig(),
- mKosmos.getSceneDataSource()),
- mock(SceneLogger.class),
- mKosmos.getDeviceUnlockedInteractor());
-
- KeyguardTransitionInteractor keyguardTransitionInteractor =
- mKosmos.getKeyguardTransitionInteractor();
- KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
- keyguardRepository,
- new FakeCommandQueue(),
- powerInteractor,
- new FakeKeyguardBouncerRepository(),
- new ConfigurationInteractor(configurationRepository),
- shadeRepository,
- keyguardTransitionInteractor,
- () -> sceneInteractor,
- () -> mKosmos.getFromGoneTransitionInteractor(),
- () -> mKosmos.getSharedNotificationContainerInteractor(),
- mTestScope);
-
- mFromLockscreenTransitionInteractor = mKosmos.getFromLockscreenTransitionInteractor();
- mFromPrimaryBouncerTransitionInteractor =
- mKosmos.getFromPrimaryBouncerTransitionInteractor();
-
- ResourcesSplitShadeStateController splitShadeStateController =
- new ResourcesSplitShadeStateController();
DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
mock(DeviceEntryUdfpsInteractor.class);
when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
- mShadeInteractor =
- new ShadeInteractorImpl(
- mTestScope.getBackgroundScope(),
- mKosmos.getDeviceProvisioningInteractor(),
- new FakeDisableFlagsRepository(),
- mDozeParameters,
- keyguardRepository,
- keyguardTransitionInteractor,
- powerInteractor,
- new FakeUserSetupRepository(),
- mock(UserSwitcherInteractor.class),
- new ShadeInteractorLegacyImpl(
- mTestScope.getBackgroundScope(), keyguardRepository,
- new SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- splitShadeStateController,
- keyguardInteractor,
- deviceEntryUdfpsInteractor,
- () -> mLargeScreenHeaderHelper),
- shadeRepository
- )
- );
+ mShadeInteractor = mKosmos.getShadeInteractor();
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
mContext,
@@ -491,7 +410,6 @@
mColorExtractor,
mDumpManager,
mKeyguardStateController,
- mScreenOffAnimationController,
mAuthController,
() -> mShadeInteractor,
mShadeWindowLogger,
@@ -2470,6 +2388,10 @@
mStateChangeCalls++;
mLastUpdate = update;
}
+
+ @Override
+ public void animateBubbleBarLocation(BubbleBarLocation location) {
+ }
}
private static class FakeBubbleProperties implements BubbleProperties {
diff --git a/packages/SystemUI/tests/utils/src/android/os/VibratorKosmos.kt b/packages/SystemUI/tests/utils/src/android/os/VibratorKosmos.kt
new file mode 100644
index 0000000..872b25c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/android/os/VibratorKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+var Kosmos.vibrator by Kosmos.Fixture { mock<Vibrator>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
index e83205c5..1107971 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
@@ -21,11 +21,9 @@
import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR
import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR
import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
-import com.android.systemui.Flags.FLAG_MEDIA_IN_SCENE_CONTAINER
import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
import com.android.systemui.Flags.FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR
import com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_SYSUI
-import com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
/**
@@ -36,13 +34,11 @@
FLAG_COMPOSE_LOCKSCREEN,
FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR,
FLAG_KEYGUARD_WM_STATE_REFACTOR,
- FLAG_MEDIA_IN_SCENE_CONTAINER,
FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR,
FLAG_PREDICTIVE_BACK_SYSUI,
FLAG_SCENE_CONTAINER,
FLAG_DEVICE_ENTRY_UDFPS_REFACTOR,
- FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
)
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..71ad3c6
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelKosmos.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.alternateBouncerToOccludedTransitionViewModel by Fixture {
+ AlternateBouncerToOccludedTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index d4b7937..a81ac03 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -56,7 +56,6 @@
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.shadeController
import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
-import com.android.systemui.statusbar.phone.screenOffAnimationController
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
@@ -90,7 +89,6 @@
val simBouncerInteractor by lazy { kosmos.simBouncerInteractor }
val statusBarStateController by lazy { kosmos.statusBarStateController }
val interactionJankMonitor by lazy { kosmos.interactionJankMonitor }
- val screenOffAnimationController by lazy { kosmos.screenOffAnimationController }
val fakeSceneContainerConfig by lazy { kosmos.sceneContainerConfig }
val sceneInteractor by lazy { kosmos.sceneInteractor }
val falsingCollector by lazy { kosmos.falsingCollector }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
index 7dab5c2..690bde7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
@@ -16,7 +16,16 @@
package com.android.systemui.media.controls.data.repository
+import android.content.applicationContext
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.policy.configurationController
import com.android.systemui.util.time.systemClock
-val Kosmos.mediaFilterRepository by Kosmos.Fixture { MediaFilterRepository(systemClock) }
+val Kosmos.mediaFilterRepository by
+ Kosmos.Fixture {
+ MediaFilterRepository(
+ applicationContext = applicationContext,
+ systemClock = systemClock,
+ configurationController = configurationController
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
index 6eae28f..069995a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.controls.ui.viewmodel
import android.content.applicationContext
+import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
@@ -32,6 +33,7 @@
applicationScope = applicationCoroutineScope,
applicationContext = applicationContext,
backgroundDispatcher = testDispatcher,
+ backgroundExecutor = fakeExecutor,
visualStabilityProvider = visualStabilityProvider,
interactor = mediaCarouselInteractor,
controlInteractorFactory = mediaControlInteractorFactory,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
index b3fb15f..2f3d3c3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
@@ -17,8 +17,8 @@
package com.android.systemui.media.controls.ui.viewmodel
import android.content.applicationContext
+import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.media.controls.domain.pipeline.interactor.mediaControlInteractor
import com.android.systemui.media.controls.util.mediaUiEventLogger
@@ -26,9 +26,9 @@
val Kosmos.mediaControlViewModel by
Kosmos.Fixture {
MediaControlViewModel(
- applicationScope = applicationCoroutineScope,
applicationContext = applicationContext,
backgroundDispatcher = testDispatcher,
+ backgroundExecutor = fakeExecutor,
interactor = mediaControlInteractor,
logger = mediaUiEventLogger,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
index 0de76c8..3f91122 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
@@ -94,6 +94,7 @@
falsingManager = falsingManager,
footerActionsInteractor = footerActionsInteractor,
globalActionsDialogLiteProvider = { mock() },
+ activityStarter,
showPowerButton = true,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
index cddb007..cde5d4e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
@@ -68,6 +68,7 @@
private val testableLooper: TestableLooper,
private val scheduler: TestCoroutineScheduler,
) {
+ private val mockActivityStarter: ActivityStarter = mock<ActivityStarter>()
/** Enable or disable the user switcher in the settings. */
fun setUserSwitcherEnabled(settings: GlobalSettings, enabled: Boolean) {
settings.putBool(Settings.Global.USER_SWITCHER_ENABLED, enabled)
@@ -90,13 +91,14 @@
footerActionsInteractor,
falsingManager,
globalActionsDialogLite,
+ mockActivityStarter,
showPowerButton,
)
}
/** Create a [FooterActionsInteractor] to be used in tests. */
fun footerActionsInteractor(
- activityStarter: ActivityStarter = mock(),
+ activityStarter: ActivityStarter = mockActivityStarter,
metricsLogger: MetricsLogger = FakeMetricsLogger(),
uiEventLogger: UiEventLogger = UiEventLoggerFake(),
deviceProvisionedController: DeviceProvisionedController = mock(),
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index 16d08dd..fff3b14 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -32,7 +32,7 @@
val Kosmos.scenes by Fixture { fakeScenes }
val Kosmos.initialSceneKey by Fixture { Scenes.Lockscreen }
-val Kosmos.sceneContainerConfig by Fixture {
+var Kosmos.sceneContainerConfig by Fixture {
val navigationDistances =
mapOf(
Scenes.Gone to 0,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
index c0f5039..ebe591b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
@@ -37,7 +37,7 @@
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
import com.android.systemui.statusbar.notificationShadeWindowController
-import com.android.systemui.statusbar.phone.centralSurfaces
+import com.android.systemui.statusbar.phone.centralSurfacesOptional
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
val Kosmos.sceneContainerStartable by Fixture {
@@ -58,7 +58,7 @@
authenticationInteractor = { authenticationInteractor },
windowController = notificationShadeWindowController,
deviceProvisioningInteractor = deviceProvisioningInteractor,
- centralSurfaces = centralSurfaces,
+ centralSurfacesOptLazy = { centralSurfacesOptional },
headsUpInteractor = headsUpNotificationInteractor,
occlusionInteractor = sceneContainerOcclusionInteractor,
faceUnlockInteractor = deviceEntryFaceAuthInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
index d17dd6c..0101961 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
@@ -23,7 +23,6 @@
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.FakeShadeRepository
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import org.junit.Assert
@@ -33,12 +32,14 @@
/** Sets shade expansion to a value between 0-1. */
fun setShadeExpansion(shadeExpansion: Float) {
- setShadeAndQsExpansion(shadeExpansion, 0f)
+ delegate.assertFlagValid()
+ delegate.setShadeExpansion(shadeExpansion)
}
/** Sets QS expansion to a value between 0-1. */
fun setQsExpansion(qsExpansion: Float) {
- setShadeAndQsExpansion(0f, qsExpansion)
+ delegate.assertFlagValid()
+ delegate.setQsExpansion(qsExpansion)
}
/** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */
@@ -48,7 +49,7 @@
shadeExpansion == 0f || qsExpansion == 0f || shadeExpansion + qsExpansion == 1f,
)
delegate.assertFlagValid()
- delegate.setShadeAndQsExpansionInternal(shadeExpansion, qsExpansion)
+ delegate.setShadeAndQsExpansion(shadeExpansion, qsExpansion)
}
/** Sets the shade expansion on the lockscreen to the given amount from 0-1. */
@@ -56,6 +57,12 @@
delegate.assertFlagValid()
delegate.setLockscreenShadeExpansion(lockscreenShadeExpansion)
}
+
+ /** Sets whether the user is moving the shade with touch input. */
+ fun setLockscreenShadeTracking(lockscreenShadeTracking: Boolean) {
+ delegate.assertFlagValid()
+ delegate.setLockscreenShadeTracking(lockscreenShadeTracking)
+ }
}
/** Sets up shade state for tests for a specific value of the scene container flag. */
@@ -64,16 +71,25 @@
fun assertFlagValid()
/** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */
- fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float)
+ fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float)
/** Sets the shade expansion on the lockscreen to the given amount from 0-1. */
fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float)
+
+ /** Sets whether the user is moving the shade with touch input. */
+ fun setLockscreenShadeTracking(lockscreenShadeTracking: Boolean)
+
+ /** Sets shade expansion to a value between 0-1. */
+ fun setShadeExpansion(shadeExpansion: Float)
+
+ /** Sets QS expansion to a value between 0-1. */
+ fun setQsExpansion(qsExpansion: Float)
}
/** Sets up shade state for tests when the scene container flag is disabled. */
class ShadeTestUtilLegacyImpl(val testScope: TestScope, val shadeRepository: FakeShadeRepository) :
ShadeTestUtilDelegate {
- override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) {
+ override fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) {
shadeRepository.setLegacyShadeExpansion(shadeExpansion)
shadeRepository.setQsExpansion(qsExpansion)
testScope.runCurrent()
@@ -83,24 +99,56 @@
shadeRepository.setLockscreenShadeExpansion(lockscreenShadeExpansion)
}
+ override fun setLockscreenShadeTracking(lockscreenShadeTracking: Boolean) {
+ shadeRepository.setLegacyLockscreenShadeTracking(lockscreenShadeTracking)
+ }
+
override fun assertFlagValid() {
Assert.assertFalse(SceneContainerFlag.isEnabled)
}
+
+ /** Sets shade expansion to a value between 0-1. */
+ override fun setShadeExpansion(shadeExpansion: Float) {
+ shadeRepository.setLegacyShadeExpansion(shadeExpansion)
+ testScope.runCurrent()
+ }
+
+ /** Sets QS expansion to a value between 0-1. */
+ override fun setQsExpansion(qsExpansion: Float) {
+ shadeRepository.setQsExpansion(qsExpansion)
+ testScope.runCurrent()
+ }
}
/** Sets up shade state for tests when the scene container flag is enabled. */
class ShadeTestUtilSceneImpl(val testScope: TestScope, val sceneInteractor: SceneInteractor) :
ShadeTestUtilDelegate {
- override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) {
+ val isUserInputOngoing = MutableStateFlow(true)
+
+ override fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) {
if (shadeExpansion == 0f) {
setTransitionProgress(Scenes.Lockscreen, Scenes.QuickSettings, qsExpansion)
} else if (qsExpansion == 0f) {
setTransitionProgress(Scenes.Lockscreen, Scenes.Shade, shadeExpansion)
+ } else if (shadeExpansion == 1f) {
+ setIdleScene(Scenes.Shade)
+ } else if (qsExpansion == 1f) {
+ setIdleScene(Scenes.QuickSettings)
} else {
setTransitionProgress(Scenes.Shade, Scenes.QuickSettings, qsExpansion)
}
}
+ /** Sets shade expansion to a value between 0-1. */
+ override fun setShadeExpansion(shadeExpansion: Float) {
+ setShadeAndQsExpansion(shadeExpansion, 0f)
+ }
+
+ /** Sets QS expansion to a value between 0-1. */
+ override fun setQsExpansion(qsExpansion: Float) {
+ setShadeAndQsExpansion(0f, qsExpansion)
+ }
+
override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
if (lockscreenShadeExpansion == 0f) {
setIdleScene(Scenes.Lockscreen)
@@ -111,6 +159,10 @@
}
}
+ override fun setLockscreenShadeTracking(lockscreenShadeTracking: Boolean) {
+ isUserInputOngoing.value = lockscreenShadeTracking
+ }
+
private fun setIdleScene(scene: SceneKey) {
sceneInteractor.changeScene(scene, "test")
val transitionState =
@@ -127,8 +179,8 @@
fromScene = from,
toScene = to,
progress = MutableStateFlow(progress),
- isInitiatedByUserInput = false,
- isUserInputOngoing = flowOf(false),
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = isUserInputOngoing,
)
)
sceneInteractor.setTransitionState(transitionState)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
index 4221d06..297d1d8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
@@ -19,6 +19,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.util.mockito.mock
val Kosmos.shadeLockscreenInteractor by
@@ -28,5 +29,6 @@
shadeInteractor = shadeInteractorImpl,
sceneInteractor = sceneInteractor,
lockIconViewController = mock(),
+ shadeRepository = shadeRepository,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryKosmos.kt
new file mode 100644
index 0000000..da95ee9
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryKosmos.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.keyguardStatusBarRepository: FakeKeyguardStatusBarRepository by
+ Kosmos.Fixture { fakeKeyguardStatusBarRepository }
+
+val Kosmos.fakeKeyguardStatusBarRepository: FakeKeyguardStatusBarRepository by
+ Kosmos.Fixture { FakeKeyguardStatusBarRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/KeyguardStatusBarInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/KeyguardStatusBarInteractorKosmos.kt
new file mode 100644
index 0000000..71ed5f6
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/KeyguardStatusBarInteractorKosmos.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.data.repository.keyguardStatusBarRepository
+
+val Kosmos.keyguardStatusBarInteractor: KeyguardStatusBarInteractor by
+ Kosmos.Fixture {
+ KeyguardStatusBarInteractor(
+ keyguardStatusBarRepository,
+ )
+ }
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 cbba80b..d00eedf 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
@@ -21,6 +21,7 @@
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.aodBurnInViewModel
+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.dozingToLockscreenTransitionViewModel
@@ -60,6 +61,7 @@
shadeInteractor = shadeInteractor,
notificationStackAppearanceInteractor = notificationStackAppearanceInteractor,
alternateBouncerToGoneTransitionViewModel = alternateBouncerToGoneTransitionViewModel,
+ aodToGoneTransitionViewModel = aodToGoneTransitionViewModel,
aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
aodToOccludedTransitionViewModel = aodToOccludedTransitionViewModel,
dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/CentralSurfacesKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/CentralSurfacesKosmos.kt
index 1611f62..f71bf03 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/CentralSurfacesKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/CentralSurfacesKosmos.kt
@@ -19,5 +19,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.util.mockito.mock
+import java.util.Optional
+var Kosmos.centralSurfacesOptional by Fixture { Optional.of(centralSurfaces) }
val Kosmos.centralSurfaces by Fixture { mock<CentralSurfaces>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt
index 348a02e..146f109 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.volume.panel
import android.content.res.mainResources
+import com.android.systemui.broadcast.broadcastDispatcher
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.policy.fakeConfigurationController
@@ -69,7 +70,9 @@
Kosmos.Fixture {
VolumePanelViewModel(
mainResources,
+ testScope.backgroundScope,
KosmosVolumePanelComponentFactory(this),
fakeConfigurationController,
+ broadcastDispatcher,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt
index e5f5d4e..1e895b5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt
@@ -32,7 +32,10 @@
class KosmosVolumePanelComponentFactory(private val kosmos: Kosmos) : VolumePanelComponentFactory {
- override fun create(viewModel: VolumePanelViewModel): VolumePanelComponent =
+ override fun create(
+ viewModel: VolumePanelViewModel,
+ scope: CoroutineScope
+ ): VolumePanelComponent =
object : VolumePanelComponent {
override fun coroutineScope(): CoroutineScope = kosmos.testScope.backgroundScope
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
index c513729..ca1daf6 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
@@ -33,6 +33,12 @@
Resources.getSystem().getBoolean(id)
}
+ override val isHapticsEnabled: Boolean by lazy {
+ val id = Resources.getSystem()
+ .getIdentifier("config_unfoldTransitionHapticsEnabled", "bool", "android")
+ Resources.getSystem().getBoolean(id)
+ }
+
override val halfFoldedTimeoutMillis: Int by lazy {
val id = Resources.getSystem()
.getIdentifier("config_unfoldTransitionHalfFoldedTimeout", "integer", "android")
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
index 765e862..1084cb3 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
@@ -18,5 +18,6 @@
interface UnfoldTransitionConfig {
val isEnabled: Boolean
val isHingeAngleEnabled: Boolean
+ val isHapticsEnabled: Boolean
val halfFoldedTimeoutMillis: Int
}
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 3337419..e06f400 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -155,6 +155,31 @@
visibility: ["//frameworks/base"],
}
+cc_library_shared {
+ name: "libravenwood_runtime",
+ host_supported: true,
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+
+ srcs: [
+ "runtime-helper-src/jni/*.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libnativehelper",
+ "libutils",
+ "libcutils",
+ ],
+ visibility: ["//frameworks/base"],
+}
+
// For collecting the *stats.csv files in a known directory under out/host/linux-x86/testcases/.
// The "test" just shows the available stats filenames.
sh_test_host {
diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING
index e77f846f..f6885e1 100644
--- a/ravenwood/TEST_MAPPING
+++ b/ravenwood/TEST_MAPPING
@@ -1,11 +1,18 @@
+// Keep the following two TEST_MAPPINGs in sync:
+// frameworks/base/ravenwood/TEST_MAPPING
+// frameworks/base/tools/hoststubgen/TEST_MAPPING
{
"presubmit": [
+ { "name": "tiny-framework-dump-test" },
+ { "name": "hoststubgentest" },
+ { "name": "hoststubgen-invoke-test" },
{
"name": "RavenwoodMockitoTest_device"
},
{
"name": "RavenwoodBivalentTest_device"
},
+ // The sysui tests should match vendor/unbundled_google/packages/SystemUIGoogle/TEST_MAPPING
{
"name": "SystemUIGoogleTests",
"options": [
@@ -18,6 +25,19 @@
]
}
],
+ "presubmit-large": [
+ {
+ "name": "SystemUITests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ],
"ravenwood-presubmit": [
{
"name": "RavenwoodMinimumTest",
diff --git a/ravenwood/bivalenttest/Android.bp b/ravenwood/bivalenttest/Android.bp
index a6b6ed9..2d94894 100644
--- a/ravenwood/bivalenttest/Android.bp
+++ b/ravenwood/bivalenttest/Android.bp
@@ -45,7 +45,6 @@
jni_libs: [
"libravenwoodbivalenttest_jni",
],
- sdk_version: "test_current",
auto_gen_config: true,
}
diff --git a/ravenwood/bivalenttest/AndroidTest.xml b/ravenwood/bivalenttest/AndroidTest.xml
index ac4695b..9e5dd11 100644
--- a/ravenwood/bivalenttest/AndroidTest.xml
+++ b/ravenwood/bivalenttest/AndroidTest.xml
@@ -25,5 +25,8 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.ravenwood.bivalenttest" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+
+ <!-- Need to use MODULE_LIBRARIES APIs, so no hidden API check. -->
+ <option name="hidden-api-checks" value="false" />
</test>
</configuration>
diff --git a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp b/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
index 83f756e..956d79c 100644
--- a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
+++ b/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
@@ -15,19 +15,70 @@
*/
#include <nativehelper/JNIHelp.h>
+#include <atomic>
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"
+// JNI methods for RavenwoodJniTest
+
static jint add(JNIEnv* env, jclass clazz, jint a, jint b) {
return a + b;
}
-static const JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods_JniTest[] =
{
{ "add", "(II)I", (void*)add },
};
+// JNI methods for RavenwoodNativeAllocationRegistryTest
+std::atomic<int> numTotalAlloc = 0;
+
+class NarTestData {
+public:
+ NarTestData(jint v): value(v) {
+ numTotalAlloc++;
+ }
+
+ ~NarTestData() {
+ value = -1;
+ numTotalAlloc--;
+ }
+
+ volatile jint value;
+};
+
+static jlong NarTestData_nMalloc(JNIEnv* env, jclass clazz, jint value) {
+ NarTestData* p = new NarTestData(value);
+ return reinterpret_cast<jlong>(p);
+}
+
+static jint NarTestData_nGet(JNIEnv* env, jclass clazz, jlong ptr) {
+ NarTestData* p = reinterpret_cast<NarTestData*>(ptr);
+ return p->value;
+}
+
+static void NarTestData_free(jlong ptr) {
+ NarTestData* p = reinterpret_cast<NarTestData*>(ptr);
+ delete p;
+}
+
+static jlong NarTestData_nGetNativeFinalizer(JNIEnv* env, jclass clazz) {
+ return reinterpret_cast<jlong>(NarTestData_free);
+}
+
+static jint NarTestData_nGetTotalAlloc(JNIEnv* env, jclass clazz) {
+ return numTotalAlloc;
+}
+
+static const JNINativeMethod sMethods_NarTestData[] =
+{
+ { "nMalloc", "(I)J", (void*)NarTestData_nMalloc },
+ { "nGet", "(J)I", (void*)NarTestData_nGet },
+ { "nGetNativeFinalizer", "()J", (void*)NarTestData_nGetNativeFinalizer },
+ { "nGetTotalAlloc", "()I", (void*)NarTestData_nGetTotalAlloc },
+};
+
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
@@ -43,7 +94,13 @@
int res = jniRegisterNativeMethods(env,
"com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest",
- sMethods, NELEM(sMethods));
+ sMethods_JniTest, NELEM(sMethods_JniTest));
+ if (res < 0) {
+ return res;
+ }
+ res = jniRegisterNativeMethods(env,
+ "com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest$Data",
+ sMethods_NarTestData, NELEM(sMethods_NarTestData));
if (res < 0) {
return res;
}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
index 59467e9..0cc2adc 100644
--- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
@@ -29,6 +29,10 @@
@RunWith(AndroidJUnit4.class)
public final class RavenwoodJniTest {
static {
+ initializeJni();
+ }
+
+ public static void initializeJni() {
RavenwoodUtils.loadJniLibrary("ravenwoodbivalenttest_jni");
}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java
new file mode 100644
index 0000000..415b467
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.bivalenttest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import libcore.util.NativeAllocationRegistry;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodNativeAllocationRegistryTest {
+ private static final String TAG = RavenwoodNativeAllocationRegistryTest.class.getSimpleName();
+ static {
+ RavenwoodJniTest.initializeJni();
+ }
+
+ @Rule
+ public final RavenwoodRule mRavenwoodRule = new RavenwoodRule();
+
+ private static class Data {
+ private final long mNativePtr;
+
+ private static native long nMalloc(int value);
+ private static native int nGet(long ptr);
+ private static native long nGetNativeFinalizer();
+
+ public static native int nGetTotalAlloc();
+
+ public int get() {
+ return nGet(mNativePtr);
+ }
+
+ private static class NarHolder {
+ public static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ Data.class.getClassLoader(), nGetNativeFinalizer());
+ }
+
+ public Data(int value) {
+ mNativePtr = nMalloc(value);
+ NarHolder.sRegistry.registerNativeAllocation(this, mNativePtr);
+ }
+ }
+
+ @Test
+ public void testNativeAllocationRegistry() {
+
+ final long timeoutTime = mRavenwoodRule.realCurrentTimeMillis() + 10_000;
+
+ final int startAlloc = Data.nGetTotalAlloc();
+
+ int totalAlloc = 0;
+
+ // Keep allocation new objects, until some get released.
+
+ while (true) {
+ for (int i = 0; i < 1000; i++) {
+ totalAlloc++;
+ Data d = new Data(i);
+ assertEquals(i, d.get());
+ }
+ System.gc();
+
+ final int currentAlloc = Data.nGetTotalAlloc() - startAlloc;
+ Log.i(TAG, "# of currently allocated objects=" + currentAlloc);
+
+ if (currentAlloc < totalAlloc) {
+ break; // Good, some objects have been released;
+ }
+ if (mRavenwoodRule.realCurrentTimeMillis() > timeoutTime) {
+ fail("No objects have been released before timeout");
+ }
+ }
+ }
+}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
index 21d8019..9d12f85 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
@@ -426,4 +426,15 @@
return ENABLE_OPTIONAL_VALIDATION;
}
}
+
+ /**
+ * Returns the "real" result from {@link System#currentTimeMillis()}.
+ *
+ * Currently, it's the same thing as calling {@link System#currentTimeMillis()},
+ * but this one is guaranteeed to return the real value, even when Ravenwood supports
+ * injecting a time to{@link System#currentTimeMillis()}.
+ */
+ public long realCurrentTimeMillis() {
+ return System.currentTimeMillis();
+ }
}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
index 37ceac6..99ab327 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
@@ -26,6 +26,15 @@
private RavenwoodUtils() {
}
+ private static final String RAVENWOOD_NATIVE_RUNTIME_NAME = "ravenwood_runtime";
+
+ // LibcoreRavenwoodUtils calls it with reflections.
+ public static void loadRavenwoodNativeRuntime() {
+ if (RavenwoodRule.isOnRavenwood()) {
+ RavenwoodUtils.loadJniLibrary(RAVENWOOD_NATIVE_RUNTIME_NAME);
+ }
+ }
+
/**
* Load a JNI library respecting {@code java.library.path}
* (which reflects {@code LD_LIBRARY_PATH}).
diff --git a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
index e951351b..773a89a 100644
--- a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -39,4 +39,8 @@
public static void validate(Statement base, Description description,
boolean enableOptionalValidation) {
}
+
+ public static long realCurrentTimeMillis() {
+ return System.currentTimeMillis();
+ }
}
diff --git a/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp b/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp
new file mode 100644
index 0000000..8e3a21d
--- /dev/null
+++ b/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+
+typedef void (*FreeFunction)(void*);
+
+static void NativeAllocationRegistry_applyFreeFunction(JNIEnv*,
+ jclass,
+ jlong freeFunction,
+ jlong ptr) {
+ void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
+ FreeFunction nativeFreeFunction
+ = reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction));
+ nativeFreeFunction(nativePtr);
+}
+
+static const JNINativeMethod sMethods_NAR[] =
+{
+ { "applyFreeFunction", "(JJ)V", (void*)NativeAllocationRegistry_applyFreeFunction },
+};
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
+{
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ ALOGE("GetEnv failed!");
+ return result;
+ }
+ ALOG_ASSERT(env, "Could not retrieve the env!");
+
+ ALOGI("%s: JNI_OnLoad", __FILE__);
+
+ // Initialize the Ravenwood version of NativeAllocationRegistry.
+ // We don't use this JNI on the device side, but if we ever have to do, skip this part.
+#ifndef __ANDROID__
+ int res = jniRegisterNativeMethods(env, "libcore/util/NativeAllocationRegistry",
+ sMethods_NAR, NELEM(sMethods_NAR));
+ if (res < 0) {
+ return res;
+ }
+#endif
+
+ return JNI_VERSION_1_4;
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java
new file mode 100644
index 0000000..839b62a
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.ravenwood;
+
+public class LibcoreRavenwoodUtils {
+ private LibcoreRavenwoodUtils() {
+ }
+
+ public static void loadRavenwoodNativeRuntime() {
+ // TODO Stop using reflections.
+ // We need to call RavenwoodUtils.loadRavenwoodNativeRuntime(), but due to the build
+ // structure complexity, we can't refer to to this method directly from here,
+ // so let's use reflections for now...
+ try {
+ final var clazz = Class.forName("android.platform.test.ravenwood.RavenwoodUtils");
+ final var method = clazz.getMethod("loadRavenwoodNativeRuntime");
+ method.invoke(null);
+ } catch (Throwable th) {
+ throw new IllegalStateException("Failed to load Ravenwood native runtime", th);
+ }
+ }
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
new file mode 100644
index 0000000..93861e8
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.util;
+
+import libcore.ravenwood.LibcoreRavenwoodUtils;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Reference;
+
+/**
+ * Re-implementation of ART's NativeAllocationRegistry for Ravenwood.
+ * - We don't track the native allocation size on Ravenwood.
+ * - sun.misc.Cleaner isn't available on the desktop JVM, so we use java.lang.ref.Cleaner.
+ * (Should ART switch to java.lang.ref.Cleaner?)
+ */
+public class NativeAllocationRegistry {
+ static {
+ // Initialize the JNI method.
+ LibcoreRavenwoodUtils.loadRavenwoodNativeRuntime();
+ }
+
+ private final long mFreeFunction;
+ private static final Cleaner sCleaner = Cleaner.create();
+
+ public static NativeAllocationRegistry createNonmalloced(
+ ClassLoader classLoader, long freeFunction, long size) {
+ return new NativeAllocationRegistry(classLoader, freeFunction, size, false);
+ }
+
+ public static NativeAllocationRegistry createMalloced(
+ ClassLoader classLoader, long freeFunction, long size) {
+ return new NativeAllocationRegistry(classLoader, freeFunction, size, true);
+ }
+
+ public static NativeAllocationRegistry createMalloced(
+ ClassLoader classLoader, long freeFunction) {
+ return new NativeAllocationRegistry(classLoader, freeFunction, 0, true);
+ }
+
+ public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) {
+ this(classLoader, freeFunction, size, size == 0);
+ }
+
+ private NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size,
+ boolean mallocAllocation) {
+ if (size < 0) {
+ throw new IllegalArgumentException("Invalid native allocation size: " + size);
+ }
+ mFreeFunction = freeFunction;
+ }
+
+ public Runnable registerNativeAllocation(Object referent, long nativePtr) {
+ if (referent == null) {
+ throw new IllegalArgumentException("referent is null");
+ }
+ if (nativePtr == 0) {
+ throw new IllegalArgumentException("nativePtr is null");
+ }
+
+ final Runnable releaser = () -> {
+ applyFreeFunction(mFreeFunction, nativePtr);
+ };
+ sCleaner.register(referent, releaser);
+
+ // Ensure that cleaner doesn't get invoked before we enable it.
+ Reference.reachabilityFence(referent);
+ return releaser;
+ }
+
+ /**
+ * Calls {@code freeFunction}({@code nativePtr}).
+ */
+ public static native void applyFreeFunction(long freeFunction, long nativePtr);
+}
+
diff --git a/ravenwood/scripts/ravenwood-stats-collector.sh b/ravenwood/scripts/ravenwood-stats-collector.sh
index b5843d0..beacde2 100755
--- a/ravenwood/scripts/ravenwood-stats-collector.sh
+++ b/ravenwood/scripts/ravenwood-stats-collector.sh
@@ -39,14 +39,18 @@
local jar=$1
local file=$2
- sed -e '1d' -e "s/^/$jar,/" $file
+ # Use sed to remove the header + prepend the jar filename.
+ sed -e '1d' -e "s/^/$jar,/" $file
}
collect_stats() {
local out="$1"
{
- echo 'Jar,PackageName,ClassName,SupportedMethods,TotalMethods'
- dump "framework-minus-apex" hoststubgen_framework-minus-apex_stats.csv
+ # Copy the header, with the first column appended.
+ echo -n "Jar,"
+ head -n 1 hoststubgen_framework-minus-apex_stats.csv
+
+ dump "framework-minus-apex" hoststubgen_framework-minus-apex_stats.csv
dump "service.core" hoststubgen_services.core_stats.csv
} > "$out"
@@ -56,7 +60,10 @@
collect_apis() {
local out="$1"
{
- echo 'Jar,PackageName,ClassName,MethodName,Descriptor'
+ # Copy the header, with the first column appended.
+ echo -n "Jar,"
+ head -n 1 hoststubgen_framework-minus-apex_apis.csv
+
dump "framework-minus-apex" hoststubgen_framework-minus-apex_apis.csv
dump "service.core" hoststubgen_services.core_apis.csv
} > "$out"
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index 0448f6d..e66fe1b 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -49,6 +49,16 @@
}
flag {
+ name: "do_not_reset_key_event_state"
+ namespace: "accessibility"
+ description: "Don't reset the event stream state when receiving an event without policy flag FLAG_PASS_TO_USER. Just pass it through the pipeline."
+ bug: "331900630"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "enable_a11y_checker_logging"
namespace: "accessibility"
description: "Whether to identify and log app a11y issues."
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 54e545d..5fb60e7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -347,8 +347,13 @@
final int eventSource = event.getSource();
final int displayId = event.getDisplayId();
if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) {
- state.reset();
- clearEventStreamHandler(displayId, eventSource);
+ if (!Flags.doNotResetKeyEventState()) {
+ state.reset();
+ clearEventStreamHandler(displayId, eventSource);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Not processing event " + event);
+ }
super.onInputEvent(event, policyFlags);
return;
}
@@ -503,9 +508,15 @@
private void processKeyEvent(EventStreamState state, KeyEvent event, int policyFlags) {
if (!state.shouldProcessKeyEvent(event)) {
+ if (DEBUG) {
+ Slog.d(TAG, "processKeyEvent: not processing: " + event);
+ }
super.onInputEvent(event, policyFlags);
return;
}
+ if (DEBUG) {
+ Slog.d(TAG, "processKeyEvent: " + event);
+ }
// Since the display id of KeyEvent always would be -1 and there is only one
// KeyboardInterceptor for all display, pass KeyEvent to the mEventHandler of
// DEFAULT_DISPLAY to handle.
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 300b147..8ee560b 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -256,6 +256,7 @@
"stats_flags_lib",
"core_os_flags_lib",
"connectivity_flags_lib",
+ "dreams_flags_lib",
],
javac_shard_size: 50,
javacflags: [
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 7979936..1ccc48d 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -777,18 +777,24 @@
+ ", info:" + mHealthInfo.toString());
}
- mHandler.post(() -> broadcastBatteryChangedIntent(intent, mBatteryChangedOptions));
+ mHandler.post(() -> broadcastBatteryChangedIntent(mContext,
+ intent, mBatteryChangedOptions));
}
- private static void broadcastBatteryChangedIntent(Intent intent, Bundle options) {
+ private static void broadcastBatteryChangedIntent(Context context, Intent intent,
+ Bundle options) {
// TODO (293959093): It is important that SystemUI receives this broadcast as soon as
// possible. Ideally, it should be using binder callbacks but until then, dispatch this
// as a foreground broadcast to SystemUI.
final Intent fgIntent = new Intent(intent);
fgIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
fgIntent.setPackage(sSystemUiPackage);
- ActivityManager.broadcastStickyIntent(fgIntent, AppOpsManager.OP_NONE,
- options, UserHandle.USER_ALL);
+ if (com.android.server.flags.Flags.pkgTargetedBatteryChangedNotSticky()) {
+ context.sendBroadcastAsUser(fgIntent, UserHandle.ALL, null, options);
+ } else {
+ ActivityManager.broadcastStickyIntent(fgIntent, AppOpsManager.OP_NONE,
+ options, UserHandle.USER_ALL);
+ }
ActivityManager.broadcastStickyIntent(intent, new String[] {sSystemUiPackage},
AppOpsManager.OP_NONE, options, UserHandle.USER_ALL);
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 6f20adf..a619257 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1396,7 +1396,14 @@
int innerDepth = parser.getDepth();
try {
if (Flags.recoverabilityDetection()) {
- observerMitigationCount = parser.getAttributeInt(null, ATTR_MITIGATION_COUNT);
+ try {
+ observerMitigationCount =
+ parser.getAttributeInt(null, ATTR_MITIGATION_COUNT);
+ } catch (XmlPullParserException e) {
+ Slog.i(
+ TAG,
+ "ObserverInternal mitigation count was not present.");
+ }
}
while (XmlUtils.nextElementWithin(parser, innerDepth)) {
if (TAG_PACKAGE.equals(parser.getName())) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 2d1aba4..bc83a0e 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2691,7 +2691,7 @@
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED)
- && idMatch(r, subId, phoneId)) {
+ && idMatchRelaxed(r, subId, phoneId)) {
try {
r.callback.onRadioPowerStateChanged(state);
} catch (RemoteException ex) {
@@ -4089,6 +4089,45 @@
}
}
+ /**
+ * Match the sub id or phone id of the event to the record with relaxed rules
+ *
+ * We follow the rules below:
+ * 1) If sub id of the event is invalid, phone id should be used.
+ * 2) If record's phoneId is also invalid then allow phone 0 notifications
+ * 3) The event on default sub should be notified to the records
+ * which register the default sub id.
+ * 4) Sub id should be exactly matched for all other cases.
+ * TODO: b/337878785 for longterm fix
+ */
+ boolean idMatchRelaxed(Record r, int subId, int phoneId) {
+ if (!Flags.useRelaxedIdMatch()) {
+ return idMatch(r, subId, phoneId);
+ }
+
+ if (subId < 0) {
+ // Invalid case, we need compare phoneId.
+ // If the record does not have a valid phone Id send phone 0 notifications.
+ // A record's phoneId can get invalid if there is no SIM or modem was restarting
+ // when caller registered.
+ if (r.phoneId == INVALID_SIM_SLOT_INDEX) {
+ return (phoneId == 0);
+ } else {
+ return (r.phoneId == phoneId);
+ }
+ }
+
+ if (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ // if the registered record does not have a valid phoneId then use the phone 0
+ if (r.phoneId == INVALID_SIM_SLOT_INDEX) {
+ return (phoneId == 0);
+ }
+ return (subId == mDefaultSubId);
+ } else {
+ return (r.subId == subId);
+ }
+ }
+
private boolean checkFineLocationAccess(Record r) {
return checkFineLocationAccess(r, Build.VERSION_CODES.BASE);
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 96228b2..ec0d897 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3856,7 +3856,7 @@
void onFgsTimeout(ServiceRecord sr) {
synchronized (mAm) {
final int fgsType = getTimeLimitedFgsType(sr.foregroundServiceType);
- if (fgsType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+ if (fgsType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE || sr.app == null) {
mFGSAnrTimer.discard(sr);
return;
}
@@ -3864,10 +3864,12 @@
final long lastTopTime = sr.app.mState.getLastTopTime();
final long constantTimeLimit = getTimeLimitForFgsType(fgsType);
final long nowUptime = SystemClock.uptimeMillis();
- if (constantTimeLimit > (nowUptime - lastTopTime)) {
+ if (lastTopTime != Long.MIN_VALUE && constantTimeLimit > (nowUptime - lastTopTime)) {
+ // Discard any other messages for this service
+ mFGSAnrTimer.discard(sr);
+ mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
// The app was in the TOP state after the FGS was started so its time allowance
// should be counted from that time since this is considered a user interaction
- mFGSAnrTimer.discard(sr);
final Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
mAm.mHandler.sendMessageAtTime(msg, lastTopTime + constantTimeLimit);
@@ -7600,8 +7602,14 @@
super(Objects.requireNonNull(am).mHandler, msg, label);
}
- void start(@NonNull ProcessRecord proc, long millis) {
- start(proc, proc.getPid(), proc.uid, millis);
+ @Override
+ public int getPid(@NonNull ProcessRecord proc) {
+ return proc.getPid();
+ }
+
+ @Override
+ public int getUid(@NonNull ProcessRecord proc) {
+ return proc.uid;
}
}
@@ -7611,11 +7619,14 @@
super(Objects.requireNonNull(am).mHandler, msg, label);
}
- void start(@NonNull ServiceRecord service, long millis) {
- start(service,
- (service.app != null) ? service.app.getPid() : 0,
- service.appInfo.uid,
- millis);
+ @Override
+ public int getPid(@NonNull ServiceRecord service) {
+ return (service.app != null) ? service.app.getPid() : 0;
+ }
+
+ @Override
+ public int getUid(@NonNull ServiceRecord service) {
+ return (service.appInfo != null) ? service.appInfo.uid : 0;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 49f2c8b..1b59c18 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3541,13 +3541,23 @@
mAppProfiler.setAllowLowerMemLevelLocked(false);
doLowMem = false;
}
+ if (doOomAdj) {
+ if (Flags.migrateFullOomadjUpdates()) {
+ app.forEachConnectionHost((host) -> enqueueOomAdjTargetLocked(host));
+ }
+ }
+
EventLogTags.writeAmProcDied(app.userId, pid, app.processName, setAdj, setProcState);
if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
handleAppDiedLocked(app, pid, false, true, fromBinderDied);
if (doOomAdj) {
- updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END);
+ if (Flags.migrateFullOomadjUpdates()) {
+ updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_PROCESS_END);
+ } else {
+ updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END);
+ }
}
if (doLowMem) {
mAppProfiler.doLowMemReportIfNeededLocked(app);
@@ -5024,7 +5034,7 @@
}
@Override
- public final void finishAttachApplication(long startSeq) {
+ public final void finishAttachApplication(long startSeq, long timestampApplicationOnCreateNs) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -5044,6 +5054,11 @@
} finally {
Binder.restoreCallingIdentity(origId);
}
+
+ if (android.app.Flags.appStartInfoTimestamps() && timestampApplicationOnCreateNs > 0) {
+ addStartInfoTimestampInternal(ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE,
+ timestampApplicationOnCreateNs, UserHandle.getUserId(uid), uid);
+ }
}
private void handleBindApplicationTimeoutSoft(ProcessRecord app, int softTimeoutMillis) {
@@ -10243,10 +10258,15 @@
mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, true,
ALLOW_NON_FULL, "addStartInfoTimestamp", null);
- final String packageName = Settings.getPackageNameForUid(mContext, callingUid);
+ addStartInfoTimestampInternal(key, timestampNs, userId, callingUid);
+ }
- mProcessList.getAppStartInfoTracker().addTimestampToStart(packageName,
- UserHandle.getUid(userId, UserHandle.getAppId(callingUid)), timestampNs, key);
+ private void addStartInfoTimestampInternal(int key, long timestampNs, int userId, int uid) {
+ mProcessList.getAppStartInfoTracker().addTimestampToStart(
+ Settings.getPackageNameForUid(mContext, uid),
+ UserHandle.getUid(userId, UserHandle.getAppId(uid)),
+ timestampNs,
+ key);
}
@Override
@@ -17723,11 +17743,6 @@
}
@GuardedBy({"this", "mProcLock"})
- final void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
- mOomAdjuster.setAppIdTempAllowlistStateLSP(uid, onAllowlist);
- }
-
- @GuardedBy({"this", "mProcLock"})
final void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
mOomAdjuster.setUidTempAllowlistStateLSP(uid, onAllowlist);
}
@@ -18689,7 +18704,7 @@
} else {
mFgsStartTempAllowList.removeUid(changingUid);
}
- setAppIdTempAllowlistStateLSP(changingUid, adding);
+ setUidTempAllowlistStateLSP(changingUid, adding);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index bf4f34f..5af9424 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -117,6 +117,7 @@
import android.util.DisplayMetrics;
import android.util.TeeWriter;
import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
import android.view.Display;
import android.window.SplashScreen;
@@ -241,6 +242,23 @@
case "start":
case "start-activity":
return runStartActivity(pw);
+ case "start-in-vsync":
+ final ProgressWaiter waiter = new ProgressWaiter(0);
+ final int[] startResult = new int[1];
+ startResult[0] = -1;
+ mInternal.mUiHandler.runWithScissors(
+ () -> Choreographer.getInstance().postFrameCallback(frameTimeNanos -> {
+ try {
+ startResult[0] = runStartActivity(pw);
+ waiter.onFinished(0, null /* extras */);
+ } catch (Exception ex) {
+ getErrPrintWriter().println(
+ "Error: unable to start activity, " + ex);
+ }
+ }),
+ USER_OPERATION_TIMEOUT_MS / 2);
+ waiter.waitForFinish(USER_OPERATION_TIMEOUT_MS);
+ return startResult[0];
case "startservice":
case "start-service":
return runStartService(pw, false);
@@ -281,6 +299,8 @@
return runClearWatchHeap(pw);
case "clear-start-info":
return runClearStartInfo(pw);
+ case "start-info-detailed-monitoring":
+ return runStartInfoDetailedMonitoring(pw);
case "clear-exit-info":
return runClearExitInfo(pw);
case "bug-report":
@@ -1395,12 +1415,12 @@
"runClearStartInfo()");
String opt;
int userId = UserHandle.USER_CURRENT;
- String packageName = null;
while ((opt = getNextOption()) != null) {
if (opt.equals("--user")) {
userId = UserHandle.parseUserArg(getNextArgRequired());
} else {
- packageName = opt;
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ return -1;
}
}
if (userId == UserHandle.USER_CURRENT) {
@@ -1411,21 +1431,19 @@
userId = user.id;
}
mInternal.mProcessList.getAppStartInfoTracker()
- .clearHistoryProcessStartInfo(packageName, userId);
+ .clearHistoryProcessStartInfo(getNextArg(), userId);
return 0;
}
- int runClearExitInfo(PrintWriter pw) throws RemoteException {
- mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
- "runClearExitInfo()");
+ int runStartInfoDetailedMonitoring(PrintWriter pw) throws RemoteException {
String opt;
int userId = UserHandle.USER_CURRENT;
- String packageName = null;
while ((opt = getNextOption()) != null) {
if (opt.equals("--user")) {
userId = UserHandle.parseUserArg(getNextArgRequired());
} else {
- packageName = opt;
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ return -1;
}
}
if (userId == UserHandle.USER_CURRENT) {
@@ -1435,7 +1453,33 @@
}
userId = user.id;
}
- mInternal.mProcessList.mAppExitInfoTracker.clearHistoryProcessExitInfo(packageName, userId);
+ mInternal.mProcessList.getAppStartInfoTracker()
+ .configureDetailedMonitoring(pw, getNextArg(), userId);
+ return 0;
+ }
+
+ int runClearExitInfo(PrintWriter pw) throws RemoteException {
+ mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
+ "runClearExitInfo()");
+ String opt;
+ int userId = UserHandle.USER_CURRENT;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else {
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ }
+ if (userId == UserHandle.USER_CURRENT) {
+ UserInfo user = mInterface.getCurrentUser();
+ if (user == null) {
+ return -1;
+ }
+ userId = user.id;
+ }
+ mInternal.mProcessList.mAppExitInfoTracker.clearHistoryProcessExitInfo(getNextArg(),
+ userId);
return 0;
}
@@ -4236,6 +4280,9 @@
pw.println(" --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as.");
pw.println(" --display <DISPLAY_ID>: The display to launch the activity into.");
pw.println(" --splashscreen-icon: Show the splash screen icon on launch.");
+ pw.println(" start-in-vsync");
+ pw.println(" Start an Activity with vsync aligned. See `start-activity` for the");
+ pw.println(" possible options.");
pw.println(" start-service [--user <USER_ID> | current] <INTENT>");
pw.println(" Start a Service. Options are:");
pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
@@ -4356,10 +4403,15 @@
pw.println(" above <HEAP-LIMIT> then a heap dump is collected for the user to report.");
pw.println(" clear-watch-heap");
pw.println(" Clear the previously set-watch-heap.");
- pw.println(" clear-start-info [--user <USER_ID> | all | current] [package]");
- pw.println(" Clear the process start-info for given package");
- pw.println(" clear-exit-info [--user <USER_ID> | all | current] [package]");
- pw.println(" Clear the process exit-info for given package");
+ pw.println(" clear-start-info [--user <USER_ID> | all | current] <PACKAGE>");
+ pw.println(" Clear process start-info for the given package.");
+ pw.println(" Clear start-info for all packages if no package is provided.");
+ pw.println(" start-info-detailed-monitoring [--user <USER_ID> | all | current] <PACKAGE>");
+ pw.println(" Enable application start info detailed monitoring for the given package.");
+ pw.println(" Disable if no package is supplied.");
+ pw.println(" clear-exit-info [--user <USER_ID> | all | current] <PACKAGE>");
+ pw.println(" Clear process exit-info for the given package.");
+ pw.println(" Clear exit-info for all packages if no package is provided.");
pw.println(" bug-report [--progress | --telephony]");
pw.println(" Request bug report generation; will launch a notification");
pw.println(" when done to select where it should be delivered. Options are:");
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index 2be1fe2..376f654 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -65,6 +65,7 @@
import java.util.Collections;
import java.util.Date;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -82,8 +83,12 @@
private static final int FOREACH_ACTION_REMOVE_ITEM = 1;
private static final int FOREACH_ACTION_STOP_ITERATION = 2;
+ private static final String MONITORING_MODE_EMPTY_TEXT = "No records";
+
@VisibleForTesting static final int APP_START_INFO_HISTORY_LIST_SIZE = 16;
+ private static final int APP_START_INFO_MONITORING_MODE_LIST_SIZE = 100;
+
@VisibleForTesting static final String APP_START_STORE_DIR = "procstartstore";
@VisibleForTesting static final String APP_START_INFO_FILE = "procstartinfo";
@@ -426,6 +431,40 @@
ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE);
}
+ /**
+ * Helper functions for monitoring shell command.
+ * > adb shell am start-info-detailed-monitoring [package-name]
+ */
+ void configureDetailedMonitoring(PrintWriter pw, String packageName, int userId) {
+ synchronized (mLock) {
+ if (!mEnabled) {
+ return;
+ }
+
+ forEachPackageLocked((name, records) -> {
+ for (int i = 0; i < records.size(); i++) {
+ records.valueAt(i).disableAppMonitoringMode();
+ }
+ return AppStartInfoTracker.FOREACH_ACTION_NONE;
+ });
+
+ if (TextUtils.isEmpty(packageName)) {
+ pw.println("ActivityManager AppStartInfo detailed monitoring disabled");
+ } else {
+ SparseArray<AppStartInfoContainer> array = mData.getMap().get(packageName);
+ if (array != null) {
+ for (int i = 0; i < array.size(); i++) {
+ array.valueAt(i).enableAppMonitoringModeForUser(userId);
+ }
+ pw.println("ActivityManager AppStartInfo detailed monitoring enabled for "
+ + packageName);
+ } else {
+ pw.println("Package " + packageName + " not found");
+ }
+ }
+ }
+ }
+
/** Report a bind application timestamp to add to {@link ApplicationStartInfo}. */
public void reportBindApplicationTimeNanos(ProcessRecord app, long timeNs) {
addTimestampToStart(app, timeNs,
@@ -1011,15 +1050,46 @@
/** A container class of (@link android.app.ApplicationStartInfo) */
final class AppStartInfoContainer {
- private List<ApplicationStartInfo> mInfos; // Always kept sorted by first timestamp.
+ private ArrayList<ApplicationStartInfo> mInfos; // Always kept sorted by first timestamp.
private int mMaxCapacity;
private int mUid;
+ private boolean mMonitoringModeEnabled = false;
AppStartInfoContainer(final int maxCapacity) {
mInfos = new ArrayList<ApplicationStartInfo>();
mMaxCapacity = maxCapacity;
}
+ int getMaxCapacity() {
+ return mMonitoringModeEnabled ? APP_START_INFO_MONITORING_MODE_LIST_SIZE : mMaxCapacity;
+ }
+
+ @GuardedBy("mLock")
+ void enableAppMonitoringModeForUser(int userId) {
+ if (UserHandle.getUserId(mUid) == userId) {
+ mMonitoringModeEnabled = true;
+ }
+ }
+
+ @GuardedBy("mLock")
+ void disableAppMonitoringMode() {
+ mMonitoringModeEnabled = false;
+
+ // Capacity is reduced by turning off monitoring mode. Check if array size is within
+ // new lower limits and trim extraneous records if it is not.
+ if (mInfos.size() <= getMaxCapacity()) {
+ return;
+ }
+
+ // Sort records so we can remove the least recent ones.
+ Collections.sort(mInfos, (a, b) ->
+ Long.compare(getStartTimestamp(b), getStartTimestamp(a)));
+
+ // Remove records and trim list object back to size.
+ mInfos.subList(0, mInfos.size() - getMaxCapacity()).clear();
+ mInfos.trimToSize();
+ }
+
@GuardedBy("mLock")
void getStartInfoLocked(
final int filterPid, final int maxNum, ArrayList<ApplicationStartInfo> results) {
@@ -1029,7 +1099,7 @@
@GuardedBy("mLock")
void addStartInfoLocked(ApplicationStartInfo info) {
int size = mInfos.size();
- if (size >= mMaxCapacity) {
+ if (size >= getMaxCapacity()) {
// Remove oldest record if size is over max capacity.
int oldestIndex = -1;
long oldestTimeStamp = Long.MAX_VALUE;
@@ -1061,12 +1131,59 @@
@GuardedBy("mLock")
void dumpLocked(PrintWriter pw, String prefix, SimpleDateFormat sdf) {
+ if (mMonitoringModeEnabled) {
+ // For monitoring mode, calculate the average start time for each start state to
+ // add to output.
+ List<Long> coldStartTimes = new ArrayList<>();
+ List<Long> warmStartTimes = new ArrayList<>();
+ List<Long> hotStartTimes = new ArrayList<>();
+
+ for (int i = 0; i < mInfos.size(); i++) {
+ ApplicationStartInfo startInfo = mInfos.get(i);
+ Map<Integer, Long> timestamps = startInfo.getStartupTimestamps();
+
+ // Confirm required timestamps exist.
+ if (timestamps.containsKey(ApplicationStartInfo.START_TIMESTAMP_LAUNCH)
+ && timestamps.containsKey(
+ ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME)) {
+ // Add timestamp to correct collection.
+ long time = timestamps.get(ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME)
+ - timestamps.get(ApplicationStartInfo.START_TIMESTAMP_LAUNCH);
+ switch (startInfo.getStartType()) {
+ case ApplicationStartInfo.START_TYPE_COLD:
+ coldStartTimes.add(time);
+ break;
+ case ApplicationStartInfo.START_TYPE_WARM:
+ warmStartTimes.add(time);
+ break;
+ case ApplicationStartInfo.START_TYPE_HOT:
+ hotStartTimes.add(time);
+ break;
+ }
+ }
+ }
+
+ pw.println(prefix + " Average Start Time in ns for Cold Starts: "
+ + (coldStartTimes.isEmpty() ? MONITORING_MODE_EMPTY_TEXT
+ : calculateAverage(coldStartTimes)));
+ pw.println(prefix + " Average Start Time in ns for Warm Starts: "
+ + (warmStartTimes.isEmpty() ? MONITORING_MODE_EMPTY_TEXT
+ : calculateAverage(warmStartTimes)));
+ pw.println(prefix + " Average Start Time in ns for Hot Starts: "
+ + (hotStartTimes.isEmpty() ? MONITORING_MODE_EMPTY_TEXT
+ : calculateAverage(hotStartTimes)));
+ }
+
int size = mInfos.size();
for (int i = 0; i < size; i++) {
mInfos.get(i).dump(pw, prefix + " ", "#" + i, sdf);
}
}
+ private long calculateAverage(List<Long> vals) {
+ return (long) vals.stream().mapToDouble(a -> a).average().orElse(0.0);
+ }
+
@GuardedBy("mLock")
void writeToProto(ProtoOutputStream proto, long fieldId) throws IOException {
long token = proto.start(fieldId);
@@ -1076,6 +1193,7 @@
mInfos.get(i)
.writeToProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO);
}
+ proto.write(AppsStartInfoProto.Package.User.MONITORING_ENABLED, mMonitoringModeEnabled);
proto.end(token);
}
@@ -1094,6 +1212,10 @@
info.readFromProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO);
mInfos.add(info);
break;
+ case (int) AppsStartInfoProto.Package.User.MONITORING_ENABLED:
+ mMonitoringModeEnabled = proto.readBoolean(
+ AppsStartInfoProto.Package.User.MONITORING_ENABLED);
+ break;
}
}
proto.end(token);
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 48dd039..4425a38 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1339,8 +1339,14 @@
MSG_DELIVERY_TIMEOUT, "BROADCAST_TIMEOUT", true);
}
- void start(@NonNull BroadcastProcessQueue queue, long timeoutMillis) {
- start(queue, queue.app.getPid(), queue.app.uid, timeoutMillis);
+ @Override
+ public int getPid(@NonNull BroadcastProcessQueue queue) {
+ return (queue.app != null) ? queue.app.getPid() : 0;
+ }
+
+ @Override
+ public int getUid(@NonNull BroadcastProcessQueue queue) {
+ return (queue.app != null) ? queue.app.uid : 0;
}
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 9b72db8..a289dd1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -3696,27 +3696,18 @@
}
@GuardedBy({"mService", "mProcLock"})
- void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
- boolean changed = false;
- for (int i = mActiveUids.size() - 1; i >= 0; i--) {
- final UidRecord uidRec = mActiveUids.valueAt(i);
- if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) {
- uidRec.setCurAllowListed(onAllowlist);
- changed = true;
- }
- }
- if (changed) {
- updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
- }
- }
-
- @GuardedBy({"mService", "mProcLock"})
void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
- boolean changed = false;
final UidRecord uidRec = mActiveUids.get(uid);
if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) {
uidRec.setCurAllowListed(onAllowlist);
- updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
+ if (Flags.migrateFullOomadjUpdates()) {
+ for (int i = uidRec.getNumOfProcs() - 1; i >= 0; i--) {
+ enqueueOomAdjTargetLocked(uidRec.getProcessRecordByIndex(i));
+ }
+ updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_ALLOWLIST);
+ } else {
+ updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
+ }
}
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0816527..a74c489 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -71,6 +71,7 @@
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
+import java.util.function.Consumer;
/**
* Full information about a particular process that
@@ -1692,4 +1693,22 @@
&& !mOptRecord.shouldNotFreeze()
&& mState.getCurAdj() >= ProcessList.FREEZER_CUTOFF_ADJ;
}
+
+ public void forEachConnectionHost(Consumer<ProcessRecord> consumer) {
+ for (int i = mServices.numberOfConnections() - 1; i >= 0; i--) {
+ final ConnectionRecord cr = mServices.getConnectionAt(i);
+ final ProcessRecord service = cr.binding.service.app;
+ consumer.accept(service);
+ }
+ for (int i = mServices.numberOfSdkSandboxConnections() - 1; i >= 0; i--) {
+ final ConnectionRecord cr = mServices.getSdkSandboxConnectionAt(i);
+ final ProcessRecord service = cr.binding.service.app;
+ consumer.accept(service);
+ }
+ for (int i = mProviders.numberOfProviderConnections() - 1; i >= 0; i--) {
+ ContentProviderConnection cpc = mProviders.getProviderConnectionAt(i);
+ ProcessRecord provider = cpc.provider.proc;
+ consumer.accept(provider);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 8b64538..9b83ede 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -35,6 +35,10 @@
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
/**
* Maps system settings to system properties.
@@ -320,15 +324,30 @@
NAMESPACE_REBOOT_STAGING,
AsyncTask.THREAD_POOL_EXECUTOR,
(DeviceConfig.Properties properties) -> {
- String scope = properties.getNamespace();
- for (String key : properties.getKeyset()) {
- String aconfigPropertyName = makeAconfigFlagStagedPropertyName(key);
- if (aconfigPropertyName == null) {
- log("unable to construct system property for " + scope + "/" + key);
- return;
+
+ HashMap<String, HashMap<String, String>> propsToStage =
+ getStagedFlagsWithValueChange(properties);
+
+ for (HashMap.Entry<String, HashMap<String, String>> entry : propsToStage.entrySet()) {
+ String actualNamespace = entry.getKey();
+ HashMap<String, String> flagValuesToStage = entry.getValue();
+
+ for (String flagName : flagValuesToStage.keySet()) {
+ String stagedValue = flagValuesToStage.get(flagName);
+ String propertyName = "next_boot." + makeAconfigFlagPropertyName(
+ actualNamespace, flagName);
+
+ if (!propertyName.matches(SYSTEM_PROPERTY_VALID_CHARACTERS_REGEX)
+ || propertyName.contains(SYSTEM_PROPERTY_INVALID_SUBSTRING)) {
+ log("unable to construct system property for " + actualNamespace
+ + "/" + flagName);
+ continue;
+ }
+
+ setProperty(propertyName, stagedValue);
}
- setProperty(aconfigPropertyName, properties.getString(key, null));
}
+
});
}
@@ -401,35 +420,6 @@
}
/**
- * system property name constructing rule for staged aconfig flags, the flag name
- * is in the form of [namespace]*[actual flag name], we should push the following
- * to system properties
- * "next_boot.[actual sys prop name]".
- * If the name contains invalid characters or substrings for system property name,
- * will return null.
- * @param flagName
- * @return
- */
- @VisibleForTesting
- static String makeAconfigFlagStagedPropertyName(String flagName) {
- int idx = flagName.indexOf(NAMESPACE_REBOOT_STAGING_DELIMITER);
- if (idx == -1 || idx == flagName.length() - 1 || idx == 0) {
- log("invalid staged flag: " + flagName);
- return null;
- }
-
- String propertyName = "next_boot." + makeAconfigFlagPropertyName(
- flagName.substring(0, idx), flagName.substring(idx+1));
-
- if (!propertyName.matches(SYSTEM_PROPERTY_VALID_CHARACTERS_REGEX)
- || propertyName.contains(SYSTEM_PROPERTY_INVALID_SUBSTRING)) {
- return null;
- }
-
- return propertyName;
- }
-
- /**
* system property name constructing rule for aconfig flags:
* "persist.device_config.aconfig_flags.[category_name].[flag_name]".
* If the name contains invalid characters or substrings for system property name,
@@ -451,6 +441,63 @@
return propertyName;
}
+ /**
+ * Get the flags that need to be staged in sys prop, only these with a real value
+ * change needs to be staged in sys prop. Otherwise, the flag stage is useless and
+ * create performance problem at sys prop side.
+ * @param properties
+ * @return a hash map of namespace name to actual flags to stage
+ */
+ @VisibleForTesting
+ static HashMap<String, HashMap<String, String>> getStagedFlagsWithValueChange(
+ DeviceConfig.Properties properties) {
+
+ // sort flags by actual namespace of the flag
+ HashMap<String, HashMap<String, String>> stagedProps = new HashMap<>();
+ for (String flagName : properties.getKeyset()) {
+ int idx = flagName.indexOf(NAMESPACE_REBOOT_STAGING_DELIMITER);
+ if (idx == -1 || idx == flagName.length() - 1 || idx == 0) {
+ log("invalid staged flag: " + flagName);
+ continue;
+ }
+ String actualNamespace = flagName.substring(0, idx);
+ String actualFlagName = flagName.substring(idx+1);
+ HashMap<String, String> flagStagedValues = stagedProps.get(actualNamespace);
+ if (flagStagedValues == null) {
+ flagStagedValues = new HashMap<String, String>();
+ stagedProps.put(actualNamespace, flagStagedValues);
+ }
+ flagStagedValues.put(actualFlagName, properties.getString(flagName, null));
+ }
+
+ // for each namespace, find flags with real flag value change
+ HashMap<String, HashMap<String, String>> propsToStage = new HashMap<>();
+ for (HashMap.Entry<String, HashMap<String, String>> entry : stagedProps.entrySet()) {
+ String actualNamespace = entry.getKey();
+ HashMap<String, String> flagStagedValues = entry.getValue();
+ Map<String, String> flagCurrentValues = Settings.Config.getStrings(
+ actualNamespace, new ArrayList<String>(flagStagedValues.keySet()));
+
+ HashMap<String, String> flagsToStage = new HashMap<>();
+ for (String flagName : flagStagedValues.keySet()) {
+ String stagedValue = flagStagedValues.get(flagName);
+ String currentValue = flagCurrentValues.get(flagName);
+ if (currentValue == null) {
+ currentValue = new String("false");
+ }
+ if (stagedValue != null && !stagedValue.equalsIgnoreCase(currentValue)) {
+ flagsToStage.put(flagName, stagedValue);
+ }
+ }
+
+ if (!flagsToStage.isEmpty()) {
+ propsToStage.put(actualNamespace, flagsToStage);
+ }
+ }
+
+ return propsToStage;
+ }
+
private void setProperty(String key, String value) {
// Check if need to clear the property
if (value == null) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index b703076..c6c1f98 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -155,9 +155,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@@ -225,9 +222,18 @@
private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000;
/**
+ * Amount of time waited for
+ * {@link ActivityTaskManagerInternal.ScreenObserver#onKeyguardStateChanged} callbacks to be
+ * called after calling {@link WindowManagerService#lockDeviceNow}.
+ * Otherwise, we should throw a {@link RuntimeException} and never dismiss the
+ * {@link UserSwitchingDialog}.
+ */
+ static final int SHOW_KEYGUARD_TIMEOUT_MS = 20 * 1000;
+
+ /**
* Amount of time waited for {@link WindowManagerService#dismissKeyguard} callbacks to be
* called after dismissing the keyguard.
- * Otherwise, we should move on to dismiss the dialog {@link #dismissUserSwitchDialog()}
+ * Otherwise, we should move on to dismiss the dialog {@link #dismissUserSwitchDialog}}
* and report user switch is complete {@link #REPORT_USER_SWITCH_COMPLETE_MSG}.
*/
private static final int DISMISS_KEYGUARD_TIMEOUT_MS = 2 * 1000;
@@ -1925,15 +1931,8 @@
updateProfileRelatedCaches();
mInjector.getWindowManager().setCurrentUser(userId);
mInjector.reportCurWakefulnessUsageEvent();
- // Once the internal notion of the active user has switched, we lock the device
- // with the option to show the user switcher on the keyguard.
if (userSwitchUiEnabled) {
mInjector.getWindowManager().setSwitchingUser(true);
- // Only lock if the user has a secure keyguard PIN/Pattern/Pwd
- if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
- // Make sure the device is locked before moving on with the user switch
- mInjector.lockDeviceNowAndWaitForKeyguardShown();
- }
}
} else {
@@ -2516,32 +2515,54 @@
@VisibleForTesting
void completeUserSwitch(int oldUserId, int newUserId) {
- final boolean isUserSwitchUiEnabled = isUserSwitchUiEnabled();
- // serialize each conditional step
- await(
- // STEP 1 - If there is no challenge set, dismiss the keyguard right away
- isUserSwitchUiEnabled && !mInjector.getKeyguardManager().isDeviceSecure(newUserId),
- mInjector::dismissKeyguard,
- () -> await(
- // STEP 2 - If user switch ui was enabled, dismiss user switch dialog
- isUserSwitchUiEnabled,
- this::dismissUserSwitchDialog,
- () -> {
- // STEP 3 - Send REPORT_USER_SWITCH_COMPLETE_MSG to broadcast
- // ACTION_USER_SWITCHED & call UserSwitchObservers.onUserSwitchComplete
- mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(
- REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId));
- }
- ));
+ final Runnable sendUserSwitchCompleteMessage = () -> {
+ mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
+ mHandler.sendMessage(mHandler.obtainMessage(
+ REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId));
+ };
+ if (isUserSwitchUiEnabled()) {
+ if (mInjector.getKeyguardManager().isDeviceSecure(newUserId)) {
+ this.showKeyguard(() -> dismissUserSwitchDialog(sendUserSwitchCompleteMessage));
+ } else {
+ this.dismissKeyguard(() -> dismissUserSwitchDialog(sendUserSwitchCompleteMessage));
+ }
+ } else {
+ sendUserSwitchCompleteMessage.run();
+ }
}
- private void await(boolean condition, Consumer<Runnable> conditionalStep, Runnable nextStep) {
- if (condition) {
- conditionalStep.accept(nextStep);
- } else {
- nextStep.run();
- }
+ protected void showKeyguard(Runnable runnable) {
+ runWithTimeout(mInjector::showKeyguard, SHOW_KEYGUARD_TIMEOUT_MS, runnable, () -> {
+ throw new RuntimeException(
+ "Keyguard is not shown in " + SHOW_KEYGUARD_TIMEOUT_MS + " ms.");
+ }, "showKeyguard");
+ }
+
+ protected void dismissKeyguard(Runnable runnable) {
+ runWithTimeout(mInjector::dismissKeyguard, DISMISS_KEYGUARD_TIMEOUT_MS, runnable, runnable,
+ "dismissKeyguard");
+ }
+
+ private void runWithTimeout(Consumer<Runnable> task, int timeoutMs, Runnable onSuccess,
+ Runnable onTimeout, String traceMsg) {
+ final AtomicInteger state = new AtomicInteger(0); // state = 0 (RUNNING)
+
+ asyncTraceBegin(traceMsg, 0);
+
+ mHandler.postDelayed(() -> {
+ if (state.compareAndSet(0, 1)) { // state = 1 (TIMEOUT)
+ asyncTraceEnd(traceMsg, 0);
+ Slogf.w(TAG, "Timeout: %s did not finish in %d ms", traceMsg, timeoutMs);
+ onTimeout.run();
+ }
+ }, timeoutMs);
+
+ task.accept(() -> {
+ if (state.compareAndSet(0, 2)) { // state = 2 (SUCCESS)
+ asyncTraceEnd(traceMsg, 0);
+ onSuccess.run();
+ }
+ });
}
private void moveUserToForeground(UserState uss, int newUserId) {
@@ -3977,29 +3998,45 @@
return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
}
- protected void dismissKeyguard(Runnable runnable) {
- final AtomicBoolean isFirst = new AtomicBoolean(true);
- final Runnable runOnce = () -> {
- if (isFirst.getAndSet(false)) {
- runnable.run();
- }
- };
+ protected void showKeyguard(Runnable runnable) {
+ if (getWindowManager().isKeyguardLocked()) {
+ runnable.run();
+ return;
+ }
+ getActivityTaskManagerInternal().registerScreenObserver(
+ new ActivityTaskManagerInternal.ScreenObserver() {
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) {
- mHandler.postDelayed(runOnce, DISMISS_KEYGUARD_TIMEOUT_MS);
+ }
+
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
+ if (isShowing) {
+ getActivityTaskManagerInternal().unregisterScreenObserver(this);
+ runnable.run();
+ }
+ }
+ }
+ );
+ getWindowManager().lockDeviceNow();
+ }
+
+ protected void dismissKeyguard(Runnable runnable) {
getWindowManager().dismissKeyguard(new IKeyguardDismissCallback.Stub() {
@Override
public void onDismissError() throws RemoteException {
- mHandler.post(runOnce);
+ runnable.run();
}
@Override
public void onDismissSucceeded() throws RemoteException {
- mHandler.post(runOnce);
+ runnable.run();
}
@Override
public void onDismissCancelled() throws RemoteException {
- mHandler.post(runOnce);
+ runnable.run();
}
}, /* message= */ null);
}
@@ -4025,43 +4062,5 @@
void onSystemUserVisibilityChanged(boolean visible) {
getUserManagerInternal().onSystemUserVisibilityChanged(visible);
}
-
- void lockDeviceNowAndWaitForKeyguardShown() {
- if (getWindowManager().isKeyguardLocked()) {
- return;
- }
-
- final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
- t.traceBegin("lockDeviceNowAndWaitForKeyguardShown");
-
- final CountDownLatch latch = new CountDownLatch(1);
- ActivityTaskManagerInternal.ScreenObserver screenObserver =
- new ActivityTaskManagerInternal.ScreenObserver() {
- @Override
- public void onAwakeStateChanged(boolean isAwake) {
-
- }
-
- @Override
- public void onKeyguardStateChanged(boolean isShowing) {
- if (isShowing) {
- latch.countDown();
- }
- }
- };
-
- getActivityTaskManagerInternal().registerScreenObserver(screenObserver);
- getWindowManager().lockDeviceNow();
- try {
- if (!latch.await(20, TimeUnit.SECONDS)) {
- throw new RuntimeException("Keyguard is not shown in 20 seconds");
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } finally {
- getActivityTaskManagerInternal().unregisterScreenObserver(screenObserver);
- t.traceEnd();
- }
- }
}
}
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 19be5f9..fb63ec6 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -106,3 +106,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "migrate_full_oomadj_updates"
+ namespace: "backstage_power"
+ description: "Migrate full updates to partial updates where possible"
+ bug: "324915545"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index e59de6a..798aaee 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1563,19 +1563,29 @@
private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops,
String persistentDeviceId) {
ArrayList<AppOpsManager.OpEntry> resOps = null;
+ boolean shouldReturnRestrictedAppOps = mContext.checkPermission(
+ Manifest.permission.GET_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED;
if (ops == null) {
resOps = new ArrayList<>();
- for (int j=0; j<pkgOps.size(); j++) {
+ for (int j = 0; j < pkgOps.size(); j++) {
Op curOp = pkgOps.valueAt(j);
+ if (opRestrictsRead(curOp.op) && !shouldReturnRestrictedAppOps) {
+ continue;
+ }
resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
}
} else {
- for (int j=0; j<ops.length; j++) {
+ for (int j = 0; j < ops.length; j++) {
Op curOp = pkgOps.get(ops[j]);
if (curOp != null) {
if (resOps == null) {
resOps = new ArrayList<>();
}
+ if (opRestrictsRead(curOp.op) && !shouldReturnRestrictedAppOps) {
+ continue;
+ }
resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
}
}
@@ -4244,10 +4254,21 @@
private void verifyIncomingOp(int op) {
if (op >= 0 && op < AppOpsManager._NUM_OP) {
- // Enforce manage appops permission if it's a restricted read op.
+ // Enforce privileged appops permission if it's a restricted read op.
if (opRestrictsRead(op)) {
- mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
- Binder.getCallingPid(), Binder.getCallingUid(), "verifyIncomingOp");
+ if (!(mContext.checkPermission(Manifest.permission.MANAGE_APPOPS,
+ Binder.getCallingPid(), Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED || mContext.checkPermission(
+ Manifest.permission.GET_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED || mContext.checkPermission(
+ Manifest.permission.MANAGE_APP_OPS_MODES,
+ Binder.getCallingPid(), Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED)) {
+ throw new SecurityException("verifyIncomingOp: uid " + Binder.getCallingUid()
+ + " does not have any of {MANAGE_APPOPS, GET_APP_OPS_STATS, "
+ + "MANAGE_APP_OPS_MODES}");
+ }
}
return;
}
diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java
index 94baf88..2285826 100644
--- a/services/core/java/com/android/server/appop/AttributedOp.java
+++ b/services/core/java/com/android/server/appop/AttributedOp.java
@@ -24,6 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.companion.virtual.VirtualDeviceManager;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
@@ -134,7 +135,7 @@
AppOpsManager.OpEventProxyInfo proxyInfo = null;
if (proxyUid != Process.INVALID_UID) {
proxyInfo = mAppOpsService.mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
- proxyAttributionTag);
+ proxyAttributionTag, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
}
AppOpsManager.NoteOpEvent existingEvent = mAccessEvents.get(key);
@@ -855,7 +856,7 @@
AppOpsManager.OpEventProxyInfo proxyInfo = null;
if (proxyUid != Process.INVALID_UID) {
proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
- proxyAttributionTag);
+ proxyAttributionTag, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
}
if (recycled != null) {
@@ -881,10 +882,11 @@
AppOpsManager.OpEventProxyInfo acquire(@IntRange(from = 0) int uid,
@Nullable String packageName,
- @Nullable String attributionTag) {
+ @Nullable String attributionTag,
+ @Nullable String deviceId) {
AppOpsManager.OpEventProxyInfo recycled = acquire();
if (recycled != null) {
- recycled.reinit(uid, packageName, attributionTag);
+ recycled.reinit(uid, packageName, attributionTag, deviceId);
return recycled;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 77654d4..da528a2 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1772,6 +1772,7 @@
@Override
public void handleMessage(Message msg) {
+ int muteCheckDelayMs = BTA2DP_MUTE_CHECK_DELAY_MS;
switch (msg.what) {
case MSG_RESTORE_DEVICES:
synchronized (mSetModeLock) {
@@ -1870,7 +1871,7 @@
btInfo.mDevice, btInfo.mProfile, btInfo.mIsLeOutput,
"MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
synchronized (mDeviceStateLock) {
- mDeviceInventory.onBluetoothDeviceConfigChange(btInfo,
+ muteCheckDelayMs += mDeviceInventory.onBluetoothDeviceConfigChange(btInfo,
codecAndChanged.first, codecAndChanged.second,
BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
}
@@ -2060,7 +2061,7 @@
// Give some time to Bluetooth service to post a connection message
// in case of active device switch
if (MESSAGES_MUTE_MUSIC.contains(msg.what)) {
- sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, BTA2DP_MUTE_CHECK_DELAY_MS);
+ sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, muteCheckDelayMs);
}
if (isMessageHandledUnderWakelock(msg.what)) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 9bdc51e..c9612ca 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -864,9 +864,25 @@
}
}
+ // Additional delay added to the music mute duration when a codec config change is executed.
+ static final int BT_CONFIG_CHANGE_MUTE_DELAY_MS = 500;
+ /**
+ * Handles a Bluetooth link codec configuration change communicated by the Bluetooth stack.
+ * Called when either A2DP or LE Audio codec encoding or sampling rate changes:
+ * the change is communicated to native audio policy to eventually reconfigure the audio
+ * path.
+ * Also used to notify a change in preferred mode (duplex or output) for Bluetooth profiles.
+ *
+ * @param btInfo contains all information on the Bluetooth device and profile
+ * @param codec the requested audio encoding (e.g SBC)
+ * @param codecChanged true if a codec parameter changed, false for preferred mode change
+ * @param event currently only EVENT_DEVICE_CONFIG_CHANGE
+ * @return an optional additional delay in milliseconds to add to the music mute period in
+ * case of an actual codec reconfiguration.
+ */
@GuardedBy("mDeviceBroker.mDeviceStateLock")
- /*package*/ void onBluetoothDeviceConfigChange(
+ /*package*/ int onBluetoothDeviceConfigChange(
@NonNull AudioDeviceBroker.BtDeviceInfo btInfo,
@AudioSystem.AudioFormatNativeEnumForBtCodec int codec,
boolean codecChanged, int event) {
@@ -874,10 +890,11 @@
+ "onBluetoothDeviceConfigChange")
.set(MediaMetrics.Property.EVENT, BtHelper.deviceEventToString(event));
+ int delayMs = 0;
final BluetoothDevice btDevice = btInfo.mDevice;
if (btDevice == null) {
mmi.set(MediaMetrics.Property.EARLY_RETURN, "btDevice null").record();
- return;
+ return delayMs;
}
if (AudioService.DEBUG_DEVICES) {
Log.d(TAG, "onBluetoothDeviceConfigChange btDevice=" + btDevice);
@@ -899,7 +916,7 @@
.printSlog(EventLogger.Event.ALOGI, TAG));
mmi.set(MediaMetrics.Property.EARLY_RETURN, "A2dp config change ignored")
.record();
- return;
+ return delayMs;
}
final String key = DeviceInfo.makeDeviceListKey(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
@@ -907,7 +924,7 @@
if (di == null) {
Log.e(TAG, "invalid null DeviceInfo in onBluetoothDeviceConfigChange");
mmi.set(MediaMetrics.Property.EARLY_RETURN, "null DeviceInfo").record();
- return;
+ return delayMs;
}
mmi.set(MediaMetrics.Property.ADDRESS, address)
@@ -915,7 +932,6 @@
.set(MediaMetrics.Property.INDEX, volume)
.set(MediaMetrics.Property.NAME, di.mDeviceName);
-
if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
if (btInfo.mProfile == BluetoothProfile.A2DP
|| btInfo.mProfile == BluetoothProfile.LE_AUDIO
@@ -943,6 +959,7 @@
+ address
+ " codec=" + AudioSystem.audioFormatToString(codec))
.printSlog(EventLogger.Event.ALOGI, TAG));
+ delayMs = BT_CONFIG_CHANGE_MUTE_DELAY_MS;
}
}
}
@@ -952,6 +969,7 @@
}
}
mmi.record();
+ return delayMs;
}
/*package*/ void onMakeA2dpDeviceUnavailableNow(String address, int a2dpCodec) {
diff --git a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
index e330ed5..030ce12 100644
--- a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
+++ b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
@@ -22,7 +22,10 @@
import static android.media.AudioManager.ADJUST_UNMUTE;
import android.content.Context;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceVolumeManager;
import android.media.AudioManager;
+import android.media.VolumeInfo;
import android.os.ShellCommand;
import java.io.PrintWriter;
@@ -58,8 +61,12 @@
return getSoundDoseValue();
case "reset-sound-dose-timeout":
return resetSoundDoseTimeout();
+ case "set-ringer-mode":
+ return setRingerMode();
case "set-volume":
return setVolume();
+ case "set-device-volume":
+ return setDeviceVolume();
case "adj-mute":
return adjMute();
case "adj-unmute":
@@ -95,8 +102,12 @@
pw.println(" Returns the current sound dose value");
pw.println(" reset-sound-dose-timeout");
pw.println(" Resets the sound dose timeout used for momentary exposure");
+ pw.println(" set-ringer-mode NORMAL|SILENT|VIBRATE");
+ pw.println(" Sets the Ringer mode to one of NORMAL|SILENT|VIBRATE");
pw.println(" set-volume STREAM_TYPE VOLUME_INDEX");
pw.println(" Sets the volume for STREAM_TYPE to VOLUME_INDEX");
+ pw.println(" set-device-volume STREAM_TYPE VOLUME_INDEX NATIVE_DEVICE_TYPE");
+ pw.println(" Sets for NATIVE_DEVICE_TYPE the STREAM_TYPE volume to VOLUME_INDEX");
pw.println(" adj-mute STREAM_TYPE");
pw.println(" mutes the STREAM_TYPE");
pw.println(" adj-unmute STREAM_TYPE");
@@ -143,6 +154,34 @@
return 0;
}
+ private int setRingerMode() {
+ String ringerModeText = getNextArg();
+ if (ringerModeText == null) {
+ getErrPrintWriter().println("Error: no ringer mode specified");
+ return 1;
+ }
+
+ final int ringerMode = getRingerMode(ringerModeText);
+ if (!AudioManager.isValidRingerMode(ringerMode)) {
+ getErrPrintWriter().println(
+ "Error: invalid value of ringerMode, should be one of NORMAL|SILENT|VIBRATE");
+ return 1;
+ }
+
+ final AudioManager am = mService.mContext.getSystemService(AudioManager.class);
+ am.setRingerModeInternal(ringerMode);
+ return 0;
+ }
+
+ private int getRingerMode(String ringerModeText) {
+ return switch (ringerModeText) {
+ case "NORMAL" -> AudioManager.RINGER_MODE_NORMAL;
+ case "VIBRATE" -> AudioManager.RINGER_MODE_VIBRATE;
+ case "SILENT" -> AudioManager.RINGER_MODE_SILENT;
+ default -> -1;
+ };
+ }
+
private int getIsSurroundFormatEnabled() {
String surroundFormatText = getNextArg();
@@ -257,6 +296,23 @@
return 0;
}
+ private int setDeviceVolume() {
+ final Context context = mService.mContext;
+ final AudioDeviceVolumeManager advm = (AudioDeviceVolumeManager) context.getSystemService(
+ Context.AUDIO_DEVICE_VOLUME_SERVICE);
+ final int stream = readIntArg();
+ final int index = readIntArg();
+ final int device = readIntArg();
+
+ final VolumeInfo volume = new VolumeInfo.Builder(stream).setVolumeIndex(index).build();
+ final AudioDeviceAttributes ada = new AudioDeviceAttributes(
+ /*native type*/ device, /*address*/ "foo");
+ getOutPrintWriter().println(
+ "calling AudioDeviceVolumeManager.setDeviceVolume(" + volume + ", " + ada + ")");
+ advm.setDeviceVolume(volume, ada);
+ return 0;
+ }
+
private int adjMute() {
final Context context = mService.mContext;
final AudioManager am = context.getSystemService(AudioManager.class);
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
index cd5d0c8..ff1e5d5 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
@@ -16,13 +16,14 @@
package com.android.server.biometrics.log;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.SensorManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.util.Slog;
@@ -137,7 +138,7 @@
final boolean isFingerprint = mStatsModality == BiometricsProtoEnums.MODALITY_FINGERPRINT;
if (isFace || isFingerprint) {
if ((isFingerprint && acquiredInfo == FingerprintManager.FINGERPRINT_ACQUIRED_START)
- || (isFace && acquiredInfo == FaceManager.FACE_ACQUIRED_START)) {
+ || (isFace && acquiredInfo == FACE_ACQUIRED_START)) {
mFirstAcquireTimeMs = System.currentTimeMillis();
}
} else if (acquiredInfo == BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 8d32235..ef7abdd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -17,6 +17,9 @@
package com.android.server.biometrics.sensors.face.aidl;
import static android.adaptiveauth.Flags.reportBiometricAuthAttempts;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_NOT_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_SENSOR_DIRTY;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR_BASE;
import static android.hardware.face.FaceManager.getAuthHelpMessage;
@@ -43,7 +46,6 @@
import android.hardware.biometrics.face.IFace;
import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceAuthenticationFrame;
-import android.hardware.face.FaceManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
@@ -90,8 +92,8 @@
private final SensorPrivacyManager mSensorPrivacyManager;
@NonNull
private final AuthenticationStateListeners mAuthenticationStateListeners;
- @FaceManager.FaceAcquired
- private int mLastAcquire = FaceManager.FACE_ACQUIRED_UNKNOWN;
+ @BiometricFaceConstants.FaceAcquired
+ private int mLastAcquire = FACE_ACQUIRED_UNKNOWN;
public FaceAuthenticationClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon,
@@ -232,9 +234,9 @@
public boolean wasUserDetected() {
// Do not provide haptic feedback if the user was not detected, and an error (usually
// ERROR_TIMEOUT) is received.
- return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED
- && mLastAcquire != FaceManager.FACE_ACQUIRED_SENSOR_DIRTY
- && mLastAcquire != FaceManager.FACE_ACQUIRED_UNKNOWN;
+ return mLastAcquire != FACE_ACQUIRED_NOT_DETECTED
+ && mLastAcquire != FACE_ACQUIRED_SENSOR_DIRTY
+ && mLastAcquire != FACE_ACQUIRED_UNKNOWN;
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 6b99493..b0e7575 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.face.aidl;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -28,7 +30,6 @@
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.biometrics.face.SensorProps;
-import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.os.Binder;
import android.os.Handler;
@@ -217,6 +218,7 @@
}
@VisibleForTesting @Nullable protected AidlSession getSessionForUser(int userId) {
+ Slog.d(TAG, "getSessionForUser: mCurrentSession: " + mCurrentSession);
if (mCurrentSession != null && mCurrentSession.getUserId() == userId) {
return mCurrentSession;
} else {
@@ -296,7 +298,7 @@
if (client != null && client.isInterruptable()) {
Slog.e(TAG, "Sending face hardware unavailable error for client: " + client);
final ErrorConsumer errorConsumer = (ErrorConsumer) client;
- errorConsumer.onError(FaceManager.FACE_ERROR_HW_UNAVAILABLE,
+ errorConsumer.onError(FACE_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */);
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index b7e3f70..1c6dfe0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -242,6 +242,7 @@
}
@Nullable protected AidlSession getSessionForUser(int userId) {
+ Slog.d(TAG, "getSessionForUser: mCurrentSession: " + mCurrentSession);
if (mCurrentSession != null && mCurrentSession.getUserId() == userId) {
return mCurrentSession;
} else {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 68e2bd6..7106e89 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2764,21 +2764,9 @@
display.setHasContentLocked(hasContent);
shouldScheduleTraversal = true;
}
- if (requestedModeId == 0 && requestedRefreshRate != 0) {
- // Scan supported modes returned by display.getInfo() to find a mode with the same
- // size as the default display mode but with the specified refresh rate instead.
- Display.Mode mode = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
- requestedRefreshRate);
- if (mode != null) {
- requestedModeId = mode.getModeId();
- } else {
- Slog.e(TAG, "Couldn't find a mode for the requestedRefreshRate: "
- + requestedRefreshRate + " on Display: " + displayId);
- }
- }
- mDisplayModeDirector.getAppRequestObserver().setAppRequest(
- displayId, requestedModeId, requestedMinRefreshRate, requestedMaxRefreshRate);
+ mDisplayModeDirector.getAppRequestObserver().setAppRequest(displayId, requestedModeId,
+ requestedRefreshRate, requestedMinRefreshRate, requestedMaxRefreshRate);
// TODO(b/202378408) set minimal post-processing only if it's supported once we have a
// separate API for disabling on-device processing.
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 50b1464..cd07f5a 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -154,6 +154,16 @@
Flags::useFusionProxSensor
);
+ private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState(
+ Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT,
+ Flags::enablePeakRefreshRatePhysicalLimit
+ );
+
+ private final FlagState mIgnoreAppPreferredRefreshRate = new FlagState(
+ Flags.FLAG_IGNORE_APP_PREFERRED_REFRESH_RATE_REQUEST,
+ Flags::ignoreAppPreferredRefreshRateRequest
+ );
+
/**
* @return {@code true} if 'port' is allowed in display layout configuration file.
*/
@@ -312,6 +322,17 @@
return mUseFusionProxSensor.getName();
}
+ public boolean isPeakRefreshRatePhysicalLimitEnabled() {
+ return mPeakRefreshRatePhysicalLimit.isEnabled();
+ }
+
+ /**
+ * @return Whether to ignore preferredRefreshRate app request or not
+ */
+ public boolean ignoreAppPreferredRefreshRateRequest() {
+ return mIgnoreAppPreferredRefreshRate.isEnabled();
+ }
+
/**
* dumps all flagstates
* @param pw printWriter
@@ -343,6 +364,7 @@
pw.println(" " + mRefactorDisplayPowerController);
pw.println(" " + mResolutionBackupRestore);
pw.println(" " + mUseFusionProxSensor);
+ pw.println(" " + mPeakRefreshRatePhysicalLimit);
}
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 a7dd243..a15a8e8 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
@@ -244,3 +244,25 @@
bug: "306203895"
is_fixed_read_only: true
}
+
+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 "
+ bug: "332413475"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "ignore_app_preferred_refresh_rate_request"
+ namespace: "display_manager"
+ description: "Feature flag for DisplayManager to ignore preferred refresh rate app request. It will be handled by SF only."
+ bug: "330810426"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 1c8c8a4..91bd80e 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -222,7 +222,7 @@
displayManagerFlags.isRefreshRateVotingTelemetryEnabled());
mSupportedModesByDisplay = new SparseArray<>();
mDefaultModeByDisplay = new SparseArray<>();
- mAppRequestObserver = new AppRequestObserver();
+ mAppRequestObserver = new AppRequestObserver(displayManagerFlags);
mConfigParameterProvider = new DeviceConfigParameterProvider(injector.getDeviceConfig());
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
mSettingsObserver = new SettingsObserver(context, handler, displayManagerFlags);
@@ -940,6 +940,7 @@
Settings.Secure.getUriFor(Settings.Secure.MATCH_CONTENT_FRAME_RATE);
private final boolean mVsynLowPowerVoteEnabled;
+ private final boolean mPeakRefreshRatePhysicalLimitEnabled;
private final Context mContext;
private float mDefaultPeakRefreshRate;
@@ -950,6 +951,7 @@
super(handler);
mContext = context;
mVsynLowPowerVoteEnabled = flags.isVsyncLowPowerVoteEnabled();
+ mPeakRefreshRatePhysicalLimitEnabled = flags.isPeakRefreshRatePhysicalLimitEnabled();
// We don't want to load from the DeviceConfig while constructing since this leads to
// a spike in the latency of DisplayManagerService startup. This happens because
// reading from the DeviceConfig is an intensive IO operation and having it in the
@@ -1127,11 +1129,19 @@
// used to predict if we're going to be doing frequent refresh rate switching, and if
// so, enable the brightness observer. The logic here is more complicated and fragile
// than necessary, and we should improve it. See b/156304339 for more info.
- Vote peakVote = peakRefreshRate == 0f
+ if (mPeakRefreshRatePhysicalLimitEnabled) {
+ Vote peakVote = peakRefreshRate == 0f
+ ? null
+ : Vote.forPhysicalRefreshRates(0f,
+ Math.max(minRefreshRate, peakRefreshRate));
+ mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
+ peakVote);
+ }
+ Vote peakRenderVote = peakRefreshRate == 0f
? null
: Vote.forRenderFrameRates(0f, Math.max(minRefreshRate, peakRefreshRate));
mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
- peakVote);
+ peakRenderVote);
mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
Vote.forRenderFrameRates(minRefreshRate, Float.POSITIVE_INFINITY));
Vote defaultVote =
@@ -1195,17 +1205,32 @@
public final class AppRequestObserver {
private final SparseArray<Display.Mode> mAppRequestedModeByDisplay;
private final SparseArray<RefreshRateRange> mAppPreferredRefreshRateRangeByDisplay;
+ private final boolean mIgnorePreferredRefreshRate;
- AppRequestObserver() {
+ AppRequestObserver(DisplayManagerFlags flags) {
mAppRequestedModeByDisplay = new SparseArray<>();
mAppPreferredRefreshRateRangeByDisplay = new SparseArray<>();
+ mIgnorePreferredRefreshRate = flags.ignoreAppPreferredRefreshRateRequest();
}
/**
* Sets refresh rates from app request
*/
- public void setAppRequest(int displayId, int modeId,
+ public void setAppRequest(int displayId, int modeId, float requestedRefreshRate,
float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange) {
+
+ if (modeId == 0 && requestedRefreshRate != 0 && !mIgnorePreferredRefreshRate) {
+ // Scan supported modes returned to find a mode with the same
+ // size as the default display mode but with the specified refresh rate instead.
+ Display.Mode mode = findDefaultModeByRefreshRate(displayId, requestedRefreshRate);
+ if (mode != null) {
+ modeId = mode.getModeId();
+ } else {
+ Slog.e(TAG, "Couldn't find a mode for the requestedRefreshRate: "
+ + requestedRefreshRate + " on Display: " + displayId);
+ }
+ }
+
synchronized (mLock) {
setAppRequestedModeLocked(displayId, modeId);
setAppPreferredRefreshRateRangeLocked(displayId, requestedMinRefreshRateRange,
@@ -1213,6 +1238,23 @@
}
}
+ @Nullable
+ private Display.Mode findDefaultModeByRefreshRate(int displayId, float refreshRate) {
+ Display.Mode[] modes;
+ Display.Mode defaultMode;
+ synchronized (mLock) {
+ modes = mSupportedModesByDisplay.get(displayId);
+ defaultMode = mDefaultModeByDisplay.get(displayId);
+ }
+ for (int i = 0; i < modes.length; i++) {
+ if (modes[i].matches(defaultMode.getPhysicalWidth(),
+ defaultMode.getPhysicalHeight(), refreshRate)) {
+ return modes[i];
+ }
+ }
+ return null;
+ }
+
private void setAppRequestedModeLocked(int displayId, int modeId) {
final Display.Mode requestedMode = findModeByIdLocked(displayId, modeId);
if (Objects.equals(requestedMode, mAppRequestedModeByDisplay.get(displayId))) {
diff --git a/services/core/java/com/android/server/display/mode/Vote.java b/services/core/java/com/android/server/display/mode/Vote.java
index 5b987f4..ddb334e 100644
--- a/services/core/java/com/android/server/display/mode/Vote.java
+++ b/services/core/java/com/android/server/display/mode/Vote.java
@@ -76,46 +76,52 @@
int PRIORITY_APP_REQUEST_SIZE = 7;
- // SETTING_PEAK_RENDER_FRAME_RATE has a high priority and will restrict the bounds of the
- // rest of low priority voters. It votes [0, max(PEAK, MIN)]
- int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 8;
+ // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE restricts physical refresh rate to
+ // [0, max(PEAK, MIN)], depending on user settings peakRR/minRR values
+ int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 8;
+
+ // PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE has a higher priority than
+ // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE and will limit render rate to [0, max(PEAK, MIN)]
+ // in case physical refresh rate vote is discarded (due to other high priority votes),
+ // render rate vote can still apply
+ int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 9;
// Restrict all displays to 60Hz when external display is connected. It votes [59Hz, 61Hz].
- int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 9;
+ int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 10;
// Restrict displays max available resolution and refresh rates. It votes [0, LIMIT]
- int PRIORITY_LIMIT_MODE = 10;
+ int PRIORITY_LIMIT_MODE = 11;
// To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh
// rate to max value (same as for PRIORITY_UDFPS) on lock screen
- int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 11;
+ int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 12;
// For concurrent displays we want to limit refresh rate on all displays
- int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 12;
+ int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 13;
// For internal application to limit display modes to specific ids
- int PRIORITY_SYSTEM_REQUESTED_MODES = 13;
+ int PRIORITY_SYSTEM_REQUESTED_MODES = 14;
// LOW_POWER_MODE force the render frame rate to [0, 60HZ] if
// Settings.Global.LOW_POWER_MODE is on.
- int PRIORITY_LOW_POWER_MODE = 14;
+ int PRIORITY_LOW_POWER_MODE = 15;
// PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
// higher priority voters' result is a range, it will fix the rate to a single choice.
// It's used to avoid refresh rate switches in certain conditions which may result in the
// user seeing the display flickering when the switches occur.
- int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 15;
+ int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 16;
// Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
- int PRIORITY_SKIN_TEMPERATURE = 16;
+ int PRIORITY_SKIN_TEMPERATURE = 17;
// The proximity sensor needs the refresh rate to be locked in order to function, so this is
// set to a high priority.
- int PRIORITY_PROXIMITY = 17;
+ int PRIORITY_PROXIMITY = 18;
// The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
// to function, so this needs to be the highest priority of all votes.
- int PRIORITY_UDFPS = 18;
+ int PRIORITY_UDFPS = 19;
// Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
// APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
diff --git a/services/core/java/com/android/server/dreams/Android.bp b/services/core/java/com/android/server/dreams/Android.bp
new file mode 100644
index 0000000..4078a42
--- /dev/null
+++ b/services/core/java/com/android/server/dreams/Android.bp
@@ -0,0 +1,11 @@
+aconfig_declarations {
+ name: "dreams_flags",
+ package: "com.android.server.dreams",
+ container: "system",
+ srcs: ["*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "dreams_flags_lib",
+ aconfig_declarations: "dreams_flags",
+}
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index a818eab..816242d 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -205,7 +205,7 @@
Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
intent.setComponent(name);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, overlayComponentName);
+ DreamService.setDreamOverlayComponent(intent, overlayComponentName);
try {
if (!mContext.bindServiceAsUser(intent, mCurrentDream,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index fc63494..2def5ae 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -45,6 +45,7 @@
import android.hardware.display.AmbientDisplayConfiguration;
import android.net.Uri;
import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -118,6 +119,7 @@
private final DreamController mController;
private final PowerManager mPowerManager;
private final PowerManagerInternal mPowerManagerInternal;
+ private final BatteryManagerInternal mBatteryManagerInternal;
private final PowerManager.WakeLock mDozeWakeLock;
private final ActivityTaskManagerInternal mAtmInternal;
private final PackageManagerInternal mPmInternal;
@@ -186,7 +188,11 @@
private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mIsCharging = (BatteryManager.ACTION_CHARGING.equals(intent.getAction()));
+ if (Flags.useBatteryChangedBroadcast()) {
+ mIsCharging = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
+ } else {
+ mIsCharging = (BatteryManager.ACTION_CHARGING.equals(intent.getAction()));
+ }
}
};
@@ -251,6 +257,12 @@
com.android.internal.R.bool.config_keepDreamingWhenUnplugging);
mDreamsDisabledByAmbientModeSuppressionConfig = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
+
+ if (Flags.useBatteryChangedBroadcast()) {
+ mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
+ } else {
+ mBatteryManagerInternal = null;
+ }
}
@Override
@@ -279,9 +291,15 @@
mContext.registerReceiver(
mDockStateReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT));
+
IntentFilter chargingIntentFilter = new IntentFilter();
- chargingIntentFilter.addAction(BatteryManager.ACTION_CHARGING);
- chargingIntentFilter.addAction(BatteryManager.ACTION_DISCHARGING);
+ if (Flags.useBatteryChangedBroadcast()) {
+ chargingIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ chargingIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ } else {
+ chargingIntentFilter.addAction(BatteryManager.ACTION_CHARGING);
+ chargingIntentFilter.addAction(BatteryManager.ACTION_DISCHARGING);
+ }
mContext.registerReceiver(mChargingReceiver, chargingIntentFilter);
mSettingsObserver = new SettingsObserver(mHandler);
diff --git a/services/core/java/com/android/server/dreams/flags.aconfig b/services/core/java/com/android/server/dreams/flags.aconfig
new file mode 100644
index 0000000..5d35ebd
--- /dev/null
+++ b/services/core/java/com/android/server/dreams/flags.aconfig
@@ -0,0 +1,12 @@
+package: "com.android.server.dreams"
+container: "system"
+
+flag {
+ name: "use_battery_changed_broadcast"
+ namespace: "communal"
+ description: "Use ACTION_BATTERY_CHANGED broadcast to track charging state"
+ bug: "329125239"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/flags/services.aconfig b/services/core/java/com/android/server/flags/services.aconfig
index e43d086..9bbcb0c 100644
--- a/services/core/java/com/android/server/flags/services.aconfig
+++ b/services/core/java/com/android/server/flags/services.aconfig
@@ -17,3 +17,14 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ namespace: "backstage_power"
+ name: "pkg_targeted_battery_changed_not_sticky"
+ description: "Avoid sending the package targeted BATTERY_CHANGED broadcast as sticky"
+ bug: "336832816"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java
index 138186b..4c5a3c2 100644
--- a/services/core/java/com/android/server/input/InputShellCommand.java
+++ b/services/core/java/com/android/server/input/InputShellCommand.java
@@ -333,8 +333,8 @@
out.println();
out.println("The commands and default sources are:");
out.println(" text <string> (Default: keyboard)");
- out.println(" keyevent [--longpress|--doubletap|--async"
- + "|--delay <duration between keycodes in ms>]"
+ out.println(" keyevent [--longpress|--duration <duration to hold key down in ms>]"
+ + " [--doubletap] [--async] [--delay <duration between keycodes in ms>]"
+ " <key code number or name> ..."
+ " (Default: keyboard)");
out.println(" tap <x> <y> (Default: touchscreen)");
@@ -402,6 +402,7 @@
boolean async = false;
boolean doubleTap = false;
long delayMs = 0;
+ long durationMs = 0;
String arg = getNextArgRequired();
do {
@@ -411,9 +412,21 @@
doubleTap = (doubleTap || arg.equals("--doubletap"));
if (arg.equals("--delay")) {
delayMs = Long.parseLong(getNextArgRequired());
+ } else if (arg.equals("--duration")) {
+ durationMs = Long.parseLong(getNextArgRequired());
}
} while ((arg = getNextArg()) != null);
+ if (durationMs > 0 && longPress) {
+ getErrPrintWriter().println(
+ "--duration and --longpress cannot be used at the same time.");
+ throw new IllegalArgumentException(
+ "keyevent args should only contain either durationMs or longPress");
+ }
+ if (longPress) {
+ durationMs = ViewConfiguration.getLongPressTimeout();
+ }
+
boolean firstInput = true;
do {
if (!firstInput && delayMs > 0) {
@@ -422,16 +435,17 @@
firstInput = false;
final int keyCode = KeyEvent.keyCodeFromString(arg);
- sendKeyEvent(inputSource, keyCode, longPress, displayId, async);
+ sendKeyEvent(inputSource, keyCode, durationMs, displayId, async);
if (doubleTap) {
sleep(ViewConfiguration.getDoubleTapMinTime());
- sendKeyEvent(inputSource, keyCode, longPress, displayId, async);
+ sendKeyEvent(inputSource, keyCode, durationMs, displayId, async);
}
} while ((arg = getNextArg()) != null);
}
private void sendKeyEvent(
- int inputSource, int keyCode, boolean longPress, int displayId, boolean async) {
+ int inputSource, int keyCode, long durationMs, int displayId,
+ boolean async) {
final long now = SystemClock.uptimeMillis();
KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0 /* repeatCount */,
@@ -440,13 +454,23 @@
event.setDisplayId(displayId);
injectKeyEvent(event, async);
- if (longPress) {
- sleep(ViewConfiguration.getLongPressTimeout());
- // Some long press behavior would check the event time, we set a new event time here.
- final long nextEventTime = now + ViewConfiguration.getLongPressTimeout();
- KeyEvent longPressEvent = KeyEvent.changeTimeRepeat(
- event, nextEventTime, 1 /* repeatCount */, KeyEvent.FLAG_LONG_PRESS);
- injectKeyEvent(longPressEvent, async);
+ long firstSleepDurationMs = Math.min(durationMs, ViewConfiguration.getLongPressTimeout());
+ if (firstSleepDurationMs > 0) {
+ sleep(firstSleepDurationMs);
+ // Send FLAG_LONG_PRESS right after `longPressTimeout`, and resume sleep if needed.
+ if (durationMs >= ViewConfiguration.getLongPressTimeout()) {
+ // Some long press behavior would check the event time, we set a new event time
+ // here.
+ final long nextEventTime = now + ViewConfiguration.getLongPressTimeout();
+ KeyEvent longPressEvent = KeyEvent.changeTimeRepeat(event, nextEventTime,
+ 1 /* repeatCount */, KeyEvent.FLAG_LONG_PRESS);
+ injectKeyEvent(longPressEvent, async);
+
+ long secondSleepDurationMs = durationMs - firstSleepDurationMs;
+ if (secondSleepDurationMs > 0) {
+ sleep(secondSleepDurationMs);
+ }
+ }
}
injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP), async);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 3bd0a9f..326ef7e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -98,7 +98,10 @@
final int size = imList.size();
mIms = new InputMethodInfo[size];
mSubtypeIds = new int[size];
- int checkedItem = 0;
+ // No items are checked by default. When we have a list of explicitly enabled subtypes,
+ // the implicit subtype is no longer listed, but if it is still the selected one,
+ // no items will be shown as checked.
+ int checkedItem = -1;
for (int i = 0; i < size; ++i) {
final ImeSubtypeListItem item = imList.get(i);
mIms[i] = item.mImi;
@@ -113,6 +116,12 @@
}
}
+ if (checkedItem == -1) {
+ Slog.w(TAG, "Switching menu shown with no item selected"
+ + ", IME id: " + preferredInputMethodId
+ + ", subtype index: " + preferredInputMethodSubtypeId);
+ }
+
if (mDialogWindowContext == null) {
mDialogWindowContext = new InputMethodDialogWindowContext();
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java
index 4636a49..7285151 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java
@@ -244,8 +244,9 @@
// Broadcast messages shouldn't be sent with any permissions tagged per CHRE API
// requirements.
if (!messagePermissions.isEmpty()) {
- Log.wtf(TAG, "Received broadcast message with permissions from "
+ Log.e(TAG, "Received broadcast message with permissions from "
+ message.getNanoAppId());
+ return ErrorCode.PERMANENT_ERROR;
}
ContextHubEventLogger.getInstance().logMessageFromNanoapp(contextHubId, message,
diff --git a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
index a5939e9..a439f16 100644
--- a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
@@ -386,7 +386,7 @@
configs = CarrierConfigManager.getDefaultConfig();
}
for (String configKey : configs.keySet()) {
- if (configKey.startsWith(CarrierConfigManager.Gps.KEY_PREFIX)) {
+ if (configKey != null && configKey.startsWith(CarrierConfigManager.Gps.KEY_PREFIX)) {
String key = configKey
.substring(CarrierConfigManager.Gps.KEY_PREFIX.length())
.toUpperCase(Locale.ROOT);
diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
index 8002300..880787e 100644
--- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
@@ -203,7 +203,7 @@
SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class);
if (subManager != null) {
- if (Flags.subscriptionsListenerThread()) {
+ if (Flags.subscriptionsChangedListenerThread()) {
subManager.addOnSubscriptionsChangedListener(FgThread.getExecutor(),
mOnSubscriptionsChangeListener);
} else {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index f981d79..3998667 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -665,6 +665,9 @@
}
private void addUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
+ if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
+ return;
+ }
synchronized (mLock) {
int uid = mediaSessionRecord.getUid();
mUserEngagedSessionsForFgs.putIfAbsent(uid, new HashSet<>());
@@ -673,6 +676,9 @@
}
private void removeUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
+ if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
+ return;
+ }
synchronized (mLock) {
int uid = mediaSessionRecord.getUid();
Set<MediaSessionRecordImpl> mUidUserEngagedSessionsForFgs =
diff --git a/services/core/java/com/android/server/net/TEST_MAPPING b/services/core/java/com/android/server/net/TEST_MAPPING
index 4fc1a17..ad6b0ca 100644
--- a/services/core/java/com/android/server/net/TEST_MAPPING
+++ b/services/core/java/com/android/server/net/TEST_MAPPING
@@ -1,7 +1,7 @@
{
"presubmit-large": [
{
- "name": "CtsHostsideNetworkTests",
+ "name": "CtsHostsideNetworkPolicyTests",
"options": [
{
"exclude-annotation": "androidx.test.filters.FlakyTest"
diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
index 96f32f3..bf49671 100644
--- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
+++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
@@ -16,7 +16,7 @@
package com.android.server.notification;
-import static android.app.Flags.updateRankingTime;
+import static android.app.Flags.sortSectionByTime;
import static android.app.Notification.FLAG_INSISTENT;
import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
import static android.app.NotificationManager.IMPORTANCE_MIN;
@@ -497,7 +497,7 @@
Slog.v(TAG, "INTERRUPTIVENESS: "
+ record.getKey() + " is interruptive: alerted");
}
- if (updateRankingTime()) {
+ if (sortSectionByTime()) {
if (buzz || beep) {
record.resetRankingTime();
}
@@ -1528,7 +1528,7 @@
// recent conversation
if (record.isConversation()
- && record.getNotification().when > mLastAvalancheTriggerTimestamp) {
+ && record.getNotification().getWhen() > mLastAvalancheTriggerTimestamp) {
return true;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bff3d39..ca6ae63 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -25,6 +25,7 @@
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR;
import static android.app.Flags.lifetimeExtensionRefactor;
+import static android.app.Flags.sortSectionByTime;
import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO;
import static android.app.Notification.EXTRA_LARGE_ICON_BIG;
@@ -266,7 +267,6 @@
import android.os.UserManager;
import android.os.WorkSource;
import android.permission.PermissionManager;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.notification.Adjustment;
@@ -313,7 +313,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.IPlatformCompat;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags;
import com.android.internal.logging.InstanceId;
@@ -704,7 +703,6 @@
private ConditionProviders mConditionProviders;
private NotificationUsageStats mUsageStats;
private boolean mLockScreenAllowSecureNotifications = true;
- boolean mSystemExemptFromDismissal = false;
final ArrayMap<String, ArrayMap<Integer,
RemoteCallbackList<ICallNotificationEventCallback>>>
mCallNotificationEventCallbacks = new ArrayMap<>();
@@ -722,7 +720,6 @@
private GroupHelper mGroupHelper;
private int mAutoGroupAtCount;
private boolean mIsTelevision;
- private DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener;
protected NotificationAttentionHelper mAttentionHelper;
private int mWarnRemoteViewsSizeBytes;
@@ -973,18 +970,6 @@
}
protected void setDefaultAssistantForUser(int userId) {
- String overrideDefaultAssistantString = DeviceConfig.getProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE);
- if (overrideDefaultAssistantString != null) {
- ArraySet<ComponentName> approved = mAssistants.queryPackageForServices(
- overrideDefaultAssistantString,
- MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- userId);
- for (int i = 0; i < approved.size(); i++) {
- if (allowAssistant(userId, approved.valueAt(i))) return;
- }
- }
ArraySet<ComponentName> defaults = mAssistants.getDefaultComponents();
// We should have only one default assistant by default
// allowAssistant should execute once in practice
@@ -2670,10 +2655,6 @@
mStatsManager.clearPullAtomCallback(DND_MODE_RULE);
mAppOps.stopWatchingMode(mAppOpsListener);
mAlarmManager.cancelAll();
-
- if (mDeviceConfigChangedListener != null) {
- DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigChangedListener);
- }
}
protected String[] getStringArrayResource(int key) {
@@ -2744,27 +2725,6 @@
publishLocalService(NotificationManagerInternal.class, mInternalService);
}
- void registerDeviceConfigChange() {
- mDeviceConfigChangedListener = properties -> {
- if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())) {
- return;
- }
- for (String name : properties.getKeyset()) {
- if (SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE.equals(name)) {
- mAssistants.resetDefaultAssistantsIfNecessary();
- }
- }
- };
- mSystemExemptFromDismissal = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
- /* name= */ "application_exemptions",
- /* defaultValue= */ true);
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- new HandlerExecutor(mHandler),
- mDeviceConfigChangedListener);
- }
-
private void registerNotificationPreferencesPullers() {
mPullAtomCallback = new StatsPullAtomCallbackImpl();
mStatsManager.setPullAtomCallback(
@@ -2938,7 +2898,6 @@
mAssistants.onBootPhaseAppsCanStart();
mConditionProviders.onBootPhaseAppsCanStart();
mHistoryManager.onBootPhaseAppsCanStart();
- registerDeviceConfigChange();
migrateDefaultNAS();
maybeShowInitialReviewPermissionsNotification();
@@ -7738,7 +7697,7 @@
return true;
}
// Check if an app has been given system exemption
- return mSystemExemptFromDismissal && mAppOps.checkOpNoThrow(
+ return mAppOps.checkOpNoThrow(
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
ai.packageName) == MODE_ALLOWED;
}
@@ -8635,7 +8594,7 @@
r.isUpdate = true;
final boolean isInterruptive = isVisuallyInterruptive(old, r);
r.setTextChanged(isInterruptive);
- if (android.app.Flags.updateRankingTime()) {
+ if (sortSectionByTime()) {
if (isInterruptive) {
r.resetRankingTime();
}
@@ -8780,7 +8739,7 @@
return false;
}
- if (android.app.Flags.updateRankingTime()) {
+ if (sortSectionByTime()) {
// Ignore visual interruptions from FGS/UIJs because users
// consider them one 'session'. Count them for everything else.
if (r.getSbn().getNotification().isFgsOrUij()) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 38c95f7..0c6a6c8 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -18,7 +18,7 @@
import static android.app.Flags.restrictAudioAttributesAlarm;
import static android.app.Flags.restrictAudioAttributesCall;
import static android.app.Flags.restrictAudioAttributesMedia;
-import static android.app.Flags.updateRankingTime;
+import static android.app.Flags.sortSectionByTime;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
@@ -580,7 +580,7 @@
pw.println(prefix + "deleteIntent=" + notification.deleteIntent);
pw.println(prefix + "number=" + notification.number);
pw.println(prefix + "groupAlertBehavior=" + notification.getGroupAlertBehavior());
- pw.println(prefix + "when=" + notification.when);
+ pw.println(prefix + "when=" + notification.when + "/" + notification.getWhen());
pw.print(prefix + "tickerText=");
if (!TextUtils.isEmpty(notification.tickerText)) {
@@ -1092,9 +1092,9 @@
private long calculateRankingTimeMs(long previousRankingTimeMs) {
Notification n = getNotification();
// Take developer provided 'when', unless it's in the future.
- if (updateRankingTime()) {
- if (n.hasAppProvidedWhen() && n.when <= getSbn().getPostTime()){
- return n.when;
+ if (sortSectionByTime()) {
+ if (n.hasAppProvidedWhen() && n.getWhen() <= getSbn().getPostTime()){
+ return n.getWhen();
}
} else {
if (n.when != 0 && n.when <= getSbn().getPostTime()) {
@@ -1211,7 +1211,7 @@
}
public void resetRankingTime() {
- if (updateRankingTime()) {
+ if (sortSectionByTime()) {
mRankingTimeMs = calculateRankingTimeMs(getSbn().getPostTime());
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
index 9a6ea2c..65ef53f 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -542,7 +542,7 @@
this.is_locked = p.r.isLocked();
this.age_in_minutes = NotificationRecordLogger.getAgeInMinutes(
- p.r.getSbn().getPostTime(), p.r.getSbn().getNotification().when);
+ p.r.getSbn().getPostTime(), p.r.getSbn().getNotification().getWhen());
}
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 1f2ad07e..309e945 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -26,6 +26,7 @@
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.os.UserHandle.USER_SYSTEM;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
@@ -139,6 +140,8 @@
private static final String ATT_VERSION = "version";
private static final String ATT_NAME = "name";
private static final String ATT_UID = "uid";
+
+ private static final String ATT_USERID = "userid";
private static final String ATT_ID = "id";
private static final String ATT_ALLOW_BUBBLE = "allow_bubble";
private static final String ATT_PRIORITY = "priority";
@@ -268,7 +271,7 @@
}
if (type == XmlPullParser.START_TAG) {
if (TAG_STATUS_ICONS.equals(tag)) {
- if (forRestore && userId != UserHandle.USER_SYSTEM) {
+ if (forRestore && userId != USER_SYSTEM) {
continue;
}
mHideSilentStatusBarIcons = parser.getAttributeBoolean(null,
@@ -311,8 +314,16 @@
: 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
+ // is pending app install needs the user id that the data was restored to
+ int fixedUserId = userId;
+ if (Flags.persistIncompleteRestoreData()) {
+ if (!forRestore && uid == UNKNOWN_UID) {
+ fixedUserId = parser.getAttributeInt(null, ATT_USERID, USER_SYSTEM);
+ }
+ }
PackagePreferences r = getOrCreatePackagePreferencesLocked(
- name, userId, uid,
+ name, fixedUserId, uid,
appImportance,
parser.getAttributeInt(null, ATT_PRIORITY, DEFAULT_PRIORITY),
parser.getAttributeInt(null, ATT_VISIBILITY, DEFAULT_VISIBILITY),
@@ -504,6 +515,9 @@
}
if (r.uid == UNKNOWN_UID) {
+ if (Flags.persistIncompleteRestoreData()) {
+ r.userId = userId;
+ }
mRestoredWithoutUids.put(unrestoredPackageKey(pkg, userId), r);
} else {
mPackagePreferences.put(key, r);
@@ -674,6 +688,7 @@
if (Flags.persistIncompleteRestoreData() && r.uid == UNKNOWN_UID) {
out.attributeLong(null, ATT_CREATION_TIME, r.creationTime);
+ out.attributeInt(null, ATT_USERID, r.userId);
}
if (!forBackup) {
@@ -2947,6 +2962,8 @@
boolean migrateToPm = false;
long creationTime;
+ @UserIdInt int userId;
+
Delegate delegate = null;
ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
Map<String, NotificationChannelGroup> groups = new ConcurrentHashMap<>();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 7756801..03dd935 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -147,11 +147,9 @@
if (sortSectionByTime()) {
final String groupKey = record.getGroupKey();
NotificationRecord existingProxy = mProxyByGroupTmp.get(groupKey);
- // summaries are mostly hidden in systemui - if there is a child notification
- // with better information, use its rank
- if (existingProxy == null
- || (existingProxy.getNotification().isGroupSummary()
- && !existingProxy.getNotification().hasAppProvidedWhen())) {
+ // summaries are mostly hidden in systemui - if there is a child notification,
+ // use its rank
+ if (existingProxy == null || existingProxy.getNotification().isGroupSummary()) {
mProxyByGroupTmp.put(groupKey, record);
}
} else {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 4747689..143bc5c 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1725,7 +1725,28 @@
synchronized (mConfigLock) {
if (policy == null || mConfig == null) return;
final ZenModeConfig newConfig = mConfig.copy();
- newConfig.applyNotificationPolicy(policy);
+ if (Flags.modesApi() && !Flags.modesUi()) {
+ // Fix for b/337193321 -- propagate changes to notificationPolicy to rules where
+ // the user cannot edit zen policy to emulate the previous "inheritance".
+ ZenPolicy previousPolicy = ZenAdapters.notificationPolicyToZenPolicy(
+ newConfig.toNotificationPolicy());
+ ZenPolicy newPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
+
+ newConfig.applyNotificationPolicy(policy);
+
+ if (!previousPolicy.equals(newPolicy)) {
+ for (ZenRule rule : newConfig.automaticRules.values()) {
+ if (!SystemZenRules.isSystemOwnedRule(rule)
+ && rule.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ && (rule.zenPolicy == null || rule.zenPolicy.equals(previousPolicy)
+ || rule.zenPolicy.equals(getDefaultZenPolicy()))) {
+ rule.zenPolicy = newPolicy;
+ }
+ }
+ }
+ } else {
+ newConfig.applyNotificationPolicy(policy);
+ }
setConfigLocked(newConfig, null, origin, "setNotificationPolicy", callingUid);
}
}
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index c8fd7e4..8a85328 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -19,6 +19,7 @@
import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.AppOpsManager;
@@ -68,6 +69,7 @@
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
@@ -335,14 +337,22 @@
}
static class Injector {
+ class RoleManagerWrapper {
+ List<String> getRoleHolders(@NonNull String roleName) {
+ return mContext.getSystemService(RoleManager.class).getRoleHolders(roleName);
+ }
+ }
+
Context mContext;
ArraySet<String> mAllowlistedPackages;
AtomicFile mMappingFile;
+ RoleManagerWrapper mRoleManagerWrapper;
Injector(Context context, ArraySet<String> allowlistedPackages, AtomicFile mappingFile) {
mContext = context;
mAllowlistedPackages = allowlistedPackages;
mMappingFile = mappingFile;
+ mRoleManagerWrapper = new RoleManagerWrapper();
}
Context getContext() {
@@ -368,6 +378,10 @@
void setSystemProperty(String key, String value) {
SystemProperties.set(key, value);
}
+
+ RoleManagerWrapper getRoleManagerWrapper() {
+ return mRoleManagerWrapper;
+ }
}
BugreportManagerServiceImpl(Context context) {
@@ -546,7 +560,7 @@
if (!allowlisted) {
final long token = Binder.clearCallingIdentity();
try {
- allowlisted = mContext.getSystemService(RoleManager.class).getRoleHolders(
+ allowlisted = mInjector.getRoleManagerWrapper().getRoleHolders(
ROLE_SYSTEM_AUTOMOTIVE_PROJECTION).contains(callingPackage);
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java
index 278deb8..369029ad 100644
--- a/services/core/java/com/android/server/pm/BroadcastHelper.java
+++ b/services/core/java/com/android/server/pm/BroadcastHelper.java
@@ -966,7 +966,14 @@
if (packageRemovedInfo.mIsAppIdRemoved) {
// If a system app's updates are uninstalled the UID is not actually removed. Some
// services need to know the package name affected.
- if (isReplace) {
+ //
+ // When setting Intent.EXTRA_REPLACING is true for isReplace or isArchived above,
+ // the system triggers AppOpsService#resetAllModes in
+ // ActivityManagerService#broadcastIntentLockedTraced when the action is
+ // ACTION_UID_REMOVED. Add Intent.EXTRA_PACKAGE_NAME for isReplace or isArchived too.
+ // Because AppOpsService#resetAllModes needs the packageName to define which uid to be
+ // reset. If there is no package name, it resets the all appOps for all uids.
+ if (isReplace || isArchived) {
extras.putString(Intent.EXTRA_PACKAGE_NAME, removedPackage);
}
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index b2c6c49..47ee1d0 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -513,7 +513,11 @@
// Legacy behavior to report appId as UID here.
// The final broadcasts will contain a per-user UID.
outInfo.mUid = ps.getAppId();
- outInfo.mIsAppIdRemoved = true;
+ // Only send Intent.ACTION_UID_REMOVED when flag & DELETE_KEEP_DATA is 0
+ // i.e. the mDataRemoved is true
+ if (outInfo.mDataRemoved) {
+ outInfo.mIsAppIdRemoved = true;
+ }
mPm.scheduleWritePackageRestrictions(user);
return;
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 36790ab..326d414d 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -89,6 +89,7 @@
import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists;
import static com.android.server.pm.PackageManagerServiceUtils.deriveAbiOverride;
+import static com.android.server.pm.PackageManagerServiceUtils.extractAppMetadataFromApk;
import static com.android.server.pm.PackageManagerServiceUtils.isInstalledByAdb;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive;
@@ -500,6 +501,36 @@
mPm.setUpCustomResolverActivity(pkg, pkgSetting);
}
+ // When upgrading a package, pkgSetting is copied from oldPkgSetting. Clear the app
+ // metadata file path for the new package.
+ if (oldPkgSetting != null) {
+ pkgSetting.setAppMetadataFilePath(null);
+ }
+ // If the app metadata file path is not null then this is a system app with a preloaded app
+ // metadata file on the system image. Do not reset the path and source if this is the
+ // case.
+ if (pkgSetting.getAppMetadataFilePath() == null) {
+ File dir = new File(pkg.getPath());
+ if (pkgSetting.isSystem()) {
+ dir = new File(Environment.getDataDirectory(),
+ "app-metadata/" + pkg.getPackageName());
+ }
+ File appMetadataFile = new File(dir, APP_METADATA_FILE_NAME);
+ if (appMetadataFile.exists()) {
+ pkgSetting.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
+ if (Flags.aslInApkAppMetadataSource()) {
+ pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_INSTALLER);
+ }
+ } else if (Flags.aslInApkAppMetadataSource()) {
+ Map<String, PackageManager.Property> properties = pkg.getProperties();
+ if (properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL_PATH)) {
+ // ASL file extraction is done in post-install
+ pkgSetting.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
+ pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_APK);
+ }
+ }
+ }
+
if (pkg.getPackageName().equals("android")) {
mPm.setPlatformPackage(pkg, pkgSetting);
}
@@ -573,12 +604,16 @@
(scanFlags & SCAN_DONT_KILL_APP) != 0 /* retainImplicitGrantOnReplace */);
mPm.addAllPackageProperties(pkg);
- if (oldPkgSetting == null || oldPkgSetting.getPkg() == null) {
- mPm.mDomainVerificationManager.addPackage(pkgSetting,
- request.getPreVerifiedDomains());
- } else {
- mPm.mDomainVerificationManager.migrateState(oldPkgSetting, pkgSetting,
- request.getPreVerifiedDomains());
+ // Only verify app links for non-archival installations, otherwise there won't be any
+ // declared app links.
+ if (!request.isArchived()) {
+ if (oldPkgSetting == null || oldPkgSetting.getPkg() == null) {
+ mPm.mDomainVerificationManager.addPackage(pkgSetting,
+ request.getPreVerifiedDomains());
+ } else {
+ mPm.mDomainVerificationManager.migrateState(oldPkgSetting, pkgSetting,
+ request.getPreVerifiedDomains());
+ }
}
int collectionSize = ArrayUtils.size(pkg.getInstrumentations());
@@ -2215,24 +2250,6 @@
installRequest.setNewUsers(
ps.queryInstalledUsers(allUsers, true));
ps.setUpdateAvailable(false /*updateAvailable*/);
-
- File appMetadataFile = new File(ps.getPath(), APP_METADATA_FILE_NAME);
- if (appMetadataFile.exists()) {
- ps.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
- if (Flags.aslInApkAppMetadataSource()) {
- ps.setAppMetadataSource(APP_METADATA_SOURCE_INSTALLER);
- }
- } else {
- Map<String, PackageManager.Property> properties = parsedPackage.getProperties();
- if (Flags.aslInApkAppMetadataSource()
- && properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL_PATH)) {
- // ASL file extraction is done in post-install
- ps.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
- ps.setAppMetadataSource(APP_METADATA_SOURCE_APK);
- } else {
- ps.setAppMetadataFilePath(null);
- }
- }
}
if (installRequest.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
// If this is an archival installation then we'll initialize the archive status,
@@ -2829,8 +2846,8 @@
if (succeeded) {
if (Flags.aslInApkAppMetadataSource()
&& pkgSetting.getAppMetadataSource() == APP_METADATA_SOURCE_APK) {
- if (!PackageManagerServiceUtils.extractAppMetadataFromApk(request.getPkg(),
- pkgSetting.getAppMetadataFilePath())) {
+ if (!extractAppMetadataFromApk(request.getPkg(),
+ pkgSetting.getAppMetadataFilePath(), pkgSetting.isSystem())) {
synchronized (mPm.mLock) {
PackageSetting setting = mPm.mSettings.getPackageLPr(packageName);
if (setting != null) {
@@ -3815,6 +3832,18 @@
new IncrementalProgressListener(parsedPackage.getPackageName(), mPm));
}
}
+
+ if (Flags.aslInApkAppMetadataSource()
+ && scanResult.mPkgSetting.getAppMetadataSource() == APP_METADATA_SOURCE_APK) {
+ if (!extractAppMetadataFromApk(parsedPackage,
+ scanResult.mPkgSetting.getAppMetadataFilePath(),
+ scanResult.mPkgSetting.isSystem())) {
+ synchronized (mPm.mLock) {
+ scanResult.mPkgSetting.setAppMetadataFilePath(null)
+ .setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN);
+ }
+ }
+ }
return scanResult.mPkgSetting.getPkg();
}
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index 9bdf613..dec97fb 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -284,7 +284,7 @@
}
String currentLauncherPackageName = getCurrentLauncherPackageName(getParentUserId(userId));
- if ((currentLauncherPackageName == null || !callerPackageName.equals(
+ if ((currentLauncherPackageName == null || !TextUtils.equals(callerPackageName,
currentLauncherPackageName)) && callingUid != Process.SHELL_UID) {
// TODO(b/311619990): Remove dependency on SHELL_UID for testing
Slog.e(TAG, TextUtils.formatSimple(
@@ -830,7 +830,7 @@
mPm.mInstallerService.getAllSessions(userId).getList();
for (int idx = 0; idx < activeSessions.size(); idx++) {
PackageInstaller.SessionInfo activeSession = activeSessions.get(idx);
- if (activeSession.appPackageName.equals(packageName)
+ if (TextUtils.equals(activeSession.appPackageName, packageName)
&& activeSession.userId == userId && activeSession.active
&& activeSession.isUnarchival()) {
return activeSession;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0f4e482..ae485ed 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3984,6 +3984,8 @@
// packageName -> list of components to send broadcasts now
final ArrayMap<String, ArrayList<String>> sendNowBroadcasts = new ArrayMap<>(targetSize);
+ final List<PackageMetrics.ComponentStateMetrics> componentStateMetricsList =
+ new ArrayList<PackageMetrics.ComponentStateMetrics>();
synchronized (mLock) {
Computer computer = snapshotComputer();
boolean scheduleBroadcastMessage = false;
@@ -3997,11 +3999,17 @@
// update enabled settings
final ComponentEnabledSetting setting = settings.get(i);
final String packageName = setting.getPackageName();
- if (!setEnabledSettingInternalLocked(computer, pkgSettings.get(packageName),
- setting, userId, callingPackage)) {
+ final PackageSetting packageSetting = pkgSettings.get(packageName);
+ final PackageMetrics.ComponentStateMetrics componentStateMetrics =
+ new PackageMetrics.ComponentStateMetrics(setting,
+ UserHandle.getUid(userId, packageSetting.getAppId()),
+ packageSetting.getEnabled(userId));
+ if (!setEnabledSettingInternalLocked(computer, packageSetting, setting, userId,
+ callingPackage)) {
continue;
}
anyChanged = true;
+ componentStateMetricsList.add(componentStateMetrics);
if ((setting.getEnabledFlags() & PackageManager.SYNCHRONOUS) != 0) {
isSynchronous = true;
@@ -4029,6 +4037,9 @@
return;
}
+ // Log the metrics when the component state is changed.
+ PackageMetrics.reportComponentStateChanged(computer, componentStateMetricsList, userId);
+
if (isSynchronous) {
flushPackageRestrictionsAsUserInternalLocked(userId);
} else {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 5f04a0b..fa54f6e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -1659,11 +1659,23 @@
* Extract the app.metadata file from apk.
*/
public static boolean extractAppMetadataFromApk(AndroidPackage pkg,
- String appMetadataFilePath) {
+ String appMetadataFilePath, boolean isSystem) {
if (appMetadataFilePath == null) {
return false;
}
File appMetadataFile = new File(appMetadataFilePath);
+ if (appMetadataFile.exists()) {
+ return true;
+ }
+ if (isSystem) {
+ try {
+ makeDirRecursive(new File(appMetadataFilePath).getParentFile(), 0700);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to create app metadata dir for package "
+ + pkg.getPackageName() + ": " + e.getMessage());
+ return false;
+ }
+ }
Map<String, Property> properties = pkg.getProperties();
if (!properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL_PATH)) {
return false;
@@ -1677,7 +1689,8 @@
for (int i = 0; i < splits.size(); i++) {
try (ZipFile zipFile = new ZipFile(splits.get(i).getPath())) {
ZipEntry zipEntry = zipFile.getEntry(fileInApkPath);
- if (zipEntry != null && zipEntry.getSize() <= getAppMetadataSizeLimit()) {
+ if (zipEntry != null
+ && (isSystem || zipEntry.getSize() <= getAppMetadataSizeLimit())) {
try (InputStream in = zipFile.getInputStream(zipEntry)) {
try (FileOutputStream out = new FileOutputStream(appMetadataFile)) {
FileUtils.copy(in, out);
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index a0b6897..20598f9 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -19,12 +19,21 @@
import static android.os.Process.INVALID_UID;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.admin.SecurityLog;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.content.pm.Flags;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Pair;
+import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.util.FrameworkStatsLog;
@@ -41,12 +50,14 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* Metrics class for reporting stats to logging infrastructures like statsd
*/
final class PackageMetrics {
+ private static final String TAG = "PackageMetrics";
public static final int STEP_PREPARE = 1;
public static final int STEP_SCAN = 2;
public static final int STEP_RECONCILE = 3;
@@ -344,4 +355,76 @@
SecurityLog.writeEvent(SecurityLog.TAG_PACKAGE_UNINSTALLED, packageName, versionCode,
userId);
}
+
+ public static class ComponentStateMetrics {
+ public int mUid;
+ public int mComponentOldState;
+ public int mComponentNewState;
+ public boolean mIsForWholeApp;
+ @NonNull private String mPackageName;
+ @Nullable private String mClassName;
+
+ ComponentStateMetrics(@NonNull PackageManager.ComponentEnabledSetting setting, int uid,
+ int componentOldState) {
+ mUid = uid;
+ mComponentOldState = componentOldState;
+ mComponentNewState = setting.getEnabledState();
+ mIsForWholeApp = !setting.isComponent();
+ mPackageName = setting.getPackageName();
+ mClassName = setting.getClassName();
+ }
+
+ public boolean isSameComponent(ActivityInfo activityInfo) {
+ if (activityInfo == null) {
+ return false;
+ }
+ return mIsForWholeApp ? TextUtils.equals(activityInfo.packageName, mPackageName)
+ : activityInfo.getComponentName().equals(
+ new ComponentName(mPackageName, mClassName));
+ }
+ }
+
+ public static void reportComponentStateChanged(@NonNull Computer computer,
+ List<ComponentStateMetrics> componentStateMetricsList, @UserIdInt int userId) {
+ if (!Flags.componentStateChangedMetrics()) {
+ return;
+ }
+ if (componentStateMetricsList == null || componentStateMetricsList.isEmpty()) {
+ Slog.d(TAG, "Fail to report component state due to metrics is empty");
+ return;
+ }
+ boolean isLauncher = false;
+ final List<ResolveInfo> resolveInfosForLauncher = getHomeActivitiesResolveInfoAsUser(
+ computer, userId);
+ final int resolveInfosForLauncherSize =
+ resolveInfosForLauncher != null ? resolveInfosForLauncher.size() : 0;
+ final int metricsSize = componentStateMetricsList.size();
+ for (int i = 0; i < metricsSize; i++) {
+ final ComponentStateMetrics componentStateMetrics = componentStateMetricsList.get(i);
+ for (int j = 0; j < resolveInfosForLauncherSize; j++) {
+ ResolveInfo resolveInfo = resolveInfosForLauncher.get(j);
+ if (componentStateMetrics.isSameComponent(resolveInfo.activityInfo)) {
+ isLauncher = true;
+ break;
+ }
+ }
+ reportComponentStateChanged(componentStateMetrics.mUid,
+ componentStateMetrics.mComponentOldState,
+ componentStateMetrics.mComponentNewState,
+ isLauncher,
+ componentStateMetrics.mIsForWholeApp);
+ }
+ }
+
+ private static void reportComponentStateChanged(int uid, int componentOldState,
+ int componentNewState, boolean isLauncher, boolean isForWholeApp) {
+ FrameworkStatsLog.write(FrameworkStatsLog.COMPONENT_STATE_CHANGED_REPORTED,
+ uid, componentOldState, componentNewState, isLauncher, isForWholeApp);
+ }
+
+ private static List<ResolveInfo> getHomeActivitiesResolveInfoAsUser(@NonNull Computer computer,
+ @UserIdInt int userId) {
+ return computer.queryIntentActivitiesInternal(computer.getHomeIntent(), /* resolvedType */
+ null, /* flags */ 0, userId);
+ }
}
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index 2e67b2f..9ab6016 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -170,6 +170,7 @@
}
}
+ boolean isPendingRestoreBefore = false;
if (pkgSetting != null && oldSharedUserSetting != sharedUserSetting) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Package " + parsedPackage.getPackageName() + " shared user changed from "
@@ -178,6 +179,9 @@
+ " to "
+ (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
+ "; replacing with new");
+ // Preserve the value of isPendingRestore. We need to set it to the new PackageSetting
+ // if the value is true to restore the app
+ isPendingRestoreBefore = pkgSetting.isPendingRestore();
pkgSetting = null;
}
@@ -224,6 +228,11 @@
parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
newDomainSetId,
parsedPackage.getTargetSdkVersion(), parsedPackage.getRestrictUpdateHash());
+
+ // If isPendingRestore is true before, set the value true to the PackageSetting
+ if (isPendingRestoreBefore) {
+ pkgSetting.setPendingRestore(true);
+ }
} else {
// make a deep copy to avoid modifying any existing system state.
pkgSetting = new PackageSetting(pkgSetting);
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index 5e24673..00582bf 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -46,7 +46,7 @@
/**
* Launcher information used by {@link ShortcutService}.
*
- * All methods should be guarded by {@code #mShortcutUser.mService.mLock}.
+ * All methods should be guarded by {@code ShortcutPackageItem#mPackageItemLock}.
*/
class ShortcutLauncher extends ShortcutPackageItem {
private static final String TAG = ShortcutService.TAG;
@@ -66,7 +66,7 @@
/**
* Package name -> IDs.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
private final ArrayMap<UserPackage, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
private ShortcutLauncher(@NonNull ShortcutUser shortcutUser,
@@ -99,7 +99,7 @@
*/
private void onRestoreBlocked() {
final ArrayList<UserPackage> pinnedPackages;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
pinnedPackages = new ArrayList<>(mPinnedShortcuts.keySet());
mPinnedShortcuts.clear();
}
@@ -138,7 +138,7 @@
final int idSize = ids.size();
if (idSize == 0) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
mPinnedShortcuts.remove(up);
}
} else {
@@ -165,7 +165,7 @@
floatingSet.add(id);
}
}
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final ArraySet<String> prevSet = mPinnedShortcuts.get(up);
if (prevSet != null) {
for (String id : floatingSet) {
@@ -187,7 +187,7 @@
@Nullable
public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName,
@UserIdInt int packageUserId) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final ArraySet<String> pinnedShortcuts = mPinnedShortcuts.get(
UserPackage.of(packageUserId, packageName));
return pinnedShortcuts == null ? null : new ArraySet<>(pinnedShortcuts);
@@ -198,7 +198,7 @@
* Return true if the given shortcut is pinned by this launcher.<code></code>
*/
public boolean hasPinned(ShortcutInfo shortcut) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final ArraySet<String> pinned = mPinnedShortcuts.get(
UserPackage.of(shortcut.getUserId(), shortcut.getPackage()));
return (pinned != null) && pinned.contains(shortcut.getId());
@@ -211,7 +211,7 @@
public void addPinnedShortcut(@NonNull String packageName, @UserIdInt int packageUserId,
String id, boolean forPinRequest) {
final ArrayList<String> pinnedList;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final ArraySet<String> pinnedSet = mPinnedShortcuts.get(
UserPackage.of(packageUserId, packageName));
if (pinnedSet != null) {
@@ -227,7 +227,7 @@
}
boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return mPinnedShortcuts.remove(UserPackage.of(packageUserId, packageName)) != null;
}
}
@@ -253,7 +253,7 @@
return;
}
final ArrayMap<UserPackage, ArraySet<String>> pinnedShortcuts;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
pinnedShortcuts = new ArrayMap<>(mPinnedShortcuts);
}
final int size = pinnedShortcuts.size();
@@ -366,7 +366,7 @@
: ShortcutService.parseIntAttribute(parser,
ATTR_PACKAGE_USER_ID, ownerUserId);
ids = new ArraySet<>();
- synchronized (ret.mLock) {
+ synchronized (ret.mPackageItemLock) {
ret.mPinnedShortcuts.put(
UserPackage.of(packageUserId, packageName), ids);
}
@@ -407,7 +407,7 @@
pw.println();
final ArrayMap<UserPackage, ArraySet<String>> pinnedShortcuts;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
pinnedShortcuts = new ArrayMap<>(mPinnedShortcuts);
}
final int size = pinnedShortcuts.size();
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 449e9ab..c929c1f 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -163,20 +163,20 @@
/**
* An in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
private final ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
/**
* A temporary copy of shortcuts that are to be cleared once persisted into AppSearch, keyed on
* IDs.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
private final ArrayMap<String, ShortcutInfo> mTransientShortcuts = new ArrayMap<>(0);
/**
* All the share targets from the package
*/
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
private final ArrayList<ShareTargetInfo> mShareTargets = new ArrayList<>(0);
/**
@@ -193,10 +193,10 @@
private long mLastKnownForegroundElapsedTime;
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
private long mLastReportedTime;
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
private boolean mIsAppSearchSchemaUpToDate;
private ShortcutPackage(ShortcutUser shortcutUser,
@@ -233,7 +233,7 @@
}
public int getShortcutCount() {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return mShortcuts.size();
}
}
@@ -276,7 +276,7 @@
@Nullable
public ShortcutInfo findShortcutById(@Nullable final String id) {
if (id == null) return null;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return mShortcuts.get(id);
}
}
@@ -354,7 +354,7 @@
*/
private ShortcutInfo forceDeleteShortcutInner(@NonNull String id) {
final ShortcutInfo shortcut;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
shortcut = mShortcuts.remove(id);
if (shortcut != null) {
removeIcon(shortcut);
@@ -409,7 +409,7 @@
if (newShortcut.isExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER)) {
if (isAppSearchEnabled()) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
mTransientShortcuts.put(newShortcut.getId(), newShortcut);
}
}
@@ -482,7 +482,7 @@
if (newShortcut.isExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER)) {
if (isAppSearchEnabled()) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
mTransientShortcuts.put(newShortcut.getId(), newShortcut);
}
}
@@ -506,7 +506,7 @@
final ShortcutService service = mShortcutUser.mService;
// Ensure the total number of shortcuts doesn't exceed the hard limit per app.
final int maxShortcutPerApp = service.getMaxAppShortcuts();
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
!si.isPinned()).collect(Collectors.toList());
if (appShortcuts.size() >= maxShortcutPerApp) {
@@ -555,7 +555,7 @@
public List<ShortcutInfo> deleteAllDynamicShortcuts() {
final long now = mShortcutUser.mService.injectCurrentTimeMillis();
boolean changed = false;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
ShortcutInfo si = mShortcuts.valueAt(i);
if (si.isDynamic() && si.isVisibleToPublisher()) {
@@ -914,7 +914,7 @@
List<ShortcutManager.ShareShortcutInfo> getMatchingShareTargets(
@NonNull final IntentFilter filter, @Nullable final String pkgName) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final List<ShareTargetInfo> matchedTargets = new ArrayList<>();
for (int i = 0; i < mShareTargets.size(); i++) {
final ShareTargetInfo target = mShareTargets.get(i);
@@ -967,7 +967,7 @@
}
public boolean hasShareTargets() {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return !mShareTargets.isEmpty();
}
}
@@ -978,7 +978,7 @@
* the app's Xml resource.
*/
int getSharingShortcutCount() {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
if (mShareTargets.isEmpty()) {
return 0;
}
@@ -1017,7 +1017,7 @@
/**
* Return the filenames (excluding path names) of icon bitmap files from this package.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
private ArraySet<String> getUsedBitmapFilesLocked() {
final ArraySet<String> usedFiles = new ArraySet<>(1);
forEachShortcut(si -> {
@@ -1029,7 +1029,7 @@
}
public void cleanupDanglingBitmapFiles(@NonNull File path) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
mShortcutBitmapSaver.waitForAllSavesLocked();
final ArraySet<String> usedFiles = getUsedBitmapFilesLocked();
@@ -1136,7 +1136,7 @@
// Now prepare to publish manifest shortcuts.
List<ShortcutInfo> newManifestShortcutList = null;
int shareTargetSize = 0;
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
try {
shareTargetSize = mShareTargets.size();
newManifestShortcutList = ShortcutParser.parseShortcuts(mShortcutUser.mService,
@@ -1680,7 +1680,7 @@
void reportShortcutUsed(@NonNull final UsageStatsManagerInternal usageStatsManagerInternal,
@NonNull final String shortcutId) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final long currentTS = SystemClock.elapsedRealtime();
final ShortcutService s = mShortcutUser.mService;
if (currentTS - mLastReportedTime > s.mSaveDelayMillis) {
@@ -1757,7 +1757,7 @@
pw.println(")");
pw.println();
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
mShortcutBitmapSaver.dumpLocked(pw, " ");
}
}
@@ -1827,7 +1827,7 @@
@Override
public void saveToXml(@NonNull TypedXmlSerializer out, boolean forBackup)
throws IOException, XmlPullParserException {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
final int size = mShortcuts.size();
final int shareTargetSize = mShareTargets.size();
@@ -2037,7 +2037,7 @@
final ShortcutPackage ret = new ShortcutPackage(shortcutUser,
shortcutUser.getUserId(), packageName);
- synchronized (ret.mLock) {
+ synchronized (ret.mPackageItemLock) {
ret.mIsAppSearchSchemaUpToDate = ShortcutService.parseIntAttribute(
parser, ATTR_SCHEMA_VERSON, 0) == AppSearchShortcutInfo.SCHEMA_VERSION;
@@ -2283,7 +2283,7 @@
@VisibleForTesting
List<ShareTargetInfo> getAllShareTargetsForTest() {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return new ArrayList<>(mShareTargets);
}
}
@@ -2404,7 +2404,7 @@
@NonNull final Consumer<ShortcutInfo> transform) {
Objects.requireNonNull(id);
Objects.requireNonNull(transform);
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
if (shortcut != null) {
transform.accept(shortcut);
}
@@ -2424,7 +2424,7 @@
private void saveShortcut(@NonNull final Collection<ShortcutInfo> shortcuts) {
Objects.requireNonNull(shortcuts);
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
for (ShortcutInfo si : shortcuts) {
mShortcuts.put(si.getId(), si);
}
@@ -2433,7 +2433,7 @@
@Nullable
List<ShortcutInfo> findAll(@NonNull final Collection<String> ids) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return ids.stream().map(mShortcuts::get)
.filter(Objects::nonNull).collect(Collectors.toList());
}
@@ -2455,7 +2455,7 @@
private void forEachShortcutStopWhen(
@NonNull final Function<ShortcutInfo, Boolean> cb) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
if (cb.apply(si)) {
@@ -2600,7 +2600,7 @@
})));
}
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
@Override
void scheduleSaveToAppSearchLocked() {
final Map<String, ShortcutInfo> copy = new ArrayMap<>(mShortcuts);
@@ -2684,7 +2684,7 @@
.penaltyLog() // TODO: change this to penaltyDeath to fix the call-site
.build());
future = mShortcutUser.getAppSearch(searchContext);
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
if (!mIsAppSearchSchemaUpToDate) {
future = future.thenCompose(this::setupSchema);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 12115af..dfd2e08 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -39,7 +39,7 @@
import java.util.Objects;
/**
- * All methods should be either guarded by {@code #mShortcutUser.mService.mLock} or {@code #mLock}.
+ * All methods should be either guarded by {@code #mPackageItemLock}.
*/
abstract class ShortcutPackageItem {
private static final String TAG = ShortcutService.TAG;
@@ -52,10 +52,10 @@
protected ShortcutUser mShortcutUser;
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
protected final ShortcutBitmapSaver mShortcutBitmapSaver;
- protected final Object mLock = new Object();
+ protected final Object mPackageItemLock = new Object();
protected ShortcutPackageItem(@NonNull ShortcutUser shortcutUser,
int packageUserId, @NonNull String packageName,
@@ -157,7 +157,7 @@
public abstract void saveToXml(@NonNull TypedXmlSerializer out, boolean forBackup)
throws IOException, XmlPullParserException;
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
public void saveToFileLocked(File path, boolean forBackup) {
try (ResilientAtomicFile file = getResilientFile(path)) {
FileOutputStream os = null;
@@ -187,7 +187,7 @@
}
}
- @GuardedBy("mLock")
+ @GuardedBy("mPackageItemLock")
void scheduleSaveToAppSearchLocked() {
}
@@ -219,7 +219,7 @@
if (ShortcutService.DEBUG || ShortcutService.DEBUG_REBOOT) {
Slog.d(TAG, "Saving package item " + getPackageName() + " to " + path);
}
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
path.getParentFile().mkdirs();
// TODO: Since we are persisting shortcuts into AppSearch, we should read from/write to
// AppSearch as opposed to maintaining a separate XML file.
@@ -229,14 +229,14 @@
}
public boolean waitForBitmapSaves() {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return mShortcutBitmapSaver.waitForAllSavesLocked();
}
}
public void saveBitmap(ShortcutInfo shortcut,
int maxDimension, Bitmap.CompressFormat format, int quality) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
mShortcutBitmapSaver.saveBitmapLocked(shortcut, maxDimension, format, quality);
}
}
@@ -246,19 +246,19 @@
*/
@Nullable
public String getBitmapPathMayWait(ShortcutInfo shortcut) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
return mShortcutBitmapSaver.getBitmapPathMayWaitLocked(shortcut);
}
}
public void removeIcon(ShortcutInfo shortcut) {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
mShortcutBitmapSaver.removeIcon(shortcut);
}
}
void removeShortcutPackageItem() {
- synchronized (mLock) {
+ synchronized (mPackageItemLock) {
getResilientFile(getShortcutPackageItemFile()).delete();
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index fe9c3f2..3f5ec06 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -295,7 +295,7 @@
final Context mContext;
- private final Object mLock = new Object();
+ private final Object mServiceLock = new Object();
private final Object mNonPersistentUsersLock = new Object();
private final Object mWtfLock = new Object();
@@ -333,7 +333,7 @@
/**
* User ID -> UserShortcuts
*/
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private final SparseArray<ShortcutUser> mUsers = new SparseArray<>();
/**
@@ -388,13 +388,13 @@
private final ShortcutRequestPinProcessor mShortcutRequestPinProcessor;
private final ShortcutDumpFiles mShortcutDumpFiles;
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
final SparseIntArray mUidState = new SparseIntArray();
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
final SparseLongArray mUidLastForegroundElapsedTime = new SparseLongArray();
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private List<Integer> mDirtyUserIds = new ArrayList<>();
private final AtomicBoolean mBootCompleted = new AtomicBoolean();
@@ -473,7 +473,7 @@
@GuardedBy("mWtfLock")
private Exception mLastWtfStacktrace;
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private final MetricsLogger mMetricsLogger = new MetricsLogger();
private final boolean mIsAppSearchEnabled;
@@ -518,7 +518,7 @@
mUriPermissionOwner = mUriGrantsManagerInternal.newUriPermissionOwner(TAG);
mRoleManager = Objects.requireNonNull(mContext.getSystemService(RoleManager.class));
- mShortcutRequestPinProcessor = new ShortcutRequestPinProcessor(this, mLock);
+ mShortcutRequestPinProcessor = new ShortcutRequestPinProcessor(this, mServiceLock);
mShortcutDumpFiles = new ShortcutDumpFiles(this);
mIsAppSearchEnabled = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, false)
@@ -595,7 +595,7 @@
// Default launcher is removed or changed, revoke all URI permissions.
mUriGrantsManagerInternal.revokeUriPermissionFromOwner(mUriPermissionOwner, null, ~0, 0);
- synchronized (mLock) {
+ synchronized (mServiceLock) {
// Clear the launcher cache for this user. It will be set again next time the default
// launcher is read from RoleManager.
if (isUserLoadedLocked(userId)) {
@@ -622,7 +622,7 @@
Slog.d(TAG, "onUidStateChanged: uid=" + uid + " state=" + procState);
}
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "shortcutHandleOnUidStateChanged");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
mUidState.put(uid, procState);
// We need to keep track of last time an app comes to foreground.
@@ -639,7 +639,7 @@
return processState <= PROCESS_STATE_FOREGROUND_THRESHOLD;
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
boolean isUidForegroundLocked(int uid) {
if (uid == Process.SYSTEM_UID) {
// IUidObserver doesn't report the state of SYSTEM, but it always has bound services,
@@ -655,7 +655,7 @@
return isProcessStateForeground(mActivityManagerInternal.getUidProcessState(uid));
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
long getUidLastForegroundElapsedTimeLocked(int uid) {
return mUidLastForegroundElapsedTime.get(uid);
}
@@ -729,7 +729,7 @@
final long start = getStatStartTime();
injectRunOnNewThread(() -> {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "shortcutHandleUnlockUser");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
logDurationStat(Stats.ASYNC_PRELOAD_USER_DELAY, start);
getUserShortcutsLocked(userId);
}
@@ -743,7 +743,7 @@
Slog.d(TAG, "handleStopUser: user=" + userId);
}
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "shortcutHandleStopUser");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
unloadUserLocked(userId);
synchronized (mUnlockedUsers) {
@@ -753,7 +753,7 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private void unloadUserLocked(int userId) {
if (DEBUG || DEBUG_REBOOT) {
Slog.d(TAG, "unloadUserLocked: user=" + userId);
@@ -784,7 +784,7 @@
* Init the instance. (load the state file, etc)
*/
private void initialize() {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
loadConfigurationLocked();
loadBaseStateLocked();
}
@@ -1003,7 +1003,7 @@
FileOutputStream outs = null;
try {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
outs = file.startWrite();
}
@@ -1029,7 +1029,7 @@
}
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private void loadBaseStateLocked() {
mRawLastResetTime.set(0);
@@ -1104,7 +1104,7 @@
Slog.d(TAG, "Saving to " + file);
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
os = file.startWrite();
saveUserInternalLocked(userId, os, /* forBackup= */ false);
}
@@ -1122,7 +1122,7 @@
getUserShortcutsLocked(userId).logSharingShortcutStats(mMetricsLogger);
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private void saveUserInternalLocked(@UserIdInt int userId, OutputStream os,
boolean forBackup) throws IOException, XmlPullParserException {
@@ -1224,7 +1224,7 @@
if (DEBUG || DEBUG_REBOOT) {
Slog.d(TAG, "Scheduling to save for " + userId);
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!mDirtyUserIds.contains(userId)) {
mDirtyUserIds.add(userId);
}
@@ -1245,7 +1245,7 @@
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "shortcutSaveDirtyInfo");
List<Integer> dirtyUserIds = new ArrayList<>();
- synchronized (mLock) {
+ synchronized (mServiceLock) {
List<Integer> tmp = mDirtyUserIds;
mDirtyUserIds = dirtyUserIds;
dirtyUserIds = tmp;
@@ -1266,14 +1266,14 @@
}
/** Return the last reset time. */
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
long getLastResetTimeLocked() {
updateTimesLocked();
return mRawLastResetTime.get();
}
/** Return the next reset time. */
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
long getNextResetTimeLocked() {
updateTimesLocked();
return mRawLastResetTime.get() + mResetInterval;
@@ -1286,7 +1286,7 @@
/**
* Update the last reset time.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private void updateTimesLocked() {
final long now = injectCurrentTimeMillis();
@@ -1315,7 +1315,7 @@
}
}
- // Requires mLock held, but "Locked" prefix would look weired so we just say "L".
+ // Requires mServiceLock held, but "Locked" prefix would look weird so we just say "L".
protected boolean isUserUnlockedL(@UserIdInt int userId) {
// First, check the local copy.
synchronized (mUnlockedUsers) {
@@ -1331,14 +1331,14 @@
return mUserManagerInternal.isUserUnlockingOrUnlocked(userId);
}
- // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L".
+ // Requires mServiceLock held, but "Locked" prefix would look weird so we just say "L".
void throwIfUserLockedL(@UserIdInt int userId) {
if (!isUserUnlockedL(userId)) {
throw new IllegalStateException("User " + userId + " is locked or not running");
}
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
@NonNull
private boolean isUserLoadedLocked(@UserIdInt int userId) {
return mUsers.get(userId) != null;
@@ -1347,7 +1347,7 @@
private int mLastLockedUser = -1;
/** Return the per-user state. */
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
@NonNull
ShortcutUser getUserShortcutsLocked(@UserIdInt int userId) {
if (!isUserUnlockedL(userId)) {
@@ -1386,7 +1386,7 @@
return ret;
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
void forEachLoadedUserLocked(@NonNull Consumer<ShortcutUser> c) {
for (int i = mUsers.size() - 1; i >= 0; i--) {
c.accept(mUsers.valueAt(i));
@@ -1397,7 +1397,7 @@
* Return the per-user per-package state. If the caller is a publisher, use
* {@link #getPackageShortcutsForPublisherLocked} instead.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
@NonNull
ShortcutPackage getPackageShortcutsLocked(
@NonNull String packageName, @UserIdInt int userId) {
@@ -1405,7 +1405,7 @@
}
/** Return the per-user per-package state. Use this when the caller is a publisher. */
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
@NonNull
ShortcutPackage getPackageShortcutsForPublisherLocked(
@NonNull String packageName, @UserIdInt int userId) {
@@ -1414,7 +1414,7 @@
return ret;
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
@NonNull
ShortcutLauncher getLauncherShortcutsLocked(
@NonNull String packageName, @UserIdInt int ownerUserId,
@@ -1443,7 +1443,7 @@
* {@link ShortcutBitmapSaver#waitForAllSavesLocked()} to make sure there's no pending bitmap
* saves are going on.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) {
if (DEBUG) {
Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId);
@@ -1780,7 +1780,7 @@
void injectPostToHandlerDebounced(@NonNull final Object token, @NonNull final Runnable r) {
Objects.requireNonNull(token);
Objects.requireNonNull(r);
- synchronized (mLock) {
+ synchronized (mServiceLock) {
mHandler.removeCallbacksAndMessages(token);
mHandler.postDelayed(r, token, CALLBACK_DELAY);
}
@@ -2015,7 +2015,7 @@
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
@@ -2084,7 +2084,7 @@
final List<ShortcutInfo> changedShortcuts = new ArrayList<>(1);
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
@@ -2184,7 +2184,7 @@
List<ShortcutInfo> changedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
@@ -2241,7 +2241,7 @@
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
@@ -2306,7 +2306,7 @@
verifyCaller(packageName, userId);
verifyShortcutInfoPackage(packageName, shortcut);
final Intent intent;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
// Send request to the launcher, if supported.
intent = mShortcutRequestPinProcessor.createShortcutResultIntent(shortcut, userId);
@@ -2337,7 +2337,7 @@
}
final boolean ret;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
Preconditions.checkState(isUidForegroundLocked(callingUid),
@@ -2378,7 +2378,7 @@
List<ShortcutInfo> changedShortcuts = null;
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
@@ -2419,7 +2419,7 @@
Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
List<ShortcutInfo> changedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
@@ -2449,7 +2449,7 @@
List<ShortcutInfo> changedShortcuts = null;
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
@@ -2487,7 +2487,7 @@
List<ShortcutInfo> changedShortcuts = new ArrayList<>();
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
// Dynamic shortcuts that are either cached or pinned will not get deleted.
@@ -2511,7 +2511,7 @@
List<ShortcutInfo> changedShortcuts = null;
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
@@ -2545,7 +2545,7 @@
public ParceledListSlice<ShortcutInfo> getShortcuts(String packageName,
@ShortcutManager.ShortcutMatchFlags int matchFlags, @UserIdInt int userId) {
verifyCaller(packageName, userId);
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
final boolean matchDynamic = (matchFlags & ShortcutManager.FLAG_MATCH_DYNAMIC) != 0;
final boolean matchPinned = (matchFlags & ShortcutManager.FLAG_MATCH_PINNED) != 0;
@@ -2575,7 +2575,7 @@
"getShareTargets");
final ComponentName chooser = injectChooserActivity();
final String pkg = chooser != null ? chooser.getPackageName() : mContext.getPackageName();
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
final List<ShortcutManager.ShareShortcutInfo> shortcutInfoList = new ArrayList<>();
final ShortcutUser user = getUserShortcutsLocked(userId);
@@ -2592,7 +2592,7 @@
enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS,
"hasShareTargets");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
return getPackageShortcutsLocked(packageToCheck, userId).hasShareTargets();
@@ -2606,7 +2606,7 @@
enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS,
"isSharingShortcut");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(callingUserId);
@@ -2623,7 +2623,7 @@
return false;
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName,
@UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> filter) {
@@ -2649,7 +2649,7 @@
final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
injectBinderCallingPid(), injectBinderCallingUid());
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
@@ -2661,7 +2661,7 @@
public long getRateLimitResetTime(String packageName, @UserIdInt int userId) {
verifyCaller(packageName, userId);
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
return getNextResetTimeLocked();
@@ -2672,7 +2672,7 @@
public int getIconMaxDimensions(String packageName, int userId) {
verifyCaller(packageName, userId);
- synchronized (mLock) {
+ synchronized (mServiceLock) {
return mMaxIconDimension;
}
}
@@ -2686,7 +2686,7 @@
shortcutId, packageName, userId));
}
final ShortcutPackage ps;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
ps = getPackageShortcutsForPublisherLocked(packageName, userId);
if (ps.findShortcutById(shortcutId) == null) {
@@ -2723,7 +2723,7 @@
}
void resetThrottlingInner(@UserIdInt int userId) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!isUserUnlockedL(userId)) {
Log.w(TAG, "User " + userId + " is locked or not running");
return;
@@ -2747,7 +2747,7 @@
Slog.d(TAG, "onApplicationActive: package=" + packageName + " userid=" + userId);
}
enforceResetThrottlingPermission();
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!isUserUnlockedL(userId)) {
// This is called by system UI, so no need to throw. Just ignore.
return;
@@ -2804,7 +2804,7 @@
// even when hasShortcutPermission() is overridden.
@VisibleForTesting
boolean hasShortcutHostPermissionInner(@NonNull String packageName, int userId) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
final String defaultLauncher = getDefaultLauncher(userId);
@@ -2830,7 +2830,7 @@
final long token = injectClearCallingIdentity();
boolean isSupported;
try {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
isSupported = !mUserManagerInternal.getUserProperties(userId)
.areItemsRestrictedOnHomeScreen();
}
@@ -2846,7 +2846,7 @@
final long start = getStatStartTime();
final long token = injectClearCallingIdentity();
try {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
final ShortcutUser user = getUserShortcutsLocked(userId);
@@ -2890,7 +2890,7 @@
private void cleanUpPackageForAllLoadedUsers(String packageName, @UserIdInt int packageUserId,
boolean appStillExists) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
forEachLoadedUserLocked(user ->
cleanUpPackageLocked(packageName, user.getUserId(), packageUserId,
appStillExists));
@@ -2904,7 +2904,7 @@
*
* This is called when an app is uninstalled, or an app gets "clear data"ed.
*/
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
@VisibleForTesting
void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId,
boolean appStillExists) {
@@ -2979,7 +2979,7 @@
shortcutIds = null; // LauncherAppsService already threw for it though.
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3005,7 +3005,7 @@
return setReturnedByServer(ret);
}
- @GuardedBy("ShortcutService.this.mLock")
+ @GuardedBy("ShortcutService.this.mServiceLock")
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
@Nullable String packageName, @Nullable List<String> shortcutIds,
@Nullable List<LocusId> locusIds, long changedSince,
@@ -3095,7 +3095,7 @@
return;
}
final ShortcutPackage p;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
p = getUserShortcutsLocked(userId).getPackageShortcutsIfExists(packageName);
}
if (p == null) {
@@ -3129,7 +3129,7 @@
Preconditions.checkStringNotEmpty(packageName, "packageName");
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3143,7 +3143,7 @@
}
}
- @GuardedBy("ShortcutService.this.mLock")
+ @GuardedBy("ShortcutService.this.mServiceLock")
private ShortcutInfo getShortcutInfoLocked(
int launcherUserId, @NonNull String callingPackage,
@NonNull String packageName, @NonNull String shortcutId, int userId,
@@ -3176,7 +3176,7 @@
throwIfUserLockedL(launcherUserId);
final ShortcutPackage p;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
p = getUserShortcutsLocked(userId).getPackageShortcutsIfExists(packageName);
}
if (p == null) {
@@ -3198,7 +3198,7 @@
List<ShortcutInfo> changedShortcuts = null;
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage sp;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3284,7 +3284,7 @@
List<ShortcutInfo> changedShortcuts = null;
List<ShortcutInfo> removedShortcuts = null;
final ShortcutPackage sp;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3346,7 +3346,7 @@
Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty");
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3380,7 +3380,7 @@
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
// Check in memory shortcut first
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3430,7 +3430,7 @@
Objects.requireNonNull(packageName, "packageName");
Objects.requireNonNull(shortcutId, "shortcutId");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3458,7 +3458,7 @@
Objects.requireNonNull(packageName, "packageName");
Objects.requireNonNull(shortcutId, "shortcutId");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3484,7 +3484,7 @@
Objects.requireNonNull(packageName, "packageName");
Objects.requireNonNull(shortcutId, "shortcutId");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3515,7 +3515,7 @@
// Checks shortcuts in memory first
final ShortcutPackage p;
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3568,7 +3568,7 @@
Objects.requireNonNull(packageName, "packageName");
Objects.requireNonNull(shortcutId, "shortcutId");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3599,7 +3599,7 @@
Objects.requireNonNull(shortcutId, "shortcutId");
// Checks shortcuts in memory first
- synchronized (mLock) {
+ synchronized (mServiceLock) {
throwIfUserLockedL(userId);
throwIfUserLockedL(launcherUserId);
@@ -3702,7 +3702,7 @@
if (!callingPackage.equals(defaultLauncher)) {
return false;
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!isUidForegroundLocked(callingUid)) {
return false;
}
@@ -3733,7 +3733,7 @@
}
scheduleSaveBaseState();
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final long token = injectClearCallingIdentity();
try {
forEachLoadedUserLocked(user -> user.detectLocaleChange());
@@ -3762,7 +3762,7 @@
// but we still check it in unit tests.
final long token = injectClearCallingIdentity();
try {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!isUserUnlockedL(userId)) {
if (DEBUG) {
Slog.d(TAG, "Ignoring package broadcast " + action
@@ -3821,7 +3821,7 @@
// Since it cleans up the shortcut directory and rewrite the ShortcutPackageItems
// in odrder during saveToXml(), it could lead to shortcuts missing when shutdown.
// We need it so that it can finish up saving before shutdown.
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (mHandler.hasCallbacks(mSaveDirtyInfoRunner)) {
mHandler.removeCallbacks(mSaveDirtyInfoRunner);
forEachLoadedUserLocked(ShortcutUser::cancelAllInFlightTasks);
@@ -3852,7 +3852,7 @@
try {
final ArrayList<UserPackage> gonePackages = new ArrayList<>();
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutUser user = getUserShortcutsLocked(ownerUserId);
// Find packages that have been uninstalled.
@@ -3885,7 +3885,7 @@
verifyStates();
}
- @GuardedBy("mLock")
+ @GuardedBy("mServiceLock")
private void rescanUpdatedPackagesLocked(@UserIdInt int userId, long lastScanTime) {
if (DEBUG_REBOOT) {
Slog.d(TAG, "rescan updated package user=" + userId + " last scanned=" + lastScanTime);
@@ -3916,7 +3916,7 @@
if (DEBUG || DEBUG_REBOOT) {
Slog.d(TAG, String.format("handlePackageAdded: %s user=%d", packageName, userId));
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutUser user = getUserShortcutsLocked(userId);
user.attemptToRestoreIfNeededAndSave(this, packageName, userId);
user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true);
@@ -3929,7 +3929,7 @@
Slog.d(TAG, String.format("handlePackageUpdateFinished: %s user=%d",
packageName, userId));
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutUser user = getUserShortcutsLocked(userId);
user.attemptToRestoreIfNeededAndSave(this, packageName, userId);
@@ -3972,7 +3972,7 @@
}
// Activities may be disabled or enabled. Just rescan the package.
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutUser user = getUserShortcutsLocked(packageUserId);
user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true);
@@ -4474,7 +4474,7 @@
if (DEBUG) {
Slog.d(TAG, "Backing up user " + userId);
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!isUserUnlockedL(userId)) {
wtf("Can't backup: user " + userId + " is locked or not running");
return null;
@@ -4524,7 +4524,7 @@
if (DEBUG || DEBUG_REBOOT) {
Slog.d(TAG, "Restoring user " + userId);
}
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!isUserUnlockedL(userId)) {
wtf("Can't restore: user " + userId + " is locked or not running");
return;
@@ -4762,7 +4762,7 @@
}
private void dumpInner(PrintWriter pw, DumpFilter filter) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (filter.shouldDumpDetails()) {
final long now = injectCurrentTimeMillis();
pw.print("Now: [");
@@ -4841,7 +4841,7 @@
}
private void dumpUid(PrintWriter pw) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
pw.println("** SHORTCUT MANAGER UID STATES (dumpsys shortcut -n -u)");
for (int i = 0; i < mUidState.size(); i++) {
@@ -4876,7 +4876,7 @@
* behavior but shortcut service doesn't for now.
*/
private void dumpCheckin(PrintWriter pw, boolean clear) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
try {
final JSONArray users = new JSONArray();
@@ -4898,7 +4898,7 @@
}
private void dumpDumpFiles(PrintWriter pw) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
pw.println("** SHORTCUT MANAGER FILES (dumpsys shortcut -n -f)");
mShortcutDumpFiles.dumpAll(pw);
}
@@ -5051,7 +5051,7 @@
}
private void handleResetThrottling() throws CommandException {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
parseOptionsLocked(/* takeUser =*/ true);
Slog.i(TAG, "cmd: handleResetThrottling: user=" + mUserId);
@@ -5071,7 +5071,7 @@
Slog.i(TAG, "cmd: handleOverrideConfig: " + config);
- synchronized (mLock) {
+ synchronized (mServiceLock) {
if (!updateConfigurationLocked(config)) {
throw new CommandException("override-config failed. See logcat for details.");
}
@@ -5081,7 +5081,7 @@
private void handleResetConfig() {
Slog.i(TAG, "cmd: handleResetConfig");
- synchronized (mLock) {
+ synchronized (mServiceLock) {
loadConfigurationLocked();
}
}
@@ -5090,7 +5090,7 @@
// should query this information directly from RoleManager instead. Keeping the old behavior
// by returning the result from package manager.
private void handleGetDefaultLauncher() throws CommandException {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
parseOptionsLocked(/* takeUser =*/ true);
final String defaultLauncher = getDefaultLauncher(mUserId);
@@ -5114,7 +5114,7 @@
}
private void handleUnloadUser() throws CommandException {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
parseOptionsLocked(/* takeUser =*/ true);
Slog.i(TAG, "cmd: handleUnloadUser: user=" + mUserId);
@@ -5124,7 +5124,7 @@
}
private void handleClearShortcuts() throws CommandException {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
parseOptionsLocked(/* takeUser =*/ true);
final String packageName = getNextArgRequired();
@@ -5136,7 +5136,7 @@
}
private void handleGetShortcuts() throws CommandException {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
parseOptionsLocked(/* takeUser =*/ true);
final String packageName = getNextArgRequired();
@@ -5162,7 +5162,7 @@
}
private void handleHasShortcutAccess() throws CommandException {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
parseOptionsLocked(/* takeUser =*/ true);
final String packageName = getNextArgRequired();
@@ -5318,7 +5318,7 @@
@VisibleForTesting
ShortcutPackage getPackageShortcutForTest(String packageName, int userId) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutUser user = mUsers.get(userId);
if (user == null) return null;
@@ -5328,7 +5328,7 @@
@VisibleForTesting
ShortcutInfo getPackageShortcutForTest(String packageName, String shortcutId, int userId) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutPackage pkg = getPackageShortcutForTest(packageName, userId);
if (pkg == null) return null;
@@ -5339,7 +5339,7 @@
@VisibleForTesting
void updatePackageShortcutForTest(String packageName, String shortcutId, int userId,
Consumer<ShortcutInfo> cb) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutPackage pkg = getPackageShortcutForTest(packageName, userId);
if (pkg == null) return;
cb.accept(pkg.findShortcutById(shortcutId));
@@ -5348,7 +5348,7 @@
@VisibleForTesting
ShortcutLauncher getLauncherShortcutForTest(String packageName, int userId) {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
final ShortcutUser user = mUsers.get(userId);
if (user == null) return null;
@@ -5385,14 +5385,14 @@
}
private void verifyStatesInner() {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
}
}
@VisibleForTesting
void waitForBitmapSavesForTest() {
- synchronized (mLock) {
+ synchronized (mServiceLock) {
forEachLoadedUserLocked(u ->
u.forAllPackageItems(ShortcutPackageItem::waitForBitmapSaves));
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index bb6708a..3c702b4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2314,6 +2314,18 @@
return userTypeDetails.getLabel(userIndex);
}
+ @Override
+ public @NonNull int getProfileAccessibilityLabelResId(@UserIdInt int userId) {
+ checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(userId,
+ "getProfileAccessibilityLabelResId");
+ final UserInfo userInfo = getUserInfoNoChecks(userId);
+ final UserTypeDetails userTypeDetails = getUserTypeDetails(userInfo);
+ if (userInfo == null || userTypeDetails == null) {
+ return Resources.ID_NULL;
+ }
+ return userTypeDetails.getAccessibilityString();
+ }
+
public boolean isProfile(@UserIdInt int userId) {
checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isProfile");
return isProfileUnchecked(userId);
diff --git a/services/core/java/com/android/server/pm/UserTypeDetails.java b/services/core/java/com/android/server/pm/UserTypeDetails.java
index 56c400a0..c6f36bf 100644
--- a/services/core/java/com/android/server/pm/UserTypeDetails.java
+++ b/services/core/java/com/android/server/pm/UserTypeDetails.java
@@ -127,7 +127,7 @@
private @DrawableRes final int mStatusBarIcon;
/**
- * Resource ID ({@link StringRes}) of the of the labels to describe badged apps; should be the
+ * Resource ID ({@link StringRes}) of the labels to describe badged apps; should be the
* same format as com.android.internal.R.color.profile_badge_1. These are used for accessibility
* services.
*
@@ -161,6 +161,12 @@
private final @Nullable int[] mDarkThemeBadgeColors;
/**
+ * Resource ID ({@link StringRes}) of the accessibility string that describes the user type.
+ * This is used by accessibility services like Talkback.
+ */
+ private final @Nullable int mAccessibilityString;
+
+ /**
* The default {@link UserProperties} for the user type.
* <p> The uninitialized value of each property is implied by {@link UserProperties.Builder}.
*/
@@ -177,6 +183,7 @@
@Nullable Bundle defaultSystemSettings,
@Nullable Bundle defaultSecureSettings,
@Nullable List<DefaultCrossProfileIntentFilter> defaultCrossProfileIntentFilters,
+ @Nullable int accessibilityString,
@NonNull UserProperties defaultUserProperties) {
this.mName = name;
this.mEnabled = enabled;
@@ -196,6 +203,7 @@
this.mBadgeLabels = badgeLabels;
this.mBadgeColors = badgeColors;
this.mDarkThemeBadgeColors = darkThemeBadgeColors;
+ this.mAccessibilityString = accessibilityString;
this.mDefaultUserProperties = defaultUserProperties;
}
@@ -323,6 +331,10 @@
return mDefaultUserProperties;
}
+ public @StringRes int getAccessibilityString() {
+ return mAccessibilityString;
+ }
+
public boolean isProfile() {
return (mBaseType & UserInfo.FLAG_PROFILE) != 0;
}
@@ -430,6 +442,7 @@
private @DrawableRes int mBadgePlain = Resources.ID_NULL;
private @DrawableRes int mBadgeNoBackground = Resources.ID_NULL;
private @DrawableRes int mStatusBarIcon = Resources.ID_NULL;
+ private @StringRes int mAccessibilityString = Resources.ID_NULL;
// Default UserProperties cannot be null but for efficiency we don't initialize it now.
// If it isn't set explicitly, {@link UserProperties.Builder#build()} will be used.
private @Nullable UserProperties mDefaultUserProperties = null;
@@ -529,6 +542,14 @@
}
/**
+ * Sets the accessibility label associated with the user
+ */
+ public Builder setAccessibilityString(@StringRes int accessibilityString) {
+ mAccessibilityString = accessibilityString;
+ return this;
+ }
+
+ /**
* Sets (replacing if necessary) the default UserProperties object for this user type.
* Takes a builder, rather than a built object, to efficiently ensure that a fresh copy of
* properties is stored (since it later might be modified by UserProperties#updateFromXml).
@@ -589,6 +610,7 @@
mDefaultSystemSettings,
mDefaultSecureSettings,
mDefaultCrossProfileIntentFilters,
+ mAccessibilityString,
getDefaultUserProperties());
}
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 1e7fdfe..2715025 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -140,6 +140,8 @@
com.android.internal.R.color.system_neutral2_800)
.setDarkThemeBadgeColors(
com.android.internal.R.color.system_neutral2_900)
+ .setAccessibilityString(com.android.internal
+ .R.string.accessibility_label_clone_profile)
.setDefaultRestrictions(null)
.setDefaultCrossProfileIntentFilters(getDefaultCloneCrossProfileIntentFilter())
.setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings())
@@ -195,6 +197,8 @@
com.android.internal.R.color.profile_badge_1_dark,
com.android.internal.R.color.profile_badge_2_dark,
com.android.internal.R.color.profile_badge_3_dark)
+ .setAccessibilityString(com.android.internal
+ .R.string.accessibility_label_managed_profile)
.setDefaultRestrictions(getDefaultProfileRestrictions())
.setDefaultSecureSettings(getDefaultManagedProfileSecureSettings())
.setDefaultCrossProfileIntentFilters(getDefaultManagedCrossProfileIntentFilter())
@@ -306,6 +310,8 @@
R.color.black)
.setDarkThemeBadgeColors(
R.color.white)
+ .setAccessibilityString(com.android.internal
+ .R.string.accessibility_label_private_profile)
.setDefaultRestrictions(getDefaultPrivateProfileRestrictions())
.setDefaultCrossProfileIntentFilters(getDefaultPrivateCrossProfileIntentFilter())
.setDefaultUserProperties(new UserProperties.Builder()
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 98499417..deaa8d8 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -494,6 +494,7 @@
PhoneCarrierPrivilegesCallback(int phoneId) {
mPhoneId = phoneId;
}
+
@Override
public void onCarrierPrivilegesChanged(
@NonNull Set<String> privilegedPackageNames,
@@ -563,7 +564,11 @@
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
t.traceBegin("Permission_grant_default_permissions-" + userId);
- grantOrUpgradeDefaultRuntimePermissionsIfNeeded(userId);
+ if (mPackageManagerInternal.isPermissionUpgradeNeeded(userId)) {
+ grantOrUpgradeDefaultRuntimePermissions(userId);
+ updateUserSensitive(userId);
+ mPackageManagerInternal.updateRuntimePermissionsFingerprint(userId);
+ }
t.traceEnd();
final OnInitializedCallback callback;
@@ -595,59 +600,56 @@
}
}
- private void grantOrUpgradeDefaultRuntimePermissionsIfNeeded(@UserIdInt int userId) {
+ private void grantOrUpgradeDefaultRuntimePermissions(@UserIdInt int userId) {
if (PermissionManager.USE_ACCESS_CHECKING_SERVICE) {
return;
}
- if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPermsIfNeeded(" + userId + ")");
+ if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPerms(" + userId + ")");
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
- final PackageManagerInternal packageManagerInternal =
- LocalServices.getService(PackageManagerInternal.class);
- final PermissionManagerServiceInternal permissionManagerInternal =
- LocalServices.getService(PermissionManagerServiceInternal.class);
- if (packageManagerInternal.isPermissionUpgradeNeeded(userId)) {
- if (DEBUG) Slog.i(LOG_TAG, "defaultPermsWereGrantedSinceBoot(" + userId + ")");
+ // Now call into the permission controller to apply policy around permissions
+ final AndroidFuture<Boolean> future = new AndroidFuture<>();
- // Now call into the permission controller to apply policy around permissions
- final AndroidFuture<Boolean> future = new AndroidFuture<>();
-
- // We need to create a local manager that does not schedule work on the main
- // there as we are on the main thread and want to block until the work is
- // completed or we time out.
- final PermissionControllerManager permissionControllerManager =
- new PermissionControllerManager(
- getUserContext(getContext(), UserHandle.of(userId)),
- PermissionThread.getHandler());
- permissionControllerManager.grantOrUpgradeDefaultRuntimePermissions(
- PermissionThread.getExecutor(), successful -> {
- if (successful) {
- future.complete(null);
- } else {
- // We are in an undefined state now, let us crash and have
- // rescue party suggest a wipe to recover to a good one.
- final String message = "Error granting/upgrading runtime permissions"
- + " for user " + userId;
- Slog.wtf(LOG_TAG, message);
- future.completeExceptionally(new IllegalStateException(message));
- }
- });
- try {
- t.traceBegin("Permission_callback_waiting-" + userId);
- future.get();
- } catch (InterruptedException | ExecutionException e) {
- throw new IllegalStateException(e);
- } finally {
- t.traceEnd();
- }
-
- permissionControllerManager.updateUserSensitive();
-
- packageManagerInternal.updateRuntimePermissionsFingerprint(userId);
+ // We need to create a local manager that does not schedule work on the main
+ // there as we are on the main thread and want to block until the work is
+ // completed or we time out.
+ final PermissionControllerManager permissionControllerManager =
+ new PermissionControllerManager(
+ getUserContext(getContext(), UserHandle.of(userId)),
+ PermissionThread.getHandler());
+ permissionControllerManager.grantOrUpgradeDefaultRuntimePermissions(
+ PermissionThread.getExecutor(), successful -> {
+ if (successful) {
+ future.complete(null);
+ } else {
+ // We are in an undefined state now, let us crash and have
+ // rescue party suggest a wipe to recover to a good one.
+ final String message = "Error granting/upgrading runtime permissions"
+ + " for user " + userId;
+ Slog.wtf(LOG_TAG, message);
+ future.completeExceptionally(new IllegalStateException(message));
+ }
+ });
+ try {
+ t.traceBegin("Permission_callback_waiting-" + userId);
+ future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new IllegalStateException(e);
+ } finally {
+ t.traceEnd();
}
}
+ private void updateUserSensitive(@UserIdInt int userId) {
+ if (DEBUG) Slog.i(LOG_TAG, "updateUserSensitive(" + userId + ")");
+ final PermissionControllerManager permissionControllerManager =
+ new PermissionControllerManager(
+ getUserContext(getContext(), UserHandle.of(userId)),
+ PermissionThread.getHandler());
+ permissionControllerManager.updateUserSensitive();
+ }
+
private static @Nullable Context getUserContext(@NonNull Context context,
@Nullable UserHandle user) {
if (context.getUser().equals(user)) {
@@ -695,12 +697,10 @@
if (DEBUG) Slog.i(LOG_TAG, "synchronizePermissionsAndAppOpsForUser(" + userId + ")");
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
- final PackageManagerInternal packageManagerInternal = LocalServices.getService(
- PackageManagerInternal.class);
final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(
getUserContext(getContext(), UserHandle.of(userId)));
t.traceBegin("Permission_synchronize_addPackages-" + userId);
- packageManagerInternal.forEachPackage(
+ mPackageManagerInternal.forEachPackage(
(pkg) -> synchronizer.addPackage(pkg.getPackageName()));
t.traceEnd();
t.traceBegin("Permission_syncPackages-" + userId);
@@ -1052,13 +1052,11 @@
* @param pkgName The package to add for later processing.
*/
void addPackage(@NonNull String pkgName) {
- PackageManagerInternal pmInternal =
- LocalServices.getService(PackageManagerInternal.class);
final PackageInfo pkgInfo;
final AndroidPackage pkg;
try {
pkgInfo = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
- pkg = pmInternal.getPackage(pkgName);
+ pkg = mPackageManagerInternal.getPackage(pkgName);
} catch (NameNotFoundException e) {
return;
}
diff --git a/services/core/java/com/android/server/policy/SideFpsEventHandler.java b/services/core/java/com/android/server/policy/SideFpsEventHandler.java
index 2d76c50..4ad4353 100644
--- a/services/core/java/com/android/server/policy/SideFpsEventHandler.java
+++ b/services/core/java/com/android/server/policy/SideFpsEventHandler.java
@@ -38,6 +38,7 @@
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -66,6 +67,7 @@
private final int mDismissDialogTimeout;
@Nullable
private SideFpsToast mDialog;
+ private final AccessibilityManager mAccessibilityManager;
private final Runnable mTurnOffDialog =
() -> {
dismissDialog("mTurnOffDialog");
@@ -96,6 +98,7 @@
DialogProvider provider) {
mContext = context;
mHandler = handler;
+ mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
mPowerManager = powerManager;
mBiometricState = STATE_IDLE;
mSideFpsEventHandlerReady = new AtomicBoolean(false);
@@ -157,7 +160,9 @@
mHandler.removeCallbacks(mTurnOffDialog);
}
showDialog(eventTime, "Enroll Power Press");
- mHandler.postDelayed(mTurnOffDialog, mDismissDialogTimeout);
+ if (!mAccessibilityManager.isEnabled()) {
+ mHandler.postDelayed(mTurnOffDialog, mDismissDialogTimeout);
+ }
});
return true;
case STATE_BP_AUTH:
@@ -231,6 +236,10 @@
public void onBiometricAction(
@BiometricStateListener.Action int action) {
Log.d(TAG, "onBiometricAction " + action);
+ if (mAccessibilityManager != null
+ && mAccessibilityManager.isEnabled()) {
+ dismissDialog("mTurnOffDialog");
+ }
}
});
mSideFpsEventHandlerReady.set(true);
@@ -256,6 +265,9 @@
mLastPowerPressTime = time;
mDialog.show();
mDialog.setOnClickListener(this);
+ if (mAccessibilityManager.isEnabled()) {
+ mDialog.addAccessibilityDelegate();
+ }
}
interface DialogProvider {
diff --git a/services/core/java/com/android/server/policy/SideFpsToast.java b/services/core/java/com/android/server/policy/SideFpsToast.java
index db07467..c27753c 100644
--- a/services/core/java/com/android/server/policy/SideFpsToast.java
+++ b/services/core/java/com/android/server/policy/SideFpsToast.java
@@ -16,6 +16,7 @@
package com.android.server.policy;
+import android.annotation.NonNull;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
@@ -23,6 +24,7 @@
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import com.android.internal.R;
@@ -34,7 +36,6 @@
* This dialog is used by {@link SideFpsEventHandler}
*/
public class SideFpsToast extends Dialog {
-
SideFpsToast(Context context) {
super(context);
}
@@ -66,4 +67,27 @@
turnOffScreen.setOnClickListener(listener);
}
}
+
+ /**
+ * When accessibility mode is on, add AccessibilityDelegate to dismiss dialog when focus is
+ * moved away from the dialog.
+ */
+ public void addAccessibilityDelegate() {
+ final Button turnOffScreen = findViewById(R.id.turn_off_screen);
+ if (turnOffScreen != null) {
+ turnOffScreen.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityEvent(@NonNull View host,
+ @NonNull AccessibilityEvent event) {
+ if (event.getEventType()
+ == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
+ && isShowing()) {
+ dismiss();
+ }
+ super.onInitializeAccessibilityEvent(host, event);
+ }
+ });
+
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index bbb59ce..76cedd8 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -444,6 +444,9 @@
// Refer to autosuspend.h.
private boolean mHalAutoSuspendModeEnabled;
+ // True if the device uses auto-suspend mode.
+ private final boolean mUseAutoSuspend;
+
// True if interactive mode is enabled.
// Refer to power.h.
private boolean mHalInteractiveModeEnabled;
@@ -1203,6 +1206,9 @@
mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();
+ mUseAutoSuspend = mContext.getResources().getBoolean(com.android.internal.R.bool
+ .config_useAutoSuspend);
+
// Save brightness values:
// Get float values from config.
// Store float if valid
@@ -3918,6 +3924,9 @@
@GuardedBy("mLock")
private void setHalAutoSuspendModeLocked(boolean enable) {
+ if (!mUseAutoSuspend) {
+ return;
+ }
if (enable != mHalAutoSuspendModeEnabled) {
if (DEBUG) {
Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
@@ -4661,6 +4670,7 @@
pw.println(" mEnhancedDischargePredictionIsPersonalized="
+ mEnhancedDischargePredictionIsPersonalized);
}
+ pw.println(" mUseAutoSuspend=" + mUseAutoSuspend);
pw.println(" mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
pw.println(" mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 6e17fd3..4ddd546 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -91,7 +91,7 @@
@GuardedBy("mLock")
private final ArrayMap<Integer, ArrayMap<IBinder, ArraySet<AppHintSession>>> mActiveSessions;
- /** Lock to protect mActiveSessions. */
+ /** Lock to protect mActiveSessions and the UidObserver. */
private final Object mLock = new Object();
@GuardedBy("mNonIsolatedTidsLock")
@@ -318,11 +318,10 @@
@VisibleForTesting
final class MyUidObserver extends UidObserver {
- private final Object mCacheLock = new Object();
- @GuardedBy("mCacheLock")
+ @GuardedBy("mLock")
private final SparseIntArray mProcStatesCache = new SparseIntArray();
public boolean isUidForeground(int uid) {
- synchronized (mCacheLock) {
+ synchronized (mLock) {
return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
<= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
}
@@ -331,10 +330,8 @@
@Override
public void onUidGone(int uid, boolean disabled) {
FgThread.getHandler().post(() -> {
- synchronized (mCacheLock) {
- mProcStatesCache.delete(uid);
- }
synchronized (mLock) {
+ mProcStatesCache.delete(uid);
ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(uid);
if (tokenMap == null) {
return;
@@ -357,7 +354,7 @@
@Override
public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
FgThread.getHandler().post(() -> {
- synchronized (mCacheLock) {
+ synchronized (mLock) {
if (powerhintThreadCleanup()) {
final boolean before = isUidForeground(uid);
mProcStatesCache.put(uid, procState);
@@ -370,9 +367,7 @@
} else {
mProcStatesCache.put(uid, procState);
}
- }
- boolean shouldAllowUpdate = isUidForeground(uid);
- synchronized (mLock) {
+ boolean shouldAllowUpdate = isUidForeground(uid);
ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(uid);
if (tokenMap == null) {
return;
@@ -691,10 +686,10 @@
}
}
- AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token,
- halSessionPtr, durationNanos);
logPerformanceHintSessionAtom(callingUid, halSessionPtr, durationNanos, tids);
synchronized (mLock) {
+ AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token,
+ halSessionPtr, durationNanos);
ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap =
mActiveSessions.get(callingUid);
if (tokenMap == null) {
diff --git a/services/core/java/com/android/server/utils/AnrTimer.java b/services/core/java/com/android/server/utils/AnrTimer.java
index e944eca..12db21d 100644
--- a/services/core/java/com/android/server/utils/AnrTimer.java
+++ b/services/core/java/com/android/server/utils/AnrTimer.java
@@ -40,6 +40,7 @@
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.Objects;
/**
@@ -47,7 +48,7 @@
* mode, the timer just sends a delayed message. In modern mode, the timer is implemented in
* native code; on expiration, the message is sent without delay.
*
- * <p>There are four external operations on a timer:
+ * <p>There are five external operations on a timer:
* <ul>
*
* <li>{@link #start} starts a timer. The timer is started with an object that the message
@@ -74,9 +75,13 @@
* exit. (So, instances in system server generally need not be explicitly closed since they are
* created during process start and will last until process exit.)
*
+ * <p>AnrTimer parameterized by the type <code>V</code>. The public methods on AnrTimer require
+ * an instance of <code>V</code>; the instance of <code>V</code> is a key that identifies a
+ * specific timer.
+ *
* @hide
*/
-public class AnrTimer<V> implements AutoCloseable {
+public abstract class AnrTimer<V> implements AutoCloseable {
/**
* The log tag.
@@ -101,6 +106,20 @@
private static final long TRACE_TAG = Trace.TRACE_TAG_ACTIVITY_MANAGER;
/**
+ * Fetch the Linux pid from the object. The returned value may be zero to indicate that there
+ * is no valid pid available.
+ * @return a valid pid or zero.
+ */
+ public abstract int getPid(V obj);
+
+ /**
+ * Fetch the Linux uid from the object. The returned value may be zero to indicate that there
+ * is no valid uid available.
+ * @return a valid uid or zero.
+ */
+ public abstract int getUid(V obj);
+
+ /**
* Return true if the feature is enabled. By default, the value is take from the Flags class
* but it can be changed for local testing.
*/
@@ -193,10 +212,6 @@
@GuardedBy("mLock")
private int mTotalStarted = 0;
- /** The total number of timers that were restarted without an explicit cancel. */
- @GuardedBy("mLock")
- private int mTotalRestarted = 0;
-
/** The total number of errors detected. */
@GuardedBy("mLock")
private int mTotalErrors = 0;
@@ -350,7 +365,7 @@
abstract boolean enabled();
- abstract void dump(PrintWriter pw, boolean verbose);
+ abstract void dump(IndentingPrintWriter pw, boolean verbose);
abstract void close();
}
@@ -392,9 +407,14 @@
return false;
}
- /** dump() is a no-op when the feature is disabled. */
+ /** Dump the limited statistics captured when the feature is disabled. */
@Override
- void dump(PrintWriter pw, boolean verbose) {
+ void dump(IndentingPrintWriter pw, boolean verbose) {
+ synchronized (mLock) {
+ pw.format("started=%d maxStarted=%d running=%d expired=%d errors=%d\n",
+ mTotalStarted, mMaxStarted, mTimerIdMap.size(),
+ mTotalExpired, mTotalErrors);
+ }
}
/** close() is a no-op when the feature is disabled. */
@@ -423,6 +443,10 @@
*/
private long mNative = 0;
+ /** The total number of timers that were restarted without an explicit cancel. */
+ @GuardedBy("mLock")
+ private int mTotalRestarted = 0;
+
/** Fetch the native tag (an integer) for the given label. */
FeatureEnabled() {
mNative = nativeAnrTimerCreate(mLabel);
@@ -519,13 +543,22 @@
/** Dump statistics from the native layer. */
@Override
- void dump(PrintWriter pw, boolean verbose) {
+ void dump(IndentingPrintWriter pw, boolean verbose) {
synchronized (mLock) {
- if (mNative != 0) {
- nativeAnrTimerDump(mNative, verbose);
- } else {
+ if (mNative == 0) {
pw.println("closed");
+ return;
}
+ String[] nativeDump = nativeAnrTimerDump(mNative);
+ if (nativeDump == null) {
+ pw.println("no-data");
+ return;
+ }
+ for (String s : nativeDump) {
+ pw.println(s);
+ }
+ // The following counter is only available at the Java level.
+ pw.println("restarted:" + mTotalRestarted);
}
}
@@ -564,13 +597,11 @@
* allows a client to deliver an immediate timeout via the AnrTimer.
*
* @param arg The key by which the timer is known. This is never examined or modified.
- * @param pid The Linux process ID of the target being timed.
- * @param uid The Linux user ID of the target being timed.
* @param timeoutMs The timer timeout, in milliseconds.
*/
- public void start(@NonNull V arg, int pid, int uid, long timeoutMs) {
+ public void start(@NonNull V arg, long timeoutMs) {
if (timeoutMs < 0) timeoutMs = 0;
- mFeature.start(arg, pid, uid, timeoutMs);
+ mFeature.start(arg, getPid(arg), getUid(arg), timeoutMs);
}
/**
@@ -674,11 +705,8 @@
synchronized (mLock) {
pw.format("timer: %s\n", mLabel);
pw.increaseIndent();
- pw.format("started=%d maxStarted=%d restarted=%d running=%d expired=%d errors=%d\n",
- mTotalStarted, mMaxStarted, mTotalRestarted, mTimerIdMap.size(),
- mTotalExpired, mTotalErrors);
- pw.decreaseIndent();
mFeature.dump(pw, false);
+ pw.decreaseIndent();
}
}
@@ -739,6 +767,14 @@
recordErrorLocked(operation, "notFound", arg);
}
+ /** Compare two AnrTimers in display order. */
+ private static final Comparator<AnrTimer> sComparator =
+ Comparator.nullsLast(new Comparator<>() {
+ @Override
+ public int compare(AnrTimer o1, AnrTimer o2) {
+ return o1.mLabel.compareTo(o2.mLabel);
+ }});
+
/** Dumpsys output, allowing for overrides. */
@VisibleForTesting
static void dump(@NonNull PrintWriter pw, boolean verbose, @NonNull Injector injector) {
@@ -748,11 +784,18 @@
ipw.println("AnrTimer statistics");
ipw.increaseIndent();
synchronized (sAnrTimerList) {
+ // Find the currently live instances and sort them by their label. The goal is to
+ // have consistent output ordering.
final int size = sAnrTimerList.size();
- ipw.println("reporting " + size + " timers");
+ AnrTimer[] active = new AnrTimer[size];
+ int valid = 0;
for (int i = 0; i < size; i++) {
AnrTimer a = sAnrTimerList.valueAt(i).get();
- if (a != null) a.dump(ipw);
+ if (a != null) active[valid++] = a;
+ }
+ Arrays.sort(active, 0, valid, sComparator);
+ for (int i = 0; i < valid; i++) {
+ if (active[i] != null) active[i].dump(ipw);
}
}
if (verbose) dumpErrors(ipw);
@@ -811,6 +854,6 @@
/** Discard an expired timer by ID. Return true if the timer was found. */
private static native boolean nativeAnrTimerDiscard(long service, int timerId);
- /** Prod the native library to log a few statistics. */
- private static native void nativeAnrTimerDump(long service, boolean verbose);
+ /** Retrieve runtime dump information from the native layer. */
+ private static native String[] nativeAnrTimerDump(long service);
}
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index ad54efc..84c37180 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -75,7 +75,7 @@
IGNORED_ERROR_TOKEN(VibrationProto.IGNORED_ERROR_TOKEN),
IGNORED_APP_OPS(VibrationProto.IGNORED_APP_OPS),
IGNORED_BACKGROUND(VibrationProto.IGNORED_BACKGROUND),
- IGNORED_UNKNOWN_VIBRATION(VibrationProto.IGNORED_UNKNOWN_VIBRATION),
+ IGNORED_MISSING_PERMISSION(VibrationProto.IGNORED_MISSING_PERMISSION),
IGNORED_UNSUPPORTED(VibrationProto.IGNORED_UNSUPPORTED),
IGNORED_FOR_EXTERNAL(VibrationProto.IGNORED_FOR_EXTERNAL),
IGNORED_FOR_HIGHER_IMPORTANCE(VibrationProto.IGNORED_FOR_HIGHER_IMPORTANCE),
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 8281ac1..09c2493 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -436,26 +436,26 @@
IBinder token, boolean fromIme) {
HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider();
if (hapticVibrationProvider == null) {
- Slog.w(TAG, "performHapticFeedback; haptic vibration provider not ready.");
+ Slog.e(TAG, "performHapticFeedback; haptic vibration provider not ready.");
return null;
}
if (hapticVibrationProvider.isRestrictedHapticFeedback(constant)
&& !hasPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS)) {
- Slog.w(TAG, "performHapticFeedback; no permission for effect " + constant);
+ Slog.w(TAG, "performHapticFeedback; no permission for system constant " + constant);
return null;
}
VibrationEffect effect = hapticVibrationProvider.getVibrationForHapticFeedback(constant);
if (effect == null) {
- Slog.w(TAG, "performHapticFeedback; vibration absent for effect " + constant);
+ Slog.w(TAG, "performHapticFeedback; vibration absent for constant " + constant);
return null;
}
- CombinedVibration combinedVibration = CombinedVibration.createParallel(effect);
+ CombinedVibration vib = CombinedVibration.createParallel(effect);
VibrationAttributes attrs =
hapticVibrationProvider.getVibrationAttributesForHapticFeedback(
constant, /* bypassVibrationIntensitySetting= */ always, fromIme);
+ reason = "performHapticFeedback(constant=" + constant + "): " + reason;
VibratorFrameworkStatsLogger.logPerformHapticsFeedbackIfKeyboard(uid, constant);
- return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, combinedVibration, attrs,
- "performHapticFeedback: " + reason, token);
+ return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, vib, attrs, reason, token);
}
/**
@@ -1951,39 +1951,34 @@
/** Implementation of {@link IExternalVibratorService} to be triggered on external control. */
@VisibleForTesting
final class ExternalVibratorService extends IExternalVibratorService.Stub {
- private static final ExternalVibrationScale SCALE_MUTE = new ExternalVibrationScale();
-
- static {
- SCALE_MUTE.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
- }
@Override
public ExternalVibrationScale onExternalVibrationStart(ExternalVibration vib) {
- if (!hasExternalControlCapability()) {
- return SCALE_MUTE;
- }
- if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
- vib.getUid(), -1 /*owningUid*/, true /*exported*/)
- != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
- + " tried to play externally controlled vibration"
- + " without VIBRATE permission, ignoring.");
- return SCALE_MUTE;
- }
-
// Create Vibration.Stats as close to the received request as possible, for tracking.
ExternalVibrationHolder vibHolder = new ExternalVibrationHolder(vib);
- VibrationAttributes attrs = fixupVibrationAttributes(vib.getVibrationAttributes(),
- /* effect= */ null);
- if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
- // Force update of user settings before checking if this vibration effect should
- // be ignored or scaled.
- mVibrationSettings.update();
- }
-
+ // Mute the request until we run all the checks and accept the vibration.
+ vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
boolean alreadyUnderExternalControl = false;
boolean waitForCompletion = false;
+
synchronized (mLock) {
+ if (!hasExternalControlCapability()) {
+ endVibrationAndWriteStatsLocked(vibHolder,
+ new Vibration.EndInfo(Vibration.Status.IGNORED_UNSUPPORTED));
+ return vibHolder.scale;
+ }
+
+ if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
+ vib.getUid(), -1 /*owningUid*/, true /*exported*/)
+ != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
+ + " tried to play externally controlled vibration"
+ + " without VIBRATE permission, ignoring.");
+ endVibrationAndWriteStatsLocked(vibHolder,
+ new Vibration.EndInfo(Vibration.Status.IGNORED_MISSING_PERMISSION));
+ return vibHolder.scale;
+ }
+
Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(
vibHolder.callerInfo);
@@ -2001,8 +1996,6 @@
}
if (vibrationEndInfo != null) {
- vibHolder.scale = SCALE_MUTE;
- // Failed to start the vibration, end it and report metrics right away.
endVibrationAndWriteStatsLocked(vibHolder, vibrationEndInfo);
return vibHolder.scale;
}
@@ -2040,6 +2033,15 @@
vibHolder.callerInfo),
/* continueExternalControl= */ true);
}
+
+ VibrationAttributes attrs = fixupVibrationAttributes(vib.getVibrationAttributes(),
+ /* effect= */ null);
+ if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
+ // Force update of user settings before checking if this vibration effect should
+ // be ignored or scaled.
+ mVibrationSettings.update();
+ }
+
mCurrentExternalVibration = vibHolder;
vibHolder.linkToDeath();
vibHolder.scale.scaleLevel = mVibrationScaler.getScaleLevel(attrs.getUsage());
@@ -2055,8 +2057,10 @@
endExternalVibrateLocked(
new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_CANCELLING),
/* continueExternalControl= */ false);
+ // Mute the request, vibration will be ignored.
+ vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
}
- return SCALE_MUTE;
+ return vibHolder.scale;
}
}
if (!alreadyUnderExternalControl) {
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index fe4522a..c5683f3 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -99,6 +99,7 @@
import android.window.SizeConfigurationBuckets;
import android.window.TransitionInfo;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.protolog.common.ProtoLog;
@@ -108,6 +109,9 @@
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.uri.GrantUri;
import com.android.server.uri.NeededUriGrants;
+import com.android.server.utils.quota.Categorizer;
+import com.android.server.utils.quota.Category;
+import com.android.server.utils.quota.CountQuotaTracker;
import com.android.server.vr.VrManagerInternal;
/**
@@ -123,6 +127,13 @@
private final ActivityTaskSupervisor mTaskSupervisor;
private final Context mContext;
+ // Prevent malicious app abusing the Activity#setPictureInPictureParams API
+ @VisibleForTesting CountQuotaTracker mSetPipAspectRatioQuotaTracker;
+ // Limit to 60 times / minute
+ private static final int SET_PIP_ASPECT_RATIO_LIMIT = 60;
+ // The timeWindowMs here can not be smaller than QuotaTracker#MIN_WINDOW_SIZE_MS
+ private static final long SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS = 60_000;
+
/** Wrapper around VoiceInteractionServiceManager. */
private AssistUtils mAssistUtils;
@@ -1035,6 +1046,25 @@
+ ": Current activity does not support picture-in-picture.");
}
+ // Rate limit how frequent an app can request aspect ratio change via
+ // Activity#setPictureInPictureParams
+ final int userId = UserHandle.getCallingUserId();
+ if (mSetPipAspectRatioQuotaTracker == null) {
+ mSetPipAspectRatioQuotaTracker = new CountQuotaTracker(mContext,
+ Categorizer.SINGLE_CATEGORIZER);
+ mSetPipAspectRatioQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
+ SET_PIP_ASPECT_RATIO_LIMIT, SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS);
+ }
+ if (r.pictureInPictureArgs.hasSetAspectRatio()
+ && params.hasSetAspectRatio()
+ && !r.pictureInPictureArgs.getAspectRatio().equals(
+ params.getAspectRatio())
+ && !mSetPipAspectRatioQuotaTracker.noteEvent(
+ userId, r.packageName, "setPipAspectRatio")) {
+ throw new IllegalStateException(caller
+ + ": Too many PiP aspect ratio change requests from " + r.packageName);
+ }
+
final float minAspectRatio = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
final float maxAspectRatio = mContext.getResources().getFloat(
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 42efc2d..7d057a9 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4105,6 +4105,7 @@
boolean removedFromHistory = false;
cleanUp(false /* cleanServices */, false /* setState */);
+ setVisibleRequested(false);
if (hasProcess()) {
app.removeActivity(this, true /* keepAssociation */);
@@ -8689,6 +8690,15 @@
// calculate the override, skip the override.
return;
}
+ // Make sure the orientation related fields will be updated by the override insets, because
+ // fixed rotation has assigned the fields from display's configuration.
+ if (hasFixedRotationTransform()) {
+ inOutConfig.windowConfiguration.setAppBounds(null);
+ inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
+ inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
+ inOutConfig.smallestScreenWidthDp = Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
+ inOutConfig.orientation = ORIENTATION_UNDEFINED;
+ }
// Override starts here.
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
@@ -8725,8 +8735,7 @@
// For the case of PIP transition and multi-window environment, the
// smallestScreenWidthDp is handled already. Override only if the app is in
// fullscreen.
- DisplayInfo info = new DisplayInfo();
- mDisplayContent.getDisplay().getDisplayInfo(info);
+ final DisplayInfo info = new DisplayInfo(mDisplayContent.getDisplayInfo());
mDisplayContent.computeSizeRanges(info, rotated, dw, dh,
mDisplayContent.getDisplayMetrics().density,
inOutConfig, true /* overrideConfig */);
@@ -9808,10 +9817,10 @@
if (mLetterboxUiController.shouldApplyUserMinAspectRatioOverride()) {
return mLetterboxUiController.getUserMinAspectRatio();
}
- if (!mLetterboxUiController.shouldOverrideMinAspectRatio()) {
+ if (!mLetterboxUiController.shouldOverrideMinAspectRatio()
+ && !mLetterboxUiController.shouldOverrideMinAspectRatioForCamera()) {
return info.getMinAspectRatio();
}
-
if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY)
&& !ActivityInfo.isFixedOrientationPortrait(
getOverrideOrientation())) {
@@ -9932,6 +9941,16 @@
return updateReportedConfigurationAndSend();
}
+ /**
+ * @return {@code true} if the Camera is active for the current activity
+ */
+ boolean isCameraActive() {
+ return mDisplayContent != null
+ && mDisplayContent.getDisplayRotationCompatPolicy() != null
+ && mDisplayContent.getDisplayRotationCompatPolicy()
+ .isCameraActive(this, /* mustBeFullscreen */ true);
+ }
+
boolean updateReportedConfigurationAndSend() {
if (isConfigurationDispatchPaused()) {
Slog.wtf(TAG, "trying to update reported(client) config while dispatch is paused");
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b3c43bc..fc05d17 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1374,13 +1374,14 @@
final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
+ final int userId = UserHandle.getCallingUserId();
ActivityInfo aInfo = null;
try {
List<ResolveInfo> resolves =
AppGlobals.getPackageManager().queryIntentActivities(
intent, r.resolvedType,
PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
- UserHandle.getCallingUserId()).getList();
+ userId).getList();
// Look for the original activity in the list...
final int N = resolves != null ? resolves.size() : 0;
@@ -1465,6 +1466,7 @@
.setRealCallingPid(-1)
.setRealCallingUid(r.launchedFromUid)
.setActivityOptions(options)
+ .setUserId(userId)
.execute();
r.finishing = wasFinishing;
return res == ActivityManager.START_SUCCESS;
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 4c53e0f..c9703d8 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -302,7 +302,8 @@
} else if (prevTask.isActivityTypeHome()) {
removedWindowContainer = currentTask;
backType = BackNavigationInfo.TYPE_RETURN_TO_HOME;
- mShowWallpaper = true;
+ final ActivityRecord ar = prevTask.getTopNonFinishingActivity();
+ mShowWallpaper = ar != null && ar.hasWallpaper();
} else {
// If it reaches the top activity, we will check the below task from parent.
// If it's null or multi-window and has different parent task, fallback the type
@@ -310,7 +311,9 @@
// another task.
final Task prevParent = prevTask.getParent().asTask();
final Task currParent = currentTask.getParent().asTask();
- if (prevTask.inMultiWindowMode() && prevParent != currParent) {
+ if ((prevTask.inMultiWindowMode() && prevParent != currParent)
+ // Do not animate to translucent task, it could be trampoline.
+ || hasTranslucentActivity(currentActivity, prevActivities)) {
backType = BackNavigationInfo.TYPE_CALLBACK;
} else {
removedWindowContainer = prevTask;
@@ -525,7 +528,7 @@
}
for (int i = prevActivities.size() - 1; i >= 0; --i) {
final ActivityRecord test = prevActivities.get(i);
- if (!test.occludesParent() || test.showWallpaper()) {
+ if (!test.occludesParent() || test.hasWallpaper()) {
return true;
}
}
diff --git a/services/core/java/com/android/server/wm/CameraStateMonitor.java b/services/core/java/com/android/server/wm/CameraStateMonitor.java
new file mode 100644
index 0000000..ea7edea
--- /dev/null
+++ b/services/core/java/com/android/server/wm/CameraStateMonitor.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.wm;
+
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.camera2.CameraManager;
+import android.os.Handler;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.protolog.common.ProtoLog;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Class that listens to camera open/closed signals, keeps track of the current apps using camera,
+ * and notifies listeners.
+ */
+class CameraStateMonitor {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "CameraStateMonitor" : TAG_WM;
+
+ // Delay for updating letterbox after Camera connection is closed. Needed to avoid flickering
+ // when an app is flipping between front and rear cameras or when size compat mode is restarted.
+ // TODO(b/330148095): Investigate flickering without using delays, remove them if possible.
+ private static final int CAMERA_CLOSED_LETTERBOX_UPDATE_DELAY_MS = 2000;
+ // Delay for updating letterboxing after Camera connection is opened. This delay is selected to
+ // be long enough to avoid conflicts with transitions on the app's side.
+ // Using a delay < CAMERA_CLOSED_ROTATION_UPDATE_DELAY_MS to avoid flickering when an app
+ // is flipping between front and rear cameras (in case requested orientation changes at
+ // runtime at the same time) or when size compat mode is restarted.
+ // TODO(b/330148095): Investigate flickering without using delays, remove them if possible.
+ private static final int CAMERA_OPENED_LETTERBOX_UPDATE_DELAY_MS =
+ CAMERA_CLOSED_LETTERBOX_UPDATE_DELAY_MS / 2;
+
+ @NonNull
+ private final DisplayContent mDisplayContent;
+ @NonNull
+ private final WindowManagerService mWmService;
+ @Nullable
+ private final CameraManager mCameraManager;
+ @NonNull
+ private final Handler mHandler;
+
+ @Nullable
+ private ActivityRecord mCameraActivity;
+
+ // Bi-directional map between package names and active camera IDs since we need to 1) get a
+ // camera id by a package name when resizing the window; 2) get a package name by a camera id
+ // when camera connection is closed and we need to clean up our records.
+ private final CameraIdPackageNameBiMapping mCameraIdPackageBiMapping =
+ new CameraIdPackageNameBiMapping();
+ private final Set<String> mScheduledToBeRemovedCameraIdSet = new ArraySet<>();
+
+ // TODO(b/336474959): should/can this go in the compat listeners?
+ private final Set<String> mScheduledCompatModeUpdateCameraIdSet = new ArraySet<>();
+
+ private final ArrayList<CameraCompatStateListener> mCameraStateListeners = new ArrayList<>();
+
+ /**
+ * {@link CameraCompatStateListener} which returned {@code true} on the last {@link
+ * CameraCompatStateListener#onCameraOpened(ActivityRecord, String)}, if any.
+ *
+ * <p>This allows the {@link CameraStateMonitor} to notify a particular listener when camera
+ * closes, so they can revert any changes.
+ */
+ @Nullable
+ private CameraCompatStateListener mCurrentListenerForCameraActivity;
+
+ private final CameraManager.AvailabilityCallback mAvailabilityCallback =
+ new CameraManager.AvailabilityCallback() {
+ @Override
+ public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) {
+ synchronized (mWmService.mGlobalLock) {
+ notifyCameraOpened(cameraId, packageId);
+ }
+ }
+ @Override
+ public void onCameraClosed(@NonNull String cameraId) {
+ synchronized (mWmService.mGlobalLock) {
+ notifyCameraClosed(cameraId);
+ }
+ }
+ };
+
+ CameraStateMonitor(@NonNull DisplayContent displayContent, @NonNull Handler handler) {
+ // This constructor is called from DisplayContent constructor. Don't use any fields in
+ // DisplayContent here since they aren't guaranteed to be set.
+ mHandler = handler;
+ mDisplayContent = displayContent;
+ mWmService = displayContent.mWmService;
+ mCameraManager = mWmService.mContext.getSystemService(CameraManager.class);
+ }
+
+ void startListeningToCameraState() {
+ mCameraManager.registerAvailabilityCallback(
+ mWmService.mContext.getMainExecutor(), mAvailabilityCallback);
+ }
+
+ /** Releases camera callback listener. */
+ void dispose() {
+ if (mCameraManager != null) {
+ mCameraManager.unregisterAvailabilityCallback(mAvailabilityCallback);
+ }
+ }
+
+ void addCameraStateListener(CameraCompatStateListener listener) {
+ mCameraStateListeners.add(listener);
+ }
+
+ void removeCameraStateListener(CameraCompatStateListener listener) {
+ mCameraStateListeners.remove(listener);
+ }
+
+ private void notifyCameraOpened(
+ @NonNull String cameraId, @NonNull String packageName) {
+ // If an activity is restarting or camera is flipping, the camera connection can be
+ // quickly closed and reopened.
+ mScheduledToBeRemovedCameraIdSet.remove(cameraId);
+ ProtoLog.v(WM_DEBUG_STATES,
+ "Display id=%d is notified that Camera %s is open for package %s",
+ mDisplayContent.mDisplayId, cameraId, packageName);
+ // Some apps can’t handle configuration changes coming at the same time with Camera setup so
+ // delaying orientation update to accommodate for that.
+ mScheduledCompatModeUpdateCameraIdSet.add(cameraId);
+ mHandler.postDelayed(
+ () -> {
+ synchronized (mWmService.mGlobalLock) {
+ if (!mScheduledCompatModeUpdateCameraIdSet.remove(cameraId)) {
+ // Camera compat mode update has happened already or was cancelled
+ // because camera was closed.
+ return;
+ }
+ mCameraIdPackageBiMapping.put(packageName, cameraId);
+ mCameraActivity = findCameraActivity(packageName);
+ if (mCameraActivity == null || mCameraActivity.getTask() == null) {
+ return;
+ }
+ notifyListenersCameraOpened(mCameraActivity, cameraId);
+ }
+ },
+ CAMERA_OPENED_LETTERBOX_UPDATE_DELAY_MS);
+ }
+
+ private void notifyListenersCameraOpened(@NonNull ActivityRecord cameraActivity,
+ @NonNull String cameraId) {
+ for (int i = 0; i < mCameraStateListeners.size(); i++) {
+ CameraCompatStateListener listener = mCameraStateListeners.get(i);
+ boolean activeCameraTreatment = listener.onCameraOpened(
+ cameraActivity, cameraId);
+ if (activeCameraTreatment) {
+ mCurrentListenerForCameraActivity = listener;
+ break;
+ }
+ }
+ }
+
+ private void notifyCameraClosed(@NonNull String cameraId) {
+ ProtoLog.v(WM_DEBUG_STATES,
+ "Display id=%d is notified that Camera %s is closed.",
+ mDisplayContent.mDisplayId, cameraId);
+ mScheduledToBeRemovedCameraIdSet.add(cameraId);
+ // No need to update window size for this camera if it's already closed.
+ mScheduledCompatModeUpdateCameraIdSet.remove(cameraId);
+ scheduleRemoveCameraId(cameraId);
+ }
+
+ boolean isCameraRunningForActivity(@NonNull ActivityRecord activity) {
+ return getCameraIdForActivity(activity) != null;
+ }
+
+ // TODO(b/336474959): try to decouple `cameraId` from the listeners.
+ boolean isCameraWithIdRunningForActivity(@NonNull ActivityRecord activity, String cameraId) {
+ return cameraId.equals(getCameraIdForActivity(activity));
+ }
+
+ void rescheduleRemoveCameraActivity(@NonNull String cameraId) {
+ mScheduledToBeRemovedCameraIdSet.add(cameraId);
+ scheduleRemoveCameraId(cameraId);
+ }
+
+ @Nullable
+ private String getCameraIdForActivity(@NonNull ActivityRecord activity) {
+ return mCameraIdPackageBiMapping.getCameraId(activity.packageName);
+ }
+
+ // Delay is needed to avoid rotation flickering when an app is flipping between front and
+ // rear cameras, when size compat mode is restarted or activity is being refreshed.
+ private void scheduleRemoveCameraId(@NonNull String cameraId) {
+ mHandler.postDelayed(
+ () -> removeCameraId(cameraId),
+ CAMERA_CLOSED_LETTERBOX_UPDATE_DELAY_MS);
+ }
+
+ private void removeCameraId(@NonNull String cameraId) {
+ synchronized (mWmService.mGlobalLock) {
+ if (!mScheduledToBeRemovedCameraIdSet.remove(cameraId)) {
+ // Already reconnected to this camera, no need to clean up.
+ return;
+ }
+ if (mCameraActivity != null && mCurrentListenerForCameraActivity != null) {
+ boolean closeSuccessful =
+ mCurrentListenerForCameraActivity.onCameraClosed(mCameraActivity, cameraId);
+ if (closeSuccessful) {
+ mCameraIdPackageBiMapping.removeCameraId(cameraId);
+ mCurrentListenerForCameraActivity = null;
+ } else {
+ rescheduleRemoveCameraActivity(cameraId);
+ }
+ }
+ }
+ }
+
+ // TODO(b/335165310): verify that this works in multi instance and permission dialogs.
+ @Nullable
+ private ActivityRecord findCameraActivity(@NonNull String packageName) {
+ final ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity != null && topActivity.packageName.equals(packageName)) {
+ return topActivity;
+ }
+
+ final List<ActivityRecord> activitiesOfPackageWhichOpenedCamera = new ArrayList<>();
+ mDisplayContent.forAllActivities(activityRecord -> {
+ if (activityRecord.isVisibleRequested()
+ && activityRecord.packageName.equals(packageName)) {
+ activitiesOfPackageWhichOpenedCamera.add(activityRecord);
+ }
+ });
+
+ if (activitiesOfPackageWhichOpenedCamera.isEmpty()) {
+ Slog.w(TAG, "Cannot find camera activity.");
+ return null;
+ }
+
+ if (activitiesOfPackageWhichOpenedCamera.size() == 1) {
+ return activitiesOfPackageWhichOpenedCamera.getFirst();
+ }
+
+ // Return null if we cannot determine which activity opened camera. This is preferred to
+ // applying treatment to the wrong activity.
+ Slog.w(TAG, "Cannot determine which activity opened camera.");
+ return null;
+ }
+
+ String getSummary() {
+ return " CameraIdPackageNameBiMapping="
+ + mCameraIdPackageBiMapping
+ .getSummaryForDisplayRotationHistoryRecord();
+ }
+
+ interface CameraCompatStateListener {
+ /**
+ * Notifies the compat listener that an activity has opened camera.
+ *
+ * @return true if the treatment has been applied.
+ */
+ // TODO(b/336474959): try to decouple `cameraId` from the listeners.
+ boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId);
+ /**
+ * Notifies the compat listener that an activity has closed the camera.
+ *
+ * @return true if cleanup has been successful - the notifier might try again if false.
+ */
+ // TODO(b/336474959): try to decouple `cameraId` from the listeners.
+ boolean onCameraClosed(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index f04b4af..1c59977 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -111,19 +111,7 @@
}
if (phase == PHASE_WINDOWING_MODE) {
- return RESULT_DONE;
- }
-
- // TODO(b/336998072) - Find a better solution to this that makes use of the logic from
- // TaskLaunchParamsModifier. Put logic in common utils, return RESULT_CONTINUE, inherit
- // from parent class, etc.
- if (outParams.mPreferredTaskDisplayArea == null && task.getRootTask() != null) {
- appendLog("display-from-task=" + task.getRootTask().getDisplayId());
- outParams.mPreferredTaskDisplayArea = task.getRootTask().getDisplayArea();
- }
-
- if (phase == PHASE_DISPLAY_AREA) {
- return RESULT_DONE;
+ return RESULT_CONTINUE;
}
if (!currentParams.mBounds.isEmpty()) {
@@ -135,7 +123,7 @@
appendLog("setting desktop mode task bounds to %s", outParams.mBounds);
- return RESULT_DONE;
+ return RESULT_CONTINUE;
}
/**
@@ -178,24 +166,24 @@
* Return {@code true} if desktop mode should be restricted to supported devices.
*/
@VisibleForTesting
- public boolean enforceDeviceRestrictions() {
+ static boolean enforceDeviceRestrictions() {
return ENFORCE_DEVICE_RESTRICTIONS;
}
/**
* Return {@code true} if the current device supports desktop mode.
*/
+ // TODO(b/337819319): use a companion object instead.
@VisibleForTesting
- public boolean isDesktopModeSupported(@NonNull Context context) {
+ static boolean isDesktopModeSupported(@NonNull Context context) {
return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
}
/**
* Return {@code true} if desktop mode can be entered on the current device.
*/
- boolean canEnterDesktopMode(@NonNull Context context) {
+ static boolean canEnterDesktopMode(@NonNull Context context) {
return isDesktopModeEnabled()
&& (!enforceDeviceRestrictions() || isDesktopModeSupported(context));
}
-
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 95ec75c..2f37e88 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -473,7 +473,12 @@
private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
private final DisplayPolicy mDisplayPolicy;
private final DisplayRotation mDisplayRotation;
- @Nullable final DisplayRotationCompatPolicy mDisplayRotationCompatPolicy;
+
+ @Nullable
+ final DisplayRotationCompatPolicy mDisplayRotationCompatPolicy;
+ @Nullable
+ final CameraStateMonitor mCameraStateMonitor;
+
DisplayFrames mDisplayFrames;
final DisplayUpdater mDisplayUpdater;
@@ -1247,11 +1252,23 @@
onDisplayChanged(this);
updateDisplayAreaOrganizers();
- mDisplayRotationCompatPolicy =
- // Not checking DeviceConfig value here to allow enabling via DeviceConfig
- // without the need to restart the device.
- mWmService.mLetterboxConfiguration.isCameraCompatTreatmentEnabledAtBuildTime()
- ? new DisplayRotationCompatPolicy(this) : null;
+ // Not checking DeviceConfig value here to allow enabling via DeviceConfig
+ // without the need to restart the device.
+ final boolean shouldCreateDisplayRotationCompatPolicy =
+ mWmService.mLetterboxConfiguration.isCameraCompatTreatmentEnabledAtBuildTime();
+ if (shouldCreateDisplayRotationCompatPolicy) {
+ mCameraStateMonitor = new CameraStateMonitor(this, mWmService.mH);
+ mDisplayRotationCompatPolicy = new DisplayRotationCompatPolicy(
+ this, mWmService.mH, mCameraStateMonitor);
+
+ mCameraStateMonitor.startListeningToCameraState();
+ } else {
+ // These are to satisfy the `final` check.
+ mCameraStateMonitor = null;
+ mDisplayRotationCompatPolicy = null;
+ }
+
+
mRotationReversionController = new DisplayRotationReversionController(this);
mInputMonitor = new InputMonitor(mWmService, this);
@@ -1301,6 +1318,15 @@
}
}
+ /**
+ * @return The {@link DisplayRotationCompatPolicy} for this DisplayContent
+ */
+ // TODO(b/335387481) Allow access to DisplayRotationCompatPolicy only with getters
+ @Nullable
+ DisplayRotationCompatPolicy getDisplayRotationCompatPolicy() {
+ return mDisplayRotationCompatPolicy;
+ }
+
@Override
void migrateToNewSurfaceControl(Transaction t) {
t.remove(mSurfaceControl);
@@ -2004,12 +2030,11 @@
}
// Update directly because the app which will change the orientation of display is ready.
if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) {
- // Run rotation change on display thread. See Transition#shouldApplyOnDisplayThread().
- mWmService.mH.post(() -> {
- synchronized (mWmService.mGlobalLock) {
- sendNewConfiguration();
- }
- });
+ // If a transition is collecting, let the transition apply the rotation change on
+ // display thread. See Transition#shouldApplyOnDisplayThread().
+ if (!mTransitionController.isCollecting(this)) {
+ sendNewConfiguration();
+ }
return;
}
if (mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange()) {
@@ -3453,6 +3478,9 @@
if (mDisplayRotationCompatPolicy != null) {
mDisplayRotationCompatPolicy.dispose();
}
+ if (mCameraStateMonitor != null) {
+ mCameraStateMonitor.dispose();
+ }
}
/** Returns true if a removal action is still being deferred. */
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index c8a7ef1..eacf9a3 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -43,20 +43,15 @@
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
-import android.hardware.camera2.CameraManager;
import android.os.Handler;
import android.os.RemoteException;
-import android.util.ArraySet;
import android.widget.Toast;
import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.UiThread;
-import java.util.Set;
-
/**
* Controls camera compatibility treatment that handles orientation mismatch between camera
* buffers and an app window for a particular display that can lead to camera issues like sideways
@@ -69,7 +64,7 @@
* R.bool.config_isWindowManagerCameraCompatTreatmentEnabled} is {@code true}.
*/
// TODO(b/261444714): Consider moving Camera-specific logic outside of the WM Core path
-final class DisplayRotationCompatPolicy {
+class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraCompatStateListener {
// Delay for updating display rotation after Camera connection is closed. Needed to avoid
// rotation flickering when an app is flipping between front and rear cameras or when size
@@ -91,54 +86,26 @@
private final DisplayContent mDisplayContent;
private final WindowManagerService mWmService;
- private final CameraManager mCameraManager;
+ private final CameraStateMonitor mCameraStateMonitor;
private final Handler mHandler;
- // Bi-directional map between package names and active camera IDs since we need to 1) get a
- // camera id by a package name when determining rotation; 2) get a package name by a camera id
- // when camera connection is closed and we need to clean up our records.
- @GuardedBy("this")
- private final CameraIdPackageNameBiMapping mCameraIdPackageBiMap =
- new CameraIdPackageNameBiMapping();
- @GuardedBy("this")
- private final Set<String> mScheduledToBeRemovedCameraIdSet = new ArraySet<>();
- @GuardedBy("this")
- private final Set<String> mScheduledOrientationUpdateCameraIdSet = new ArraySet<>();
-
- private final CameraManager.AvailabilityCallback mAvailabilityCallback =
- new CameraManager.AvailabilityCallback() {
- @Override
- public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) {
- notifyCameraOpened(cameraId, packageId);
- }
-
- @Override
- public void onCameraClosed(@NonNull String cameraId) {
- notifyCameraClosed(cameraId);
- }
- };
-
@ScreenOrientation
private int mLastReportedOrientation = SCREEN_ORIENTATION_UNSET;
- DisplayRotationCompatPolicy(@NonNull DisplayContent displayContent) {
- this(displayContent, displayContent.mWmService.mH);
- }
-
- @VisibleForTesting
- DisplayRotationCompatPolicy(@NonNull DisplayContent displayContent, Handler handler) {
+ DisplayRotationCompatPolicy(@NonNull DisplayContent displayContent, Handler handler,
+ @NonNull CameraStateMonitor cameraStateMonitor) {
// This constructor is called from DisplayContent constructor. Don't use any fields in
// DisplayContent here since they aren't guaranteed to be set.
mHandler = handler;
mDisplayContent = displayContent;
mWmService = displayContent.mWmService;
- mCameraManager = mWmService.mContext.getSystemService(CameraManager.class);
- mCameraManager.registerAvailabilityCallback(
- mWmService.mContext.getMainExecutor(), mAvailabilityCallback);
+ mCameraStateMonitor = cameraStateMonitor;
+ mCameraStateMonitor.addCameraStateListener(this);
}
+ /** Releases camera state listener. */
void dispose() {
- mCameraManager.unregisterAvailabilityCallback(mAvailabilityCallback);
+ mCameraStateMonitor.removeCameraStateListener(this);
}
/**
@@ -169,7 +136,7 @@
if (!isTreatmentEnabledForDisplay()) {
return SCREEN_ORIENTATION_UNSPECIFIED;
}
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ final ActivityRecord topActivity = mDisplayContent.topRunningActivity(
/* considerKeyguardState= */ true);
if (!isTreatmentEnabledForActivity(topActivity)) {
return SCREEN_ORIENTATION_UNSPECIFIED;
@@ -188,7 +155,7 @@
// rotated in the orientation oposite to the natural one even if it's portrait.
// TODO(b/261475895): Consider allowing more rotations for "sensor" and "user" versions
// of the portrait and landscape orientation requests.
- int orientation = (isPortraitActivity && isNaturalDisplayOrientationPortrait)
+ final int orientation = (isPortraitActivity && isNaturalDisplayOrientationPortrait)
|| (!isPortraitActivity && !isNaturalDisplayOrientationPortrait)
? SCREEN_ORIENTATION_PORTRAIT
: SCREEN_ORIENTATION_LANDSCAPE;
@@ -249,12 +216,10 @@
* reason with the {@link Toast}.
*/
void onScreenRotationAnimationFinished() {
- if (!isTreatmentEnabledForDisplay() || mCameraIdPackageBiMap.isEmpty()) {
- return;
- }
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (!isTreatmentEnabledForActivity(topActivity)) {
+ final ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (!isTreatmentEnabledForDisplay()
+ || !isTreatmentEnabledForActivity(topActivity)) {
return;
}
showToast(R.string.display_rotation_camera_compat_toast_after_rotation);
@@ -272,8 +237,8 @@
+ (topActivity == null ? "null" : topActivity.shortComponentName)
+ " isTreatmentEnabledForActivity="
+ isTreatmentEnabledForActivity(topActivity)
- + " CameraIdPackageNameBiMap="
- + mCameraIdPackageBiMap.getSummaryForDisplayRotationHistoryRecord();
+ + "mCameraStateMonitor="
+ + mCameraStateMonitor.getSummary();
}
return "DisplayRotationCompatPolicy{"
+ " isTreatmentEnabledForDisplay=" + isTreatmentEnabledForDisplay()
@@ -341,7 +306,8 @@
boolean isActivityEligibleForOrientationOverride(@NonNull ActivityRecord activity) {
return isTreatmentEnabledForDisplay()
- && isCameraActive(activity, /* mustBeFullscreen */ true);
+ && isCameraActive(activity, /* mustBeFullscreen */ true)
+ && activity.mLetterboxUiController.shouldForceRotateForCameraCompat();
}
@@ -359,6 +325,13 @@
return isTreatmentEnabledForActivity(activity, /* mustBeFullscreen */ true);
}
+ boolean isCameraActive(@NonNull ActivityRecord activity, boolean mustBeFullscreen) {
+ // Checking windowing mode on activity level because we don't want to
+ // apply treatment in case of activity embedding.
+ return (!mustBeFullscreen || !activity.inMultiWindowMode())
+ && mCameraStateMonitor.isCameraRunningForActivity(activity);
+ }
+
private boolean isTreatmentEnabledForActivity(@Nullable ActivityRecord activity,
boolean mustBeFullscreen) {
return activity != null && isCameraActive(activity, mustBeFullscreen)
@@ -366,74 +339,41 @@
// "locked" and "nosensor" values are often used by camera apps that can't
// handle dynamic changes so we shouldn't force rotate them.
&& activity.getOverrideOrientation() != SCREEN_ORIENTATION_NOSENSOR
- && activity.getOverrideOrientation() != SCREEN_ORIENTATION_LOCKED;
- }
-
- private boolean isCameraActive(@NonNull ActivityRecord activity, boolean mustBeFullscreen) {
- // Checking windowing mode on activity level because we don't want to
- // apply treatment in case of activity embedding.
- return (!mustBeFullscreen || !activity.inMultiWindowMode())
- && mCameraIdPackageBiMap.containsPackageName(activity.packageName)
+ && activity.getOverrideOrientation() != SCREEN_ORIENTATION_LOCKED
&& activity.mLetterboxUiController.shouldForceRotateForCameraCompat();
}
- private synchronized void notifyCameraOpened(
- @NonNull String cameraId, @NonNull String packageName) {
- // If an activity is restarting or camera is flipping, the camera connection can be
- // quickly closed and reopened.
- mScheduledToBeRemovedCameraIdSet.remove(cameraId);
- ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Display id=%d is notified that Camera %s is open for package %s",
- mDisplayContent.mDisplayId, cameraId, packageName);
- // Some apps can’t handle configuration changes coming at the same time with Camera setup
- // so delaying orientation update to accomadate for that.
- mScheduledOrientationUpdateCameraIdSet.add(cameraId);
- mHandler.postDelayed(
- () -> delayedUpdateOrientationWithWmLock(cameraId, packageName),
- CAMERA_OPENED_ROTATION_UPDATE_DELAY_MS);
- }
-
- private void delayedUpdateOrientationWithWmLock(
- @NonNull String cameraId, @NonNull String packageName) {
- synchronized (this) {
- if (!mScheduledOrientationUpdateCameraIdSet.remove(cameraId)) {
- // Orientation update has happened already or was cancelled because
- // camera was closed.
- return;
- }
- mCameraIdPackageBiMap.put(packageName, cameraId);
+ @Override
+ public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity,
+ @NonNull String cameraId) {
+ // Checking whether an activity in fullscreen rather than the task as this camera
+ // compat treatment doesn't cover activity embedding.
+ if (cameraActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ cameraActivity.mLetterboxUiController.recomputeConfigurationForCameraCompatIfNeeded();
+ mDisplayContent.updateOrientation();
+ return true;
}
- synchronized (mWmService.mGlobalLock) {
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null || topActivity.getTask() == null) {
- return;
- }
- // Checking whether an activity in fullscreen rather than the task as this camera
- // compat treatment doesn't cover activity embedding.
- if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
- topActivity.mLetterboxUiController.recomputeConfigurationForCameraCompatIfNeeded();
- mDisplayContent.updateOrientation();
- return;
- }
- // Checking that the whole app is in multi-window mode as we shouldn't show toast
- // for the activity embedding case.
- if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
- && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
- final PackageManager packageManager = mWmService.mContext.getPackageManager();
- try {
- showToast(
- R.string.display_rotation_camera_compat_toast_in_multi_window,
- (String) packageManager.getApplicationLabel(
- packageManager.getApplicationInfo(packageName, /* flags */ 0)));
- } catch (PackageManager.NameNotFoundException e) {
- ProtoLog.e(WM_DEBUG_ORIENTATION,
- "DisplayRotationCompatPolicy: Multi-window toast not shown as "
- + "package '%s' cannot be found.",
- packageName);
- }
+ // Checking that the whole app is in multi-window mode as we shouldn't show toast
+ // for the activity embedding case.
+ if (cameraActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
+ && isTreatmentEnabledForActivity(
+ cameraActivity, /* mustBeFullscreen */ false)) {
+ final PackageManager packageManager = mWmService.mContext.getPackageManager();
+ try {
+ showToast(
+ R.string.display_rotation_camera_compat_toast_in_multi_window,
+ (String) packageManager.getApplicationLabel(
+ packageManager.getApplicationInfo(cameraActivity.packageName,
+ /* flags */ 0)));
+ return true;
+ } catch (PackageManager.NameNotFoundException e) {
+ ProtoLog.e(WM_DEBUG_ORIENTATION,
+ "DisplayRotationCompatPolicy: Multi-window toast not shown as "
+ + "package '%s' cannot be found.",
+ cameraActivity.packageName);
}
}
+ return false;
}
@VisibleForTesting
@@ -451,66 +391,42 @@
Toast.LENGTH_LONG).show());
}
- private synchronized void notifyCameraClosed(@NonNull String cameraId) {
- ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Display id=%d is notified that Camera %s is closed, scheduling rotation update.",
- mDisplayContent.mDisplayId, cameraId);
- mScheduledToBeRemovedCameraIdSet.add(cameraId);
- // No need to update orientation for this camera if it's already closed.
- mScheduledOrientationUpdateCameraIdSet.remove(cameraId);
- scheduleRemoveCameraId(cameraId);
- }
-
- // Delay is needed to avoid rotation flickering when an app is flipping between front and
- // rear cameras, when size compat mode is restarted or activity is being refreshed.
- private void scheduleRemoveCameraId(@NonNull String cameraId) {
- mHandler.postDelayed(
- () -> removeCameraId(cameraId),
- CAMERA_CLOSED_ROTATION_UPDATE_DELAY_MS);
- }
-
- private void removeCameraId(String cameraId) {
+ @Override
+ public boolean onCameraClosed(@NonNull ActivityRecord cameraActivity,
+ @NonNull String cameraId) {
synchronized (this) {
- if (!mScheduledToBeRemovedCameraIdSet.remove(cameraId)) {
- // Already reconnected to this camera, no need to clean up.
- return;
- }
+ // TODO(b/336474959): Once refresh is implemented in `CameraCompatFreeformPolicy`,
+ // consider checking this in CameraStateMonitor before notifying the listeners (this).
if (isActivityForCameraIdRefreshing(cameraId)) {
ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Display id=%d is notified that Camera %s is closed but activity is"
+ "Display id=%d is notified that camera is closed but activity is"
+ " still refreshing. Rescheduling an update.",
- mDisplayContent.mDisplayId, cameraId);
- mScheduledToBeRemovedCameraIdSet.add(cameraId);
- scheduleRemoveCameraId(cameraId);
- return;
+ mDisplayContent.mDisplayId);
+ return false;
}
- mCameraIdPackageBiMap.removeCameraId(cameraId);
}
ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Display id=%d is notified that Camera %s is closed, updating rotation.",
- mDisplayContent.mDisplayId, cameraId);
- synchronized (mWmService.mGlobalLock) {
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null
- // Checking whether an activity in fullscreen rather than the task as this
- // camera compat treatment doesn't cover activity embedding.
- || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
- return;
- }
- topActivity.mLetterboxUiController.recomputeConfigurationForCameraCompatIfNeeded();
- mDisplayContent.updateOrientation();
+ "Display id=%d is notified that Camera is closed, updating rotation.",
+ mDisplayContent.mDisplayId);
+ final ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity == null
+ // Checking whether an activity in fullscreen rather than the task as this
+ // camera compat treatment doesn't cover activity embedding.
+ || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ return true;
}
+ topActivity.mLetterboxUiController.recomputeConfigurationForCameraCompatIfNeeded();
+ mDisplayContent.updateOrientation();
+ return true;
}
+ // TODO(b/336474959): Do we need cameraId here?
private boolean isActivityForCameraIdRefreshing(String cameraId) {
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ final ActivityRecord topActivity = mDisplayContent.topRunningActivity(
/* considerKeyguardState= */ true);
- if (!isTreatmentEnabledForActivity(topActivity)) {
- return false;
- }
- String activeCameraId = mCameraIdPackageBiMap.getCameraId(topActivity.packageName);
- if (activeCameraId == null || activeCameraId != cameraId) {
+ if (!isTreatmentEnabledForActivity(topActivity)
+ || !mCameraStateMonitor.isCameraWithIdRunningForActivity(topActivity, cameraId)) {
return false;
}
return topActivity.mLetterboxUiController.isRefreshAfterRotationRequested();
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 683efde..b38e666 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -30,6 +30,7 @@
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
@@ -510,6 +511,26 @@
}
/**
+ * Whether we should apply the min aspect ratio per-app override only when an app is connected
+ * to the camera.
+ * When this override is applied the min aspect ratio given in the app's manifest will be
+ * overridden to the largest enabled aspect ratio treatment unless the app's manifest value
+ * is higher. The treatment will also apply if no value is provided in the manifest.
+ *
+ * <p>This method returns {@code true} when the following conditions are met:
+ * <ul>
+ * <li>Opt-out component property isn't enabled
+ * <li>Per-app override is enabled
+ * </ul>
+ */
+ boolean shouldOverrideMinAspectRatioForCamera() {
+ return mActivityRecord.isCameraActive()
+ && mAllowMinAspectRatioOverrideOptProp
+ .shouldEnableWithOptInOverrideAndOptOutProperty(
+ isCompatChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA));
+ }
+
+ /**
* Whether we should apply the force resize per-app override. When this override is applied it
* forces the packages it is applied to to be resizable. It won't change whether the app can be
* put into multi-windowing mode, but allow the app to resize without going into size-compat
@@ -962,7 +983,8 @@
void recomputeConfigurationForCameraCompatIfNeeded() {
if (isOverrideOrientationOnlyForCameraEnabled()
- || isCameraCompatSplitScreenAspectRatioAllowed()) {
+ || isCameraCompatSplitScreenAspectRatioAllowed()
+ || shouldOverrideMinAspectRatioForCamera()) {
mActivityRecord.recomputeConfiguration();
}
}
diff --git a/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java b/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
index 883d27f..498182d 100644
--- a/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
+++ b/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.tracing.perfetto.DataSourceParams.PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT;
+
import android.annotation.NonNull;
import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellTransition;
import android.internal.perfetto.protos.TracePacketOuterClass.TracePacket;
@@ -39,7 +41,8 @@
PerfettoTransitionTracer() {
Producer.init(InitArguments.DEFAULTS);
- mDataSource.register(DataSourceParams.DEFAULTS);
+ mDataSource.register(
+ new DataSourceParams(PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT));
}
/**
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 622a809..6003c1b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2477,6 +2477,7 @@
final DisplayContent display = getChildAt(displayNdx);
final boolean curResult = result;
boolean[] resumedOnDisplay = new boolean[1];
+ final ActivityRecord topOfDisplay = display.topRunningActivity();
display.forAllRootTasks(rootTask -> {
final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
@@ -2490,8 +2491,7 @@
resumedOnDisplay[0] |= curResult;
return;
}
- if (topRunningActivity.isState(RESUMED)
- && topRunningActivity == rootTask.getDisplayArea().topRunningActivity()) {
+ if (topRunningActivity.isState(RESUMED) && topRunningActivity == topOfDisplay) {
// Kick off any lingering app transitions form the MoveTaskToFront operation,
// but only consider the top activity on that display.
rootTask.executeAppTransition(targetOptions);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index f8aa69b..bb86460 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -41,6 +41,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.window.flags.Flags.windowSessionRelayoutInfo;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -79,6 +80,7 @@
import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager;
+import android.view.WindowRelayoutResult;
import android.window.ClientWindowFrames;
import android.window.InputTransferToken;
import android.window.OnBackInvokedCallbackInfo;
@@ -280,20 +282,29 @@
@Override
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
+ int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
+ int res = mService.relayoutWindow(this, window, attrs, requestedWidth,
+ requestedHeight, viewFlags, flags, seq, lastSyncSeqId, outRelayoutResult);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ return res;
+ }
+
+ /** @deprecated */
+ @Deprecated
+ @Override
+ public int relayoutLegacy(IWindow window, WindowManager.LayoutParams attrs,
+ int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
int lastSyncSeqId, ClientWindowFrames outFrames,
MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl,
InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,
Bundle outBundle) {
- if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
- + Binder.getCallingPid());
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
int res = mService.relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, flags, seq,
lastSyncSeqId, outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
outActiveControls, outBundle);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
- + Binder.getCallingPid());
return res;
}
@@ -301,10 +312,15 @@
public void relayoutAsync(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
int lastSyncSeqId) {
- relayout(window, attrs, requestedWidth, requestedHeight, viewFlags, flags, seq,
- lastSyncSeqId, null /* outFrames */, null /* mergedConfiguration */,
- null /* outSurfaceControl */, null /* outInsetsState */,
- null /* outActiveControls */, null /* outSyncIdBundle */);
+ if (windowSessionRelayoutInfo()) {
+ relayout(window, attrs, requestedWidth, requestedHeight, viewFlags, flags, seq,
+ lastSyncSeqId, null /* outRelayoutResult */);
+ } else {
+ relayoutLegacy(window, attrs, requestedWidth, requestedHeight, viewFlags, flags, seq,
+ lastSyncSeqId, null /* outFrames */, null /* mergedConfiguration */,
+ null /* outSurfaceControl */, null /* outInsetsState */,
+ null /* outActiveControls */, null /* outSyncIdBundle */);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9a7f87d..56e5d76 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -43,12 +43,10 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
import static android.view.SurfaceControl.METADATA_TASK_ID;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
@@ -171,12 +169,10 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
-import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.RemoteAnimationAdapter;
import android.view.Surface;
import android.view.SurfaceControl;
-import android.view.TaskTransitionSpec;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.window.ITaskOrganizer;
@@ -641,8 +637,6 @@
mLastTaskSnapshotData = _lastSnapshotData != null
? _lastSnapshotData
: new PersistedTaskSnapshotData();
- // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
- setOrientation(SCREEN_ORIENTATION_UNSET);
affinityIntent = _affinityIntent;
affinity = _affinity;
rootAffinity = _rootAffinity;
@@ -2942,33 +2936,6 @@
return;
}
- /**
- * Account for specified insets to crop the animation bounds by to avoid the animation
- * occurring over "out of bounds" regions
- *
- * For example this is used to make sure the tasks are cropped to be fully above the expanded
- * taskbar when animating.
- *
- * TEMPORARY FIELD (b/202383002)
- * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays
- * or when shell transitions are fully enabled
- *
- * @param animationBounds The animation bounds to adjust to account for the custom spec insets.
- */
- void adjustAnimationBoundsForTransition(Rect animationBounds) {
- TaskTransitionSpec spec = mWmService.mTaskTransitionSpec;
- if (spec != null) {
- final InsetsState state =
- getDisplayContent().getInsetsStateController().getRawInsetsState();
- for (int i = state.sourceSize() - 1; i >= 0; i--) {
- final InsetsSource source = state.sourceAt(i);
- if (source.hasFlags(FLAG_INSETS_ROUNDED_CORNER)) {
- animationBounds.inset(source.calculateVisibleInsets(animationBounds));
- }
- }
- }
- }
-
void setDragResizing(boolean dragResizing) {
if (mDragResizing != dragResizing) {
// No need to check if allowed if it's leaving dragResize
@@ -3691,6 +3658,9 @@
info.requestedVisibleTypes = topMainWin.getRequestedVisibleTypes();
}
}
+ final Rect rotatedBounds = activity.getFixedRotationTransformDisplayBounds();
+ info.taskBounds.set(rotatedBounds != null ? rotatedBounds
+ : info.taskInfo.configuration.windowConfiguration.getBounds());
// If the developer has persist a different configuration, we need to override it to the
// starting window because persisted configuration does not effect to Task.
info.taskInfo.configuration.setTo(activity.getConfiguration());
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 90ac576..d70ca02 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -44,7 +44,6 @@
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.AppTransition.isTaskTransitOld;
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;
@@ -72,7 +71,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
@@ -103,7 +101,6 @@
import android.view.SurfaceControl.Builder;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
-import android.view.TaskTransitionSpec;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
@@ -186,7 +183,7 @@
// The specified orientation for this window container.
// Shouldn't be accessed directly since subclasses can override getOverrideOrientation.
@ScreenOrientation
- private int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+ private int mOverrideOrientation = SCREEN_ORIENTATION_UNSET;
/**
* The window container which decides its orientation since the last time
@@ -1683,8 +1680,6 @@
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
- // TODO: Maybe mOverrideOrientation should default to SCREEN_ORIENTATION_UNSET vs.
- // SCREEN_ORIENTATION_UNSPECIFIED?
final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
if (orientation == SCREEN_ORIENTATION_BEHIND) {
@@ -1700,7 +1695,7 @@
continue;
}
- if (wc.providesOrientation() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
+ if (orientation != SCREEN_ORIENTATION_UNSPECIFIED || wc.providesOrientation()) {
// Use the orientation if the container can provide or requested an explicit
// orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
@@ -3148,9 +3143,6 @@
// Separate position and size for use in animators.
final Rect screenBounds = getAnimationBounds(appRootTaskClipMode);
mTmpRect.set(screenBounds);
- if (this.asTask() != null && isTaskTransitOld(transit)) {
- this.asTask().adjustAnimationBoundsForTransition(mTmpRect);
- }
getAnimationPosition(mTmpPoint);
mTmpRect.offsetTo(0, 0);
@@ -3285,10 +3277,6 @@
AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder();
- if (isTaskTransitOld(transit) && getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
- animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor());
- }
-
// Check if the animation requests to show background color for Activity and embedded
// TaskFragment.
final ActivityRecord activityRecord = asActivityRecord();
@@ -3342,18 +3330,6 @@
}
}
- private @ColorInt int getTaskAnimationBackgroundColor() {
- Context uiContext = mDisplayContent.getDisplayPolicy().getSystemUiContext();
- TaskTransitionSpec customSpec = mWmService.mTaskTransitionSpec;
- @ColorInt int defaultFallbackColor = uiContext.getColor(R.color.overview_background);
-
- if (customSpec != null && customSpec.backgroundColor != 0) {
- return customSpec.backgroundColor;
- }
-
- return defaultFallbackColor;
- }
-
final SurfaceAnimationRunner getSurfaceAnimationRunner() {
return mWmService.mSurfaceAnimationRunner;
}
@@ -3889,6 +3865,18 @@
return false;
}
+
+ /** @return {@code true} if this container wants to show wallpaper. */
+ boolean hasWallpaper() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer child = mChildren.get(i);
+ if (child.hasWallpaper()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Nullable
static WindowContainer fromBinder(IBinder binder) {
return RemoteToken.fromBinder(binder).getContainer();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index de7c0eb..feede01 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,7 +20,6 @@
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.INPUT_CONSUMER;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
-import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.MODIFY_TOUCH_MODE_STATE;
import static android.Manifest.permission.READ_FRAME_BUFFER;
@@ -295,7 +294,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
-import android.view.TaskTransitionSpec;
import android.view.View;
import android.view.View.FocusDirection;
import android.view.ViewDebug;
@@ -308,6 +306,7 @@
import android.view.WindowManager.RemoveContentMode;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
+import android.view.WindowRelayoutResult;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.VerifiedDisplayHash;
import android.view.inputmethod.ImeTracker;
@@ -349,6 +348,7 @@
import com.android.server.DisplayThread;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
@@ -454,13 +454,12 @@
/**
* Use WMShell for app transition.
*/
- public static final String ENABLE_SHELL_TRANSITIONS = "persist.wm.debug.shell_transit";
+ private static final String ENABLE_SHELL_TRANSITIONS = "persist.wm.debug.shell_transit";
/**
* @see #ENABLE_SHELL_TRANSITIONS
*/
- public static final boolean sEnableShellTransitions =
- SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, true);
+ public static final boolean sEnableShellTransitions = getShellTransitEnabled();
/**
* Allows a fullscreen windowing mode activity to launch in its desired orientation directly
@@ -762,11 +761,6 @@
*/
final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
- /**
- * Used during task transitions to allow SysUI and launcher to customize task transitions.
- */
- TaskTransitionSpec mTaskTransitionSpec;
-
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
@@ -2268,12 +2262,54 @@
}
}
+ /** Relayouts window. */
+ public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
+ int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
+ int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
+ final ClientWindowFrames outFrames;
+ final MergedConfiguration outMergedConfiguration;
+ final SurfaceControl outSurfaceControl;
+ final InsetsState outInsetsState;
+ final InsetsSourceControl.Array outActiveControls;
+ if (outRelayoutResult != null) {
+ outFrames = outRelayoutResult.frames;
+ outMergedConfiguration = outRelayoutResult.mergedConfiguration;
+ outSurfaceControl = outRelayoutResult.surfaceControl;
+ outInsetsState = outRelayoutResult.insetsState;
+ outActiveControls = outRelayoutResult.activeControls;
+ } else {
+ outFrames = null;
+ outMergedConfiguration = null;
+ outSurfaceControl = null;
+ outInsetsState = null;
+ outActiveControls = null;
+ }
+ return relayoutWindowInner(session, client, attrs, requestedWidth, requestedHeight,
+ viewVisibility, flags, seq, lastSyncSeqId, outFrames, outMergedConfiguration,
+ outSurfaceControl, outInsetsState, outActiveControls, null /* outBundle */,
+ outRelayoutResult);
+ }
+
+ /** @deprecated */
+ @Deprecated
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
int lastSyncSeqId, ClientWindowFrames outFrames,
MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl,
InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,
Bundle outBundle) {
+ return relayoutWindowInner(session, client, attrs, requestedWidth, requestedHeight,
+ viewVisibility, flags, seq, lastSyncSeqId, outFrames, outMergedConfiguration,
+ outSurfaceControl, outInsetsState, outActiveControls, outBundle,
+ null /* outRelayoutResult */);
+ }
+
+ private int relayoutWindowInner(Session session, IWindow client, LayoutParams attrs,
+ int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
+ int lastSyncSeqId, ClientWindowFrames outFrames,
+ MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl,
+ InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,
+ Bundle outBundle, WindowRelayoutResult outRelayoutResult) {
if (outActiveControls != null) {
outActiveControls.set(null);
}
@@ -2608,8 +2644,14 @@
}
if (outFrames != null && outMergedConfiguration != null) {
- final boolean shouldReportActivityWindowInfo = outBundle != null
- && win.mLastReportedActivityWindowInfo != null;
+ final boolean shouldReportActivityWindowInfo;
+ if (Flags.windowSessionRelayoutInfo()) {
+ shouldReportActivityWindowInfo = outRelayoutResult != null
+ && win.mLastReportedActivityWindowInfo != null;
+ } else {
+ shouldReportActivityWindowInfo = outBundle != null
+ && win.mLastReportedActivityWindowInfo != null;
+ }
final ActivityWindowInfo outActivityWindowInfo = shouldReportActivityWindowInfo
? new ActivityWindowInfo()
: null;
@@ -2618,8 +2660,13 @@
outActivityWindowInfo, false /* useLatestConfig */, shouldRelayout);
if (shouldReportActivityWindowInfo) {
- outBundle.putParcelable(IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO,
- outActivityWindowInfo);
+ if (Flags.windowSessionRelayoutInfo()) {
+ outRelayoutResult.activityWindowInfo = outActivityWindowInfo;
+ } else {
+ outBundle.putParcelable(
+ IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO,
+ outActivityWindowInfo);
+ }
}
// Set resize-handled here because the values are sent back to the client.
@@ -2650,7 +2697,19 @@
win.isVisible() /* visible */, false /* removed */);
}
- if (outBundle != null) {
+ if (Flags.windowSessionRelayoutInfo()) {
+ if (outRelayoutResult != null) {
+ if (win.syncNextBuffer() && viewVisibility == View.VISIBLE
+ && win.mSyncSeqId > lastSyncSeqId) {
+ outRelayoutResult.syncSeqId = win.shouldSyncWithBuffers()
+ ? win.mSyncSeqId
+ : -1;
+ win.markRedrawForSyncReported();
+ } else {
+ outRelayoutResult.syncSeqId = -1;
+ }
+ }
+ } else if (outBundle != null) {
final int maybeSyncSeqId;
if (win.syncNextBuffer() && viewVisibility == View.VISIBLE
&& win.mSyncSeqId > lastSyncSeqId) {
@@ -9866,24 +9925,6 @@
}
@Override
- public void setTaskTransitionSpec(TaskTransitionSpec spec) {
- if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "setTaskTransitionSpec()")) {
- throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
- }
-
- mTaskTransitionSpec = spec;
- }
-
- @Override
- public void clearTaskTransitionSpec() {
- if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "clearTaskTransitionSpec()")) {
- throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
- }
-
- mTaskTransitionSpec = null;
- }
-
- @Override
@RequiresPermission(Manifest.permission.ACCESS_FPS_COUNTER)
public void registerTaskFpsCallback(@IntRange(from = 0) int taskId,
ITaskFpsCallback callback) {
@@ -10230,4 +10271,13 @@
}
}
}
+
+ private static boolean getShellTransitEnabled() {
+ android.content.pm.FeatureInfo autoFeature = SystemConfig.getInstance()
+ .getAvailableFeatures().get(PackageManager.FEATURE_AUTOMOTIVE);
+ if (autoFeature != null && autoFeature.version >= 0) {
+ return SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, true);
+ }
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index d91a211..fd1b5be 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -110,9 +110,9 @@
private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
- private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 50;
+ private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 200;
private static final long RAPID_ACTIVITY_LAUNCH_MS = 500;
- private static final long RESET_RAPID_ACTIVITY_LAUNCH_MS = 5 * RAPID_ACTIVITY_LAUNCH_MS;
+ private static final long RESET_RAPID_ACTIVITY_LAUNCH_MS = 3 * RAPID_ACTIVITY_LAUNCH_MS;
public static final int STOPPED_STATE_NOT_STOPPED = 0;
public static final int STOPPED_STATE_FIRST_LAUNCH = 1;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2fcee50..c25080f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3092,12 +3092,13 @@
}
void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) {
+ final int baseType = getBaseType();
if (mSession.mCanAddInternalSystemWindow
- || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
+ || (!isSystemAlertWindowType(baseType) && baseType != TYPE_TOAST)) {
return;
}
- if (mAttrs.type == TYPE_APPLICATION_OVERLAY && mAttrs.isSystemApplicationOverlay()
+ if (baseType == TYPE_APPLICATION_OVERLAY && mAttrs.isSystemApplicationOverlay()
&& mSession.mCanCreateSystemApplicationOverlay) {
return;
}
@@ -5857,6 +5858,7 @@
return hasWallpaper();
}
+ @Override
boolean hasWallpaper() {
return (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0 || hasWallpaperForLetterboxBackground();
}
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 25c5db1..64cbb0d1 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -12,6 +12,7 @@
per-file com_android_server_Usb* = file:/services/usb/OWNERS
per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
per-file com_android_server_accessibility_* = file:/services/accessibility/OWNERS
+per-file com_android_server_adb_* = file:/services/core/java/com/android/server/adb/OWNERS
per-file com_android_server_display_* = file:/services/core/java/com/android/server/display/OWNERS
per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
per-file com_android_server_lights_* = file:/services/core/java/com/android/server/lights/OWNERS
diff --git a/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp b/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
index 9c834aa..c7b6852 100644
--- a/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
+++ b/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
@@ -18,58 +18,22 @@
#define LOG_NDEBUG 0
-#include <algorithm>
#include <condition_variable>
#include <mutex>
#include <optional>
-#include <random>
-#include <string>
-#include <vector>
#include <adb/pairing/pairing_server.h>
#include <android-base/properties.h>
-#include <utils/Log.h>
-
+#include <jni.h>
#include <nativehelper/JNIHelp.h>
-#include "jni.h"
+#include <nativehelper/utils.h>
+#include <utils/Log.h>
namespace android {
// ----------------------------------------------------------------------------
namespace {
-template <class T, class N>
-class JSmartWrapper {
-public:
- JSmartWrapper(JNIEnv* env, T* jData) : mEnv(env), mJData(jData) {}
-
- virtual ~JSmartWrapper() = default;
-
- const N* data() const { return mRawData; }
-
- jsize size() const { return mSize; }
-
-protected:
- N* mRawData = nullptr;
- JNIEnv* mEnv = nullptr;
- T* mJData = nullptr;
- jsize mSize = 0;
-}; // JSmartWrapper
-
-class JStringUTFWrapper : public JSmartWrapper<jstring, const char> {
-public:
- explicit JStringUTFWrapper(JNIEnv* env, jstring* str) : JSmartWrapper(env, str) {
- mRawData = env->GetStringUTFChars(*str, NULL);
- mSize = env->GetStringUTFLength(*str);
- }
-
- virtual ~JStringUTFWrapper() {
- if (data()) {
- mEnv->ReleaseStringUTFChars(*mJData, mRawData);
- }
- }
-}; // JStringUTFWrapper
-
struct ServerDeleter {
void operator()(PairingServerCtx* p) { pairing_server_destroy(p); }
};
@@ -97,19 +61,19 @@
std::unique_ptr<PairingResultWaiter> sWaiter;
} // namespace
-static jint native_pairing_start(JNIEnv* env, jobject thiz, jstring guid, jstring password) {
+static jint native_pairing_start(JNIEnv* env, jobject thiz, jstring javaGuid, jstring javaPassword) {
// Server-side only sends its GUID on success.
- PeerInfo system_info = {};
- system_info.type = ADB_DEVICE_GUID;
- JStringUTFWrapper guidWrapper(env, &guid);
- memcpy(system_info.data, guidWrapper.data(), guidWrapper.size());
+ PeerInfo system_info = { .type = ADB_DEVICE_GUID };
- JStringUTFWrapper passwordWrapper(env, &password);
+ ScopedUtfChars guid = GET_UTF_OR_RETURN(env, javaGuid);
+ memcpy(system_info.data, guid.c_str(), guid.size());
+
+ ScopedUtfChars password = GET_UTF_OR_RETURN(env, javaPassword);
// Create the pairing server
sServer = PairingServerPtr(
- pairing_server_new_no_cert(reinterpret_cast<const uint8_t*>(passwordWrapper.data()),
- passwordWrapper.size(), &system_info, 0));
+ pairing_server_new_no_cert(reinterpret_cast<const uint8_t*>(password.c_str()),
+ password.size(), &system_info, 0));
sWaiter.reset(new PairingResultWaiter);
uint16_t port = pairing_server_start(sServer.get(), sWaiter->ResultCallback, sWaiter.get());
@@ -137,11 +101,16 @@
return JNI_FALSE;
}
- std::string peer_public_key = reinterpret_cast<char*>(sWaiter->peer_info_.data);
- // Write to PairingThread's member variables
+ // Create a Java string for the public key.
+ char* peer_public_key = reinterpret_cast<char*>(sWaiter->peer_info_.data);
+ jstring jpublickey = env->NewStringUTF(peer_public_key);
+ if (jpublickey == nullptr) {
+ return JNI_FALSE;
+ }
+
+ // Write to PairingThread.mPublicKey.
jclass clazz = env->GetObjectClass(thiz);
jfieldID mPublicKey = env->GetFieldID(clazz, "mPublicKey", "Ljava/lang/String;");
- jstring jpublickey = env->NewStringUTF(peer_public_key.c_str());
env->SetObjectField(thiz, mPublicKey, jpublickey);
return JNI_TRUE;
}
@@ -157,12 +126,9 @@
};
int register_android_server_AdbDebuggingManager(JNIEnv* env) {
- int res = jniRegisterNativeMethods(env,
- "com/android/server/adb/AdbDebuggingManager$PairingThread",
- gPairingThreadMethods, NELEM(gPairingThreadMethods));
- (void)res; // Faked use when LOG_NDEBUG.
- LOG_FATAL_IF(res < 0, "Unable to register native methods.");
- return 0;
+ return jniRegisterNativeMethods(env,
+ "com/android/server/adb/AdbDebuggingManager$PairingThread",
+ gPairingThreadMethods, NELEM(gPairingThreadMethods));
}
} /* namespace android */
diff --git a/services/core/jni/com_android_server_utils_AnrTimer.cpp b/services/core/jni/com_android_server_utils_AnrTimer.cpp
index da95666..6509958 100644
--- a/services/core/jni/com_android_server_utils_AnrTimer.cpp
+++ b/services/core/jni/com_android_server_utils_AnrTimer.cpp
@@ -161,14 +161,14 @@
// A timer has expired.
void expire(timer_id_t);
- // Dump a small amount of state to the log file.
- void dump(bool verbose) const;
-
// Return the Java object associated with this instance.
jweak jtimer() const {
return notifierObject_;
}
+ // Return the per-instance statistics.
+ std::vector<std::string> getDump() const;
+
private:
// The service cannot be copied.
AnrTimerService(AnrTimerService const &) = delete;
@@ -199,7 +199,7 @@
std::set<Timer> running_;
// The maximum number of active timers.
- size_t maxActive_;
+ size_t maxRunning_;
// Simple counters
struct Counters {
@@ -209,6 +209,7 @@
size_t accepted;
size_t discarded;
size_t expired;
+ size_t extended;
// The number of times there were zero active timers.
size_t drained;
@@ -437,7 +438,9 @@
// Construct the ticker. This creates the timerfd file descriptor and starts the monitor
// thread. The monitor thread is given a unique name.
- Ticker() {
+ Ticker() :
+ id_(idGen_.fetch_add(1))
+ {
timerFd_ = timer_create();
if (timerFd_ < 0) {
ALOGE("failed to create timerFd: %s", strerror(errno));
@@ -502,6 +505,11 @@
}
}
+ // The unique ID of this particular ticker. Used for debug and logging.
+ size_t id() const {
+ return id_;
+ }
+
// Return the number of timers still running.
size_t running() const {
AutoMutex _l(lock_);
@@ -617,8 +625,16 @@
// The list of timers that are scheduled. This set is sorted by timeout and then by timer
// ID. A set is sufficient (as opposed to a multiset) because timer IDs are unique.
std::set<Entry> running_;
+
+ // A unique ID assigned to this instance.
+ const size_t id_;
+
+ // The ID generator.
+ static std::atomic<size_t> idGen_;
};
+std::atomic<size_t> AnrTimerService::Ticker::idGen_;
+
AnrTimerService::AnrTimerService(char const* label,
notifier_t notifier, void* cookie, jweak jtimer, Ticker* ticker) :
@@ -629,7 +645,7 @@
ticker_(ticker) {
// Zero the statistics
- maxActive_ = 0;
+ maxRunning_ = 0;
memset(&counters_, 0, sizeof(counters_));
ALOGI_IF(DEBUG, "initialized %s", label);
@@ -739,6 +755,12 @@
elapsed = now() - t.started;
}
+ if (expired) {
+ counters_.expired++;
+ } else {
+ counters_.extended++;
+ }
+
// Deliver the notification outside of the lock.
if (expired) {
if (!notifier_(timerId, pid, uid, elapsed, notifierCookie_, notifierObject_)) {
@@ -756,8 +778,8 @@
if (t.status == Running) {
// Only forward running timers to the ticker. Expired timers are handled separately.
ticker_->insert(t.scheduled, t.id, this);
- maxActive_ = std::max(maxActive_, running_.size());
}
+ maxRunning_ = std::max(maxRunning_, running_.size());
}
AnrTimerService::Timer AnrTimerService::remove(timer_id_t timerId) {
@@ -767,29 +789,32 @@
Timer result = *found;
running_.erase(found);
ticker_->remove(result.scheduled, result.id);
+ if (running_.size() == 0) counters_.drained++;
return result;
}
return Timer();
}
-void AnrTimerService::dump(bool verbose) const {
+std::vector<std::string> AnrTimerService::getDump() const {
+ std::vector<std::string> r;
AutoMutex _l(lock_);
- ALOGI("timer %s ops started=%zu canceled=%zu accepted=%zu discarded=%zu expired=%zu",
- label_.c_str(),
- counters_.started, counters_.canceled, counters_.accepted,
- counters_.discarded, counters_.expired);
- ALOGI("timer %s stats max-active=%zu/%zu running=%zu/%zu errors=%zu",
- label_.c_str(),
- maxActive_, ticker_->maxRunning(), running_.size(), ticker_->running(),
- counters_.error);
-
- if (verbose) {
- nsecs_t time = now();
- for (auto i = running_.begin(); i != running_.end(); i++) {
- Timer t = *i;
- ALOGI(" running %s", t.toString(time).c_str());
- }
- }
+ r.push_back(StringPrintf("started:%zu canceled:%zu accepted:%zu discarded:%zu expired:%zu",
+ counters_.started,
+ counters_.canceled,
+ counters_.accepted,
+ counters_.discarded,
+ counters_.expired));
+ r.push_back(StringPrintf("extended:%zu drained:%zu error:%zu running:%zu maxRunning:%zu",
+ counters_.extended,
+ counters_.drained,
+ counters_.error,
+ running_.size(),
+ maxRunning_));
+ r.push_back(StringPrintf("ticker:%zu ticking:%zu maxTicking:%zu",
+ ticker_->id(),
+ ticker_->running(),
+ ticker_->maxRunning()));
+ return r;
}
/**
@@ -894,21 +919,26 @@
return toService(ptr)->discard(timerId);
}
-jint anrTimerDump(JNIEnv *env, jclass, jlong ptr, jboolean verbose) {
- if (!nativeSupportEnabled) return -1;
- toService(ptr)->dump(verbose);
- return 0;
+jobjectArray anrTimerDump(JNIEnv *env, jclass, jlong ptr) {
+ if (!nativeSupportEnabled) return nullptr;
+ std::vector<std::string> stats = toService(ptr)->getDump();
+ jclass sclass = env->FindClass("java/lang/String");
+ jobjectArray r = env->NewObjectArray(stats.size(), sclass, nullptr);
+ for (size_t i = 0; i < stats.size(); i++) {
+ env->SetObjectArrayElement(r, i, env->NewStringUTF(stats[i].c_str()));
+ }
+ return r;
}
static const JNINativeMethod methods[] = {
{"nativeAnrTimerSupported", "()Z", (void*) anrTimerSupported},
- {"nativeAnrTimerCreate", "(Ljava/lang/String;)J", (void*) anrTimerCreate},
- {"nativeAnrTimerClose", "(J)I", (void*) anrTimerClose},
- {"nativeAnrTimerStart", "(JIIJZ)I", (void*) anrTimerStart},
- {"nativeAnrTimerCancel", "(JI)Z", (void*) anrTimerCancel},
- {"nativeAnrTimerAccept", "(JI)Z", (void*) anrTimerAccept},
- {"nativeAnrTimerDiscard", "(JI)Z", (void*) anrTimerDiscard},
- {"nativeAnrTimerDump", "(JZ)V", (void*) anrTimerDump},
+ {"nativeAnrTimerCreate", "(Ljava/lang/String;)J", (void*) anrTimerCreate},
+ {"nativeAnrTimerClose", "(J)I", (void*) anrTimerClose},
+ {"nativeAnrTimerStart", "(JIIJZ)I", (void*) anrTimerStart},
+ {"nativeAnrTimerCancel", "(JI)Z", (void*) anrTimerCancel},
+ {"nativeAnrTimerAccept", "(JI)Z", (void*) anrTimerAccept},
+ {"nativeAnrTimerDiscard", "(JI)Z", (void*) anrTimerDiscard},
+ {"nativeAnrTimerDump", "(J)[Ljava/lang/String;", (void*) anrTimerDump},
};
} // anonymous namespace
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6458eac..85ab562 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -666,15 +666,6 @@
DELEGATION_CERT_SELECTION,
});
- /**
- * System property whose value indicates whether the device is fully owned by an organization:
- * it can be either a device owner device, or a device with an organization-owned managed
- * profile.
- *
- * <p>The state is stored as a Boolean string.
- */
- private static final String PROPERTY_ORGANIZATION_OWNED = "ro.organization_owned";
-
private static final int STATUS_BAR_DISABLE_MASK =
StatusBarManager.DISABLE_EXPAND |
StatusBarManager.DISABLE_NOTIFICATION_ICONS |
@@ -2356,7 +2347,6 @@
void loadOwners() {
synchronized (getLockObject()) {
mOwners.load();
- setDeviceOwnershipSystemPropertyLocked();
if (mOwners.hasDeviceOwner()) {
setGlobalSettingDeviceOwnerType(
mOwners.getDeviceOwnerType(mOwners.getDeviceOwnerPackageName()));
@@ -2720,27 +2710,6 @@
+ defaultRestrictions);
}
- private void setDeviceOwnershipSystemPropertyLocked() {
- final boolean deviceProvisioned =
- mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- final boolean hasDeviceOwner = mOwners.hasDeviceOwner();
- final boolean hasOrgOwnedProfile = isOrganizationOwnedDeviceWithManagedProfile();
- // If the device is not provisioned and there is currently no management, do not set the
- // read-only system property yet, since device owner / org-owned profile may still be
- // provisioned.
- if (!hasDeviceOwner && !hasOrgOwnedProfile && !deviceProvisioned) {
- return;
- }
- final String value = Boolean.toString(hasDeviceOwner || hasOrgOwnedProfile);
- final String currentVal = mInjector.systemPropertiesGet(PROPERTY_ORGANIZATION_OWNED, null);
- if (TextUtils.isEmpty(currentVal)) {
- Slogf.i(LOG_TAG, "Set ro.organization_owned property to " + value);
- mInjector.systemPropertiesSet(PROPERTY_ORGANIZATION_OWNED, value);
- } else if (!value.equals(currentVal)) {
- Slogf.w(LOG_TAG, "Cannot change existing ro.organization_owned to " + value);
- }
- }
-
private void maybeStartSecurityLogMonitorOnActivityManagerReady() {
if (!mInjector.securityLogIsLoggingEnabled()) {
return;
@@ -9447,7 +9416,6 @@
mOwners.setDeviceOwner(admin, userId);
mOwners.writeDeviceOwner();
- setDeviceOwnershipSystemPropertyLocked();
//TODO(b/180371154): when provisionFullyManagedDevice is used in tests, remove this
// hard-coded default value setting.
@@ -15303,8 +15271,6 @@
private class SetupContentObserver extends ContentObserver {
private final Uri mUserSetupComplete = Settings.Secure.getUriFor(
Settings.Secure.USER_SETUP_COMPLETE);
- private final Uri mDeviceProvisioned = Settings.Global.getUriFor(
- Settings.Global.DEVICE_PROVISIONED);
private final Uri mPaired = Settings.Secure.getUriFor(Settings.Secure.DEVICE_PAIRED);
private final Uri mDefaultImeChanged = Settings.Secure.getUriFor(
Settings.Secure.DEFAULT_INPUT_METHOD);
@@ -15318,7 +15284,6 @@
void register() {
mInjector.registerContentObserver(mUserSetupComplete, false, this, UserHandle.USER_ALL);
- mInjector.registerContentObserver(mDeviceProvisioned, false, this, UserHandle.USER_ALL);
if (mIsWatch) {
mInjector.registerContentObserver(mPaired, false, this, UserHandle.USER_ALL);
}
@@ -15334,12 +15299,6 @@
public void onChange(boolean selfChange, Uri uri, int userId) {
if (mUserSetupComplete.equals(uri) || (mIsWatch && mPaired.equals(uri))) {
updateUserSetupCompleteAndPaired();
- } else if (mDeviceProvisioned.equals(uri)) {
- synchronized (getLockObject()) {
- // Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
- // is delayed until device is marked as provisioned.
- setDeviceOwnershipSystemPropertyLocked();
- }
} else if (mDefaultImeChanged.equals(uri)) {
synchronized (getLockObject()) {
if (mUserIdsWithPendingChangesByOwner.contains(userId)) {
@@ -21651,7 +21610,8 @@
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
}
- if (Flags.headlessSingleUserFixes() && isSingleUserMode && !mInjector.isChangeEnabled(
+ if (Flags.headlessSingleUserFixes() && mInjector.userManagerIsHeadlessSystemUserMode()
+ && isSingleUserMode && !mInjector.isChangeEnabled(
PROVISION_SINGLE_USER_MODE, deviceAdmin.getPackageName(), caller.getUserId())) {
throw new IllegalStateException("Device admin is not targeting Android V.");
}
@@ -21670,7 +21630,7 @@
setLocale(provisioningParams.getLocale());
int deviceOwnerUserId = Flags.headlessDeviceOwnerSingleUserEnabled()
- && isSingleUserMode
+ && isSingleUserMode && mInjector.userManagerIsHeadlessSystemUserMode()
? mUserManagerInternal.getMainUserId() : UserHandle.USER_SYSTEM;
if (!removeNonRequiredAppsForManagedDevice(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
index a0d9be54..eeb4976 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
@@ -16,6 +16,9 @@
package com.android.server.devicepolicy;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -185,6 +188,9 @@
}
}
+ // TODO: when a local policy exists for a user, this callback will be invoked for this user
+ // individually as well as for USER_ALL. This can be optimized by separating local and global
+ // enforcement in the policy engine.
static boolean setUserControlDisabledPackages(
@Nullable Set<String> packages, Context context, int userId, PolicyKey policyKey) {
Binder.withCleanCallingIdentity(() -> {
@@ -201,20 +207,35 @@
return;
}
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
- for (var pkg : packages) {
- final var appInfo = pmi.getApplicationInfo(pkg,
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- Process.myUid(), userId);
- if (appInfo != null) {
- DevicePolicyManagerService.setBgUsageAppOp(appOpsManager, appInfo);
- }
- }
+ resolveUsers(userId).forEach(
+ user -> setBgUsageAppOp(packages, pmi, user, appOpsManager));
}
});
return true;
}
+ /** Handles USER_ALL expanding it into the list of all intact users. */
+ private static List<Integer> resolveUsers(int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
+ return userManager.getUsers(/* excludeDying= */ true)
+ .stream().map(ui -> ui.id).toList();
+ } else {
+ return List.of(userId);
+ }
+ }
+
+ private static void setBgUsageAppOp(Set<String> packages, PackageManagerInternal pmi,
+ int userId, AppOpsManager appOpsManager) {
+ for (var pkg : packages) {
+ int packageFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
+ final var appInfo = pmi.getApplicationInfo(pkg, packageFlags, Process.myUid(), userId);
+ if (appInfo != null) {
+ DevicePolicyManagerService.setBgUsageAppOp(appOpsManager, appInfo);
+ }
+ }
+ }
+
static boolean addPersistentPreferredActivity(
@Nullable ComponentName preferredActivity, @NonNull Context context, int userId,
@NonNull PolicyKey policyKey) {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt
new file mode 100644
index 0000000..f0abcd2
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.mode
+
+import android.content.Context
+import android.util.SparseArray
+import android.view.Display
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.SmallTest
+import com.android.server.display.feature.DisplayManagerFlags
+import com.android.server.display.mode.DisplayModeDirector.DisplayDeviceConfigProvider
+import com.android.server.display.mode.RefreshRateVote.RenderVote
+import com.android.server.testutils.TestHandler
+import com.google.common.truth.Truth.assertThat
+import com.google.testing.junit.testparameterinjector.TestParameter
+import com.google.testing.junit.testparameterinjector.TestParameterInjector
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(TestParameterInjector::class)
+class AppRequestObserverTest {
+
+ private lateinit var context: Context
+ private val mockInjector = mock<DisplayModeDirector.Injector>()
+ private val mockFlags = mock<DisplayManagerFlags>()
+ private val mockDisplayDeviceConfigProvider = mock<DisplayDeviceConfigProvider>()
+ private val testHandler = TestHandler(null)
+
+ @Before
+ fun setUp() {
+ context = ApplicationProvider.getApplicationContext()
+ }
+
+ @Test
+ fun `test app request votes`(@TestParameter testCase: AppRequestTestCase) {
+ whenever(mockFlags.ignoreAppPreferredRefreshRateRequest())
+ .thenReturn(testCase.ignoreRefreshRateRequest)
+ val displayModeDirector = DisplayModeDirector(
+ context, testHandler, mockInjector, mockFlags, mockDisplayDeviceConfigProvider)
+ val modes = arrayOf(
+ Display.Mode(1, 1000, 1000, 60f),
+ Display.Mode(2, 1000, 1000, 90f),
+ Display.Mode(3, 1000, 1000, 120f)
+ )
+ displayModeDirector.injectSupportedModesByDisplay(SparseArray<Array<Display.Mode>>().apply {
+ append(Display.DEFAULT_DISPLAY, modes)
+ })
+ displayModeDirector.injectDefaultModeByDisplay(SparseArray<Display.Mode>().apply {
+ append(Display.DEFAULT_DISPLAY, modes[0])
+ })
+
+ displayModeDirector.appRequestObserver.setAppRequest(Display.DEFAULT_DISPLAY,
+ testCase.modeId,
+ testCase.requestedRefreshRates,
+ testCase.requestedMinRefreshRates,
+ testCase.requestedMaxRefreshRates)
+
+ val baseModeVote = displayModeDirector.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE)
+ assertThat(baseModeVote).isEqualTo(testCase.expectedBaseModeVote)
+
+ val sizeVote = displayModeDirector.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_APP_REQUEST_SIZE)
+ assertThat(sizeVote).isEqualTo(testCase.expectedSizeVote)
+
+ val renderRateVote = displayModeDirector.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE)
+ assertThat(renderRateVote).isEqualTo(testCase.expectedRenderRateVote)
+ }
+
+ enum class AppRequestTestCase(
+ val ignoreRefreshRateRequest: Boolean,
+ val modeId: Int,
+ val requestedRefreshRates: Float,
+ val requestedMinRefreshRates: Float,
+ val requestedMaxRefreshRates: Float,
+ internal val expectedBaseModeVote: Vote?,
+ internal val expectedSizeVote: Vote?,
+ internal val expectedRenderRateVote: Vote?,
+ ) {
+ BASE_MODE_60(true, 1, 0f, 0f, 0f,
+ BaseModeRefreshRateVote(60f), SizeVote(1000, 1000, 1000, 1000), null),
+ BASE_MODE_90(true, 2, 0f, 0f, 0f,
+ BaseModeRefreshRateVote(90f), SizeVote(1000, 1000, 1000, 1000), null),
+ MIN_REFRESH_RATE_60(true, 0, 0f, 60f, 0f,
+ null, null, RenderVote(60f, Float.POSITIVE_INFINITY)),
+ MIN_REFRESH_RATE_120(true, 0, 0f, 120f, 0f,
+ null, null, RenderVote(120f, Float.POSITIVE_INFINITY)),
+ MAX_REFRESH_RATE_60(true, 0, 0f, 0f, 60f,
+ null, null, RenderVote(0f, 60f)),
+ MAX_REFRESH_RATE_120(true, 0, 0f, 0f, 120f,
+ null, null, RenderVote(0f, 120f)),
+ INVALID_MIN_MAX_REFRESH_RATE(true, 0, 0f, 90f, 60f,
+ null, null, null),
+ BASE_MODE_MIN_MAX(true, 1, 0f, 60f, 90f,
+ BaseModeRefreshRateVote(60f), SizeVote(1000, 1000, 1000, 1000), RenderVote(60f, 90f)),
+ PREFERRED_REFRESH_RATE(false, 0, 60f, 0f, 0f,
+ BaseModeRefreshRateVote(60f), SizeVote(1000, 1000, 1000, 1000), null),
+ PREFERRED_REFRESH_RATE_IGNORED(true, 0, 60f, 0f, 0f,
+ null, null, null),
+ PREFERRED_REFRESH_RATE_INVALID(false, 0, 45f, 0f, 0f,
+ null, null, null),
+ }
+}
\ No newline at end of file
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index a2a4773..cd1e9e8 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -31,7 +31,6 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -78,7 +77,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.IdleScreenRefreshRateConfig;
import android.view.SurfaceControl.RefreshRateRange;
-import android.view.SurfaceControl.RefreshRateRanges;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
@@ -843,61 +841,6 @@
assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(expectedAppRequestedRefreshRate);
}
- void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps,
- float peakFps, float defaultFps, RefreshRateRanges primary,
- RefreshRateRanges appRequest) {
- DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings(
- minFps, peakFps, defaultFps);
- assertThat(specs.primary).isEqualTo(primary);
- assertThat(specs.appRequest).isEqualTo(appRequest);
- }
-
- @Test
- public void testSpecsFromRefreshRateSettings() {
- // Confirm that, with varying settings for min, peak, and default refresh rate,
- // DesiredDisplayModeSpecs is calculated correctly.
- float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f};
- DisplayModeDirector director =
- createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0);
-
- float inf = Float.POSITIVE_INFINITY;
- RefreshRateRange rangeAll = new RefreshRateRange(0, inf);
- RefreshRateRange range0to60 = new RefreshRateRange(0, 60);
- RefreshRateRange range0to90 = new RefreshRateRange(0, 90);
- RefreshRateRange range0to120 = new RefreshRateRange(0, 120);
- RefreshRateRange range60to90 = new RefreshRateRange(60, 90);
- RefreshRateRange range90to90 = new RefreshRateRange(90, 90);
- RefreshRateRange range90to120 = new RefreshRateRange(90, 120);
- RefreshRateRange range60toInf = new RefreshRateRange(60, inf);
- RefreshRateRange range90toInf = new RefreshRateRange(90, inf);
-
- RefreshRateRanges frameRateAll = new RefreshRateRanges(rangeAll, rangeAll);
- RefreshRateRanges frameRate90toInf = new RefreshRateRanges(range90toInf, range90toInf);
- RefreshRateRanges frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60);
- RefreshRateRanges frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90);
- RefreshRateRanges frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120);
- RefreshRateRanges frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90);
- RefreshRateRanges frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90);
- RefreshRateRanges frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120);
-
- verifySpecsWithRefreshRateSettings(director, 0, 0, 0, frameRateAll, frameRateAll);
- verifySpecsWithRefreshRateSettings(director, 0, 0, 90, frameRate0to90, frameRateAll);
- verifySpecsWithRefreshRateSettings(director, 0, 90, 0, frameRate0to90, frameRate0to90);
- verifySpecsWithRefreshRateSettings(director, 0, 90, 60, frameRate0to60, frameRate0to90);
- verifySpecsWithRefreshRateSettings(director, 0, 90, 120, frameRate0to90,
- frameRate0to90);
- verifySpecsWithRefreshRateSettings(director, 90, 0, 0, frameRate90toInf, frameRateAll);
- verifySpecsWithRefreshRateSettings(director, 90, 0, 120, frameRate90to120,
- frameRateAll);
- verifySpecsWithRefreshRateSettings(director, 90, 0, 60, frameRate90toInf, frameRateAll);
- verifySpecsWithRefreshRateSettings(director, 90, 120, 0, frameRate90to120,
- frameRate0to120);
- verifySpecsWithRefreshRateSettings(director, 90, 60, 0, frameRate90to90,
- frameRate0to90);
- verifySpecsWithRefreshRateSettings(director, 60, 120, 90, frameRate60to90,
- frameRate0to120);
- }
-
void verifyBrightnessObserverCall(DisplayModeDirector director, float minFps, float peakFps,
float defaultFps, float brightnessObserverMin, float brightnessObserverMax) {
BrightnessObserver brightnessObserver = mock(BrightnessObserver.class);
@@ -2318,162 +2261,6 @@
}
@Test
- public void testAppRequestObserver_modeId() {
- DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 0, 0);
-
- Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(BaseModeRefreshRateVote.class);
- BaseModeRefreshRateVote baseModeVote = (BaseModeRefreshRateVote) vote;
- assertThat(baseModeVote.mAppRequestBaseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(SizeVote.class);
- SizeVote sizeVote = (SizeVote) vote;
- assertThat(sizeVote.mHeight).isEqualTo(1000);
- assertThat(sizeVote.mWidth).isEqualTo(1000);
- assertThat(sizeVote.mMinHeight).isEqualTo(1000);
- assertThat(sizeVote.mMinWidth).isEqualTo(1000);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNull(vote);
-
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 90, 0, 0);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(BaseModeRefreshRateVote.class);
- baseModeVote = (BaseModeRefreshRateVote) vote;
- assertThat(baseModeVote.mAppRequestBaseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(90);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(SizeVote.class);
- sizeVote = (SizeVote) vote;
- assertThat(sizeVote.mHeight).isEqualTo(1000);
- assertThat(sizeVote.mWidth).isEqualTo(1000);
- assertThat(sizeVote.mMinHeight).isEqualTo(1000);
- assertThat(sizeVote.mMinWidth).isEqualTo(1000);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNull(vote);
- }
-
- @Test
- public void testAppRequestObserver_minRefreshRate() {
- DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 60, 0);
- Vote appRequestRefreshRate =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNull(appRequestRefreshRate);
-
- Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNull(appRequestSize);
-
- Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(RefreshRateVote.RenderVote.class);
- RefreshRateVote.RenderVote renderVote = (RefreshRateVote.RenderVote) vote;
- assertThat(renderVote.mMinRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(renderVote.mMaxRefreshRate).isAtLeast(90);
-
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 90, 0);
- appRequestRefreshRate =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNull(appRequestRefreshRate);
-
- appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNull(appRequestSize);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(RefreshRateVote.RenderVote.class);
- renderVote = (RefreshRateVote.RenderVote) vote;
- assertThat(renderVote.mMinRefreshRate).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(renderVote.mMaxRefreshRate).isAtLeast(90);
- }
-
- @Test
- public void testAppRequestObserver_maxRefreshRate() {
- DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 0, 90);
- Vote appRequestRefreshRate =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNull(appRequestRefreshRate);
-
- Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNull(appRequestSize);
-
- Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(RefreshRateVote.RenderVote.class);
- RefreshRateVote.RenderVote renderVote = (RefreshRateVote.RenderVote) vote;
- assertThat(renderVote.mMinRefreshRate).isZero();
- assertThat(renderVote.mMaxRefreshRate).isWithin(FLOAT_TOLERANCE).of(90);
-
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 0, 60);
- appRequestRefreshRate =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNull(appRequestRefreshRate);
-
- appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNull(appRequestSize);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(RefreshRateVote.RenderVote.class);
- renderVote = (RefreshRateVote.RenderVote) vote;
- assertThat(renderVote.mMinRefreshRate).isZero();
- assertThat(renderVote.mMaxRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
- }
-
- @Test
- public void testAppRequestObserver_invalidRefreshRateRange() {
- DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 90, 60);
- Vote appRequestRefreshRate =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNull(appRequestRefreshRate);
-
- Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNull(appRequestSize);
-
- Vote appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNull(appRequestRefreshRateRange);
- }
-
- @Test
- public void testAppRequestObserver_modeIdAndRefreshRateRange() {
- DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
- director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 90, 90);
-
- Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(BaseModeRefreshRateVote.class);
- BaseModeRefreshRateVote baseModeVote = (BaseModeRefreshRateVote) vote;
- assertThat(baseModeVote.mAppRequestBaseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(SizeVote.class);
- SizeVote sizeVote = (SizeVote) vote;
- assertThat(sizeVote.mHeight).isEqualTo(1000);
- assertThat(sizeVote.mWidth).isEqualTo(1000);
- assertThat(sizeVote.mMinHeight).isEqualTo(1000);
- assertThat(sizeVote.mMinWidth).isEqualTo(1000);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
- assertNotNull(vote);
- assertThat(vote).isInstanceOf(RefreshRateVote.RenderVote.class);
- RefreshRateVote.RenderVote renderVote = (RefreshRateVote.RenderVote) vote;
- assertThat(renderVote.mMinRefreshRate).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(renderVote.mMaxRefreshRate).isWithin(FLOAT_TOLERANCE).of(90);
- }
-
- @Test
public void testAppRequestsIsTheDefaultMode() {
Display.Mode[] modes = new Display.Mode[2];
modes[0] = new Display.Mode(
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
index 3c87261..4d910ce 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
@@ -21,6 +21,8 @@
import android.provider.Settings
import android.util.SparseArray
import android.view.Display
+import android.view.SurfaceControl.RefreshRateRange
+import android.view.SurfaceControl.RefreshRateRanges
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.SmallTest
import com.android.internal.util.test.FakeSettingsProvider
@@ -29,6 +31,7 @@
import com.android.server.display.mode.DisplayModeDirector.DisplayDeviceConfigProvider
import com.android.server.testutils.TestHandler
import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
import com.google.testing.junit.testparameterinjector.TestParameter
import com.google.testing.junit.testparameterinjector.TestParameterInjector
import org.junit.Before
@@ -40,6 +43,32 @@
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
+private val RANGE_NO_LIMIT = RefreshRateRange(0f, Float.POSITIVE_INFINITY)
+private val RANGE_0_60 = RefreshRateRange(0f, 60f)
+private val RANGE_0_90 = RefreshRateRange(0f, 90f)
+private val RANGE_0_120 = RefreshRateRange(0f, 120f)
+private val RANGE_60_90 = RefreshRateRange(60f, 90f)
+private val RANGE_60_120 = RefreshRateRange(60f, 120f)
+private val RANGE_60_INF = RefreshRateRange(60f, Float.POSITIVE_INFINITY)
+private val RANGE_90_90 = RefreshRateRange(90f, 90f)
+private val RANGE_90_120 = RefreshRateRange(90f, 120f)
+private val RANGE_90_INF = RefreshRateRange(90f, Float.POSITIVE_INFINITY)
+
+private val RANGES_NO_LIMIT = RefreshRateRanges(RANGE_NO_LIMIT, RANGE_NO_LIMIT)
+private val RANGES_NO_LIMIT_60 = RefreshRateRanges(RANGE_NO_LIMIT, RANGE_0_60)
+private val RANGES_NO_LIMIT_90 = RefreshRateRanges(RANGE_NO_LIMIT, RANGE_0_90)
+private val RANGES_NO_LIMIT_120 = RefreshRateRanges(RANGE_NO_LIMIT, RANGE_0_120)
+private val RANGES_90 = RefreshRateRanges(RANGE_0_90, RANGE_0_90)
+private val RANGES_120 = RefreshRateRanges(RANGE_0_120, RANGE_0_120)
+private val RANGES_90_60 = RefreshRateRanges(RANGE_0_90, RANGE_0_60)
+private val RANGES_90TO90 = RefreshRateRanges(RANGE_90_90, RANGE_90_90)
+private val RANGES_90TO120 = RefreshRateRanges(RANGE_90_120, RANGE_90_120)
+private val RANGES_60TO120_60TO90 = RefreshRateRanges(RANGE_60_120, RANGE_60_90)
+private val RANGES_MIN90 = RefreshRateRanges(RANGE_90_INF, RANGE_90_INF)
+private val RANGES_MIN90_90TO120 = RefreshRateRanges(RANGE_90_INF, RANGE_90_120)
+private val RANGES_MIN60_60TO90 = RefreshRateRanges(RANGE_60_INF, RANGE_60_90)
+private val RANGES_MIN90_90TO90 = RefreshRateRanges(RANGE_90_INF, RANGE_90_90)
+
@SmallTest
@RunWith(TestParameterInjector::class)
class SettingsObserverTest {
@@ -63,7 +92,7 @@
}
@Test
- fun testLowPowerMode(@TestParameter testCase: SettingsObserverTestCase) {
+ fun `test low power mode`(@TestParameter testCase: LowPowerTestCase) {
whenever(mockFlags.isVsyncLowPowerVoteEnabled).thenReturn(testCase.vsyncLowPowerVoteEnabled)
whenever(spyContext.contentResolver)
.thenReturn(settingsProviderRule.mockContentResolver(null))
@@ -87,23 +116,127 @@
Vote.PRIORITY_LOW_POWER_MODE)).isEqualTo(testCase.expectedVote)
}
- enum class SettingsObserverTestCase(
- val vrrSupported: Boolean,
- val vsyncLowPowerVoteEnabled: Boolean,
- val lowPowerModeEnabled: Boolean,
- internal val expectedVote: Vote?
+ enum class LowPowerTestCase(
+ val vrrSupported: Boolean,
+ val vsyncLowPowerVoteEnabled: Boolean,
+ val lowPowerModeEnabled: Boolean,
+ internal val expectedVote: Vote?
) {
ALL_ENABLED(true, true, true,
- SupportedRefreshRatesVote(listOf(
- SupportedRefreshRatesVote.RefreshRates(60f, 240f),
- SupportedRefreshRatesVote.RefreshRates(60f, 60f)
- ))),
+ SupportedRefreshRatesVote(listOf(
+ SupportedRefreshRatesVote.RefreshRates(60f, 240f),
+ SupportedRefreshRatesVote.RefreshRates(60f, 60f)
+ ))),
LOW_POWER_OFF(true, true, false, null),
DVRR_NOT_SUPPORTED_LOW_POWER_ON(false, true, true,
- RefreshRateVote.RenderVote(0f, 60f)),
+ RefreshRateVote.RenderVote(0f, 60f)),
DVRR_NOT_SUPPORTED_LOW_POWER_OFF(false, true, false, null),
VSYNC_VOTE_DISABLED_SUPPORTED_LOW_POWER_ON(true, false, true,
- RefreshRateVote.RenderVote(0f, 60f)),
+ RefreshRateVote.RenderVote(0f, 60f)),
VSYNC_VOTE_DISABLED_LOW_POWER_OFF(true, false, false, null),
}
+
+ @Test
+ fun `test settings refresh rates`(@TestParameter testCase: SettingsRefreshRateTestCase) {
+ whenever(mockFlags.isPeakRefreshRatePhysicalLimitEnabled)
+ .thenReturn(testCase.peakRefreshRatePhysicalLimitEnabled)
+
+ val displayModeDirector = DisplayModeDirector(
+ spyContext, testHandler, mockInjector, mockFlags, mockDisplayDeviceConfigProvider)
+
+ val modes = arrayOf(
+ Display.Mode(1, 1000, 1000, 60f),
+ Display.Mode(2, 1000, 1000, 90f),
+ Display.Mode(3, 1000, 1000, 120f)
+ )
+ displayModeDirector.injectSupportedModesByDisplay(SparseArray<Array<Display.Mode>>().apply {
+ append(Display.DEFAULT_DISPLAY, modes)
+ })
+ displayModeDirector.injectDefaultModeByDisplay(SparseArray<Display.Mode>().apply {
+ append(Display.DEFAULT_DISPLAY, modes[0])
+ })
+
+ val specs = displayModeDirector.getDesiredDisplayModeSpecsWithInjectedFpsSettings(
+ testCase.minRefreshRate, testCase.peakRefreshRate, testCase.defaultRefreshRate)
+
+ assertWithMessage("Primary RefreshRateRanges: ")
+ .that(specs.primary).isEqualTo(testCase.expectedPrimaryRefreshRateRanges)
+ assertWithMessage("App RefreshRateRanges: ")
+ .that(specs.appRequest).isEqualTo(testCase.expectedAppRefreshRateRanges)
+ }
+
+ /**
+ * Votes considered:
+ * priority: PRIORITY_USER_SETTING_PEAK_REFRESH_RATE (also used for appRanged)
+ * condition: peakRefreshRatePhysicalLimitEnabled, peakRR > 0
+ * vote: physical(minRR, peakRR)
+ *
+ * priority: PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE (also used for appRanged)
+ * condition: peakRR > 0
+ * vote: render(minRR, peakRR)
+ *
+ * priority: PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE
+ * condition: -
+ * vote: render(minRR, INF)
+ *
+ * priority: PRIORITY_DEFAULT_RENDER_FRAME_RATE
+ * condition: defaultRR > 0
+ * vote: render(0, defaultRR)
+ *
+ * 0 considered not set
+ *
+ * For this test:
+ * primary physical rate:
+ * (minRR, peakRefreshRatePhysicalLimitEnabled ? max(minRR, peakRR) : INF)
+ * primary render rate : (minRR, min(defaultRR, max(minRR, peakRR)))
+ *
+ * app physical rate: (0, peakRefreshRatePhysicalLimitEnabled ? max(minRR, peakRR) : INF)
+ * app render rate: (0, max(minRR, peakRR))
+ */
+ enum class SettingsRefreshRateTestCase(
+ val minRefreshRate: Float,
+ val peakRefreshRate: Float,
+ val defaultRefreshRate: Float,
+ val peakRefreshRatePhysicalLimitEnabled: Boolean,
+ val expectedPrimaryRefreshRateRanges: RefreshRateRanges,
+ val expectedAppRefreshRateRanges: RefreshRateRanges,
+ ) {
+ NO_LIMIT(0f, 0f, 0f, false, RANGES_NO_LIMIT, RANGES_NO_LIMIT),
+ NO_LIMIT_WITH_PHYSICAL_RR(0f, 0f, 0f, true, RANGES_NO_LIMIT, RANGES_NO_LIMIT),
+
+ LIMITS_0_0_90(0f, 0f, 90f, false, RANGES_NO_LIMIT_90, RANGES_NO_LIMIT),
+ LIMITS_0_0_90_WITH_PHYSICAL_RR(0f, 0f, 90f, true, RANGES_NO_LIMIT_90, RANGES_NO_LIMIT),
+
+ LIMITS_0_90_0(0f, 90f, 0f, false, RANGES_NO_LIMIT_90, RANGES_NO_LIMIT_90),
+ LIMITS_0_90_0_WITH_PHYSICAL_RR(0f, 90f, 0f, true, RANGES_90, RANGES_90),
+
+ LIMITS_0_90_60(0f, 90f, 60f, false, RANGES_NO_LIMIT_60, RANGES_NO_LIMIT_90),
+ LIMITS_0_90_60_WITH_PHYSICAL_RR(0f, 90f, 60f, true, RANGES_90_60, RANGES_90),
+
+ LIMITS_0_90_120(0f, 90f, 120f, false, RANGES_NO_LIMIT_90, RANGES_NO_LIMIT_90),
+ LIMITS_0_90_120_WITH_PHYSICAL_RR(0f, 90f, 120f, true, RANGES_90, RANGES_90),
+
+ LIMITS_90_0_0(90f, 0f, 0f, false, RANGES_MIN90, RANGES_NO_LIMIT),
+ LIMITS_90_0_0_WITH_PHYSICAL_RR(90f, 0f, 0f, true, RANGES_MIN90, RANGES_NO_LIMIT),
+
+ LIMITS_90_0_120(90f, 0f, 120f, false, RANGES_MIN90_90TO120, RANGES_NO_LIMIT),
+ LIMITS_90_0_120_WITH_PHYSICAL_RR(90f,
+ 0f,
+ 120f,
+ true,
+ RANGES_MIN90_90TO120,
+ RANGES_NO_LIMIT),
+
+ LIMITS_90_0_60(90f, 0f, 60f, false, RANGES_MIN90, RANGES_NO_LIMIT),
+ LIMITS_90_0_60_WITH_PHYSICAL_RR(90f, 0f, 60f, true, RANGES_MIN90, RANGES_NO_LIMIT),
+
+ LIMITS_90_120_0(90f, 120f, 0f, false, RANGES_MIN90_90TO120, RANGES_NO_LIMIT_120),
+ LIMITS_90_120_0_WITH_PHYSICAL_RR(90f, 120f, 0f, true, RANGES_90TO120, RANGES_120),
+
+ LIMITS_90_60_0(90f, 60f, 0f, false, RANGES_MIN90_90TO90, RANGES_NO_LIMIT_90),
+ LIMITS_90_60_0_WITH_PHYSICAL_RR(90f, 60f, 0f, true, RANGES_90TO90, RANGES_90),
+
+ LIMITS_60_120_90(60f, 120f, 90f, false, RANGES_MIN60_60TO90, RANGES_NO_LIMIT_120),
+ LIMITS_60_120_90_WITH_PHYSICAL_RR(60f, 120f, 90f, true, RANGES_60TO120_60TO90, RANGES_120),
+ }
}
\ No newline at end of file
diff --git a/services/tests/dreamservicetests/Android.bp b/services/tests/dreamservicetests/Android.bp
index 86b3a6c..6369d45 100644
--- a/services/tests/dreamservicetests/Android.bp
+++ b/services/tests/dreamservicetests/Android.bp
@@ -18,7 +18,9 @@
"mockito-target-minus-junit4",
"services.core",
"mockingservicestests-utils-mockito",
+ "platform-test-annotations",
"servicestests-utils",
+ "testables",
],
defaults: [
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
index 293ab7b..1322545 100644
--- a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
@@ -19,25 +19,52 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.content.res.TypedArray;
+import android.os.Looper;
+import android.platform.test.annotations.EnableFlags;
import android.service.dreams.DreamService;
+import android.service.dreams.Flags;
+import android.service.dreams.IDreamOverlayCallback;
+import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamServiceTest {
private static final String TEST_PACKAGE_NAME = "com.android.frameworks.dreamservicetests";
+ private TestableLooper mTestableLooper;
+
+ @Before
+ public void setup() throws Exception {
+ mTestableLooper = new TestableLooper(Looper.getMainLooper());
+ }
+
+ @After
+ public void tearDown() {
+ mTestableLooper.destroy();
+ }
+
@Test
public void testMetadataParsing() throws PackageManager.NameNotFoundException {
final String testDreamClassName = "com.android.server.dreams.TestDreamService";
@@ -62,6 +89,18 @@
assertThat(metadata.dreamCategory).isEqualTo(DreamService.DREAM_CATEGORY_DEFAULT);
}
+ @Test
+ public void testMetadataParsing_exceptionReading() {
+ final PackageManager packageManager = Mockito.mock(PackageManager.class);
+ final ServiceInfo serviceInfo = Mockito.mock(ServiceInfo.class);
+ final TypedArray rawMetadata = Mockito.mock(TypedArray.class);
+ when(packageManager.extractPackageItemInfoAttributes(eq(serviceInfo), any(), any(), any()))
+ .thenReturn(rawMetadata);
+ when(rawMetadata.getString(anyInt())).thenThrow(new RuntimeException("failure"));
+
+ assertThat(DreamService.getDreamMetadata(packageManager, serviceInfo)).isNull();
+ }
+
private DreamService.DreamMetadata getDreamMetadata(String dreamClassName)
throws PackageManager.NameNotFoundException {
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
@@ -70,4 +109,76 @@
PackageManager.ComponentInfoFlags.of(PackageManager.GET_META_DATA));
return DreamService.getDreamMetadata(context, si);
}
+
+ /**
+ * Verifies progressing a {@link DreamService} to creation
+ */
+ @Test
+ public void testCreate() throws Exception {
+ final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+ .setShouldShowComplications(true)
+ .build();
+ assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_CREATE));
+ }
+
+ /**
+ * Verifies progressing a {@link DreamService} to binding
+ */
+ @Test
+ public void testBind() throws Exception {
+ final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+ .setShouldShowComplications(true)
+ .build();
+ assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_BIND));
+ }
+
+ /**
+ * Verifies progressing a {@link DreamService} through
+ * {@link android.service.dreams.DreamActivity} creation.
+ */
+ @Test
+ public void testDreamActivityCreate() throws Exception {
+ final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+ .setShouldShowComplications(true)
+ .build();
+ assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_DREAM_ACTIVITY_CREATED));
+ }
+
+ /**
+ * Verifies progressing a {@link DreamService} through starting.
+ */
+ @Test
+ public void testStart() throws Exception {
+ final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+ .setShouldShowComplications(true)
+ .build();
+ assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_STARTED));
+ }
+
+ /**
+ * Verifies progressing a {@link DreamService} through waking.
+ */
+ @Test
+ public void testWake() throws Exception {
+ final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+ .setShouldShowComplications(true)
+ .build();
+ assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_WOKEN));
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT)
+ public void testRedirect() throws Exception {
+ TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+ .setDreamOverlayPresent(true)
+ .setShouldShowComplications(true)
+ .build();
+
+ environment.advance(TestDreamEnvironment.DREAM_STATE_STARTED);
+ final IDreamOverlayCallback overlayCallback = environment.getDreamOverlayCallback();
+ overlayCallback.onRedirectWake(true);
+ environment.resetClientInvocations();
+ environment.advance(TestDreamEnvironment.DREAM_STATE_WOKEN);
+ verify(environment.getDreamOverlayClient()).onWakeRequested();
+ }
}
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java
new file mode 100644
index 0000000..ef85ba5
--- /dev/null
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.dreams;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.description;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.IntDef;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.service.dreams.DreamActivity;
+import android.service.dreams.DreamOverlayConnectionHandler;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
+import android.service.dreams.IDreamOverlayCallback;
+import android.service.dreams.IDreamOverlayClient;
+import android.service.dreams.IDreamService;
+import android.testing.TestableLooper;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowInsetsController;
+import android.view.WindowManager;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Consumer;
+
+
+/**
+ * {@link TestDreamEnvironment} sets up entire testing environment around a dream service, allowing
+ * bring-up and interaction around the dream.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class TestDreamEnvironment {
+ private static final String FAKE_DREAM_PACKAGE_NAME = "com.foo.bar";
+ private static final ComponentName FAKE_DREAM_OVERLAY_COMPONENT =
+ ComponentName.createRelative(FAKE_DREAM_PACKAGE_NAME, ".OverlayComponent");
+ private static final String FAKE_DREAM_SETTINGS_ACTIVITY = ".SettingsActivity";
+ private static final ComponentName FAKE_DREAM_ACTIVITY_COMPONENT =
+ ComponentName.createRelative(FAKE_DREAM_PACKAGE_NAME, ".DreamActivity");
+ private static final ComponentName FAKE_DREAM_COMPONENT =
+ ComponentName.createRelative(FAKE_DREAM_PACKAGE_NAME, ".DreamService");
+
+ /** Initial state when creating a test environment */
+ public static final int DREAM_STATE_INIT = 0;
+
+ /** State where the dream has been created */
+ public static final int DREAM_STATE_CREATE = 1;
+
+ /** State where the dream has been bound to */
+ public static final int DREAM_STATE_BIND = 2;
+
+ /** State where the dream activity has been created and signaled back to the dream */
+ public static final int DREAM_STATE_DREAM_ACTIVITY_CREATED = 3;
+
+
+ /** State where the dream has started after being attached */
+ public static final int DREAM_STATE_STARTED = 4;
+
+ /** State where the dream has been woken */
+ public static final int DREAM_STATE_WOKEN = 5;
+
+
+ @IntDef(prefix = { "DREAM_STATE_" }, value = {
+ DREAM_STATE_INIT,
+ DREAM_STATE_CREATE,
+ DREAM_STATE_BIND,
+ DREAM_STATE_DREAM_ACTIVITY_CREATED,
+ DREAM_STATE_STARTED,
+ DREAM_STATE_WOKEN,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DreamState{}
+
+ /**
+ * A convenience builder for assembling a {@link TestDreamEnvironment}.
+ */
+ public static class Builder {
+ private final TestableLooper mLooper;
+ private boolean mShouldShowComplications;
+ private boolean mOverlayPresent;
+ private boolean mWindowless;
+
+ public Builder(TestableLooper looper) {
+ mLooper = looper;
+ }
+
+ /**
+ * Sets whether the dream should show complications.
+ * @param show {@code true} for showing complications, {@code false} otherwise.
+ * @return The updated {@link Builder}.
+ */
+ public Builder setShouldShowComplications(boolean show) {
+ mShouldShowComplications = show;
+ return this;
+ }
+
+ /**
+ * Sets whether a dream overlay is present
+ * @param present {@code true} if the overlay is present, {@code false} otherwise.
+ */
+ public Builder setDreamOverlayPresent(boolean present) {
+ mOverlayPresent = present;
+ return this;
+ }
+
+ /**
+ * Sets whether the dream should be windowless
+ */
+ public Builder setWindowless(boolean windowless) {
+ mWindowless = windowless;
+ return this;
+ }
+
+ /**
+ * Builds the a {@link TestDreamEnvironment} based on the builder.
+ */
+ public TestDreamEnvironment build() throws Exception {
+ return new TestDreamEnvironment(mLooper, mShouldShowComplications,
+ mOverlayPresent, mWindowless);
+ }
+ }
+
+ private static class TestInjector implements DreamService.Injector {
+ @Mock
+ private Resources mResources;
+
+ @Mock
+ private PackageManager mPackageManager;
+
+ @Mock
+ private TypedArray mAttributes;
+
+ @Mock
+ private ServiceInfo mServiceInfo;
+
+ private final Handler mHandler;
+ private final IDreamManager mDreamManager;
+ private final DreamOverlayConnectionHandler mDreamOverlayConnectionHandler;
+
+ TestInjector(Looper looper,
+ IDreamManager dreamManager,
+ DreamOverlayConnectionHandler dreamOverlayConnectionHandler,
+ boolean shouldShowComplications) {
+ MockitoAnnotations.initMocks(this);
+ mHandler = new Handler(looper);
+ mDreamManager = dreamManager;
+ mDreamOverlayConnectionHandler = dreamOverlayConnectionHandler;
+ mServiceInfo.packageName = FAKE_DREAM_PACKAGE_NAME;
+ when(mAttributes.getBoolean(eq(R.styleable.Dream_showClockAndComplications),
+ anyBoolean()))
+ .thenReturn(shouldShowComplications);
+ when(mAttributes.getDrawable(eq(com.android.internal.R.styleable.Dream_previewImage)))
+ .thenReturn(mock(Drawable.class));
+ when(mAttributes.getString(eq(com.android.internal.R.styleable.Dream_settingsActivity)))
+ .thenReturn(FAKE_DREAM_SETTINGS_ACTIVITY);
+ when(mPackageManager.extractPackageItemInfoAttributes(any(), any(), any(), any()))
+ .thenReturn(mAttributes);
+ }
+ @Override
+ public void init(Context context) {
+ }
+
+ @Override
+ public DreamOverlayConnectionHandler createOverlayConnection(
+ ComponentName overlayComponent) {
+ return mDreamOverlayConnectionHandler;
+ }
+
+ @Override
+ public ComponentName getDreamActivityComponent() {
+ return FAKE_DREAM_ACTIVITY_COMPONENT;
+ }
+
+ @Override
+ public ComponentName getDreamComponent() {
+ return FAKE_DREAM_COMPONENT;
+ }
+
+ @Override
+ public String getDreamPackageName() {
+ return FAKE_DREAM_PACKAGE_NAME;
+ }
+
+ @Override
+ public IDreamManager getDreamManager() {
+ return mDreamManager;
+ }
+
+ @Override
+ public ServiceInfo getServiceInfo() {
+ return mServiceInfo;
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+
+ @Override
+ public Resources getResources() {
+ return mResources;
+ }
+ }
+
+ @Mock
+ private IDreamManager mDreamManager;
+
+ @Mock
+ private DreamOverlayConnectionHandler mDreamOverlayConnectionHandler;
+
+ @Mock
+ private DreamActivity mDreamActivity;
+
+ @Mock
+ private Window mActivityWindow;
+
+ @Mock
+ private View mDecorView;
+
+ @Mock
+ private IDreamOverlayClient mDreamOverlayClient;
+
+ private final TestableLooper mTestableLooper;
+ private final DreamService mService;
+ private final boolean mWindowless;
+
+ private IDreamService mDreamServiceWrapper;
+
+ private @DreamState int mCurrentDreamState = DREAM_STATE_INIT;
+
+ private IDreamOverlayCallback mDreamOverlayCallback;
+
+ private boolean mOverlayPresent;
+
+ public TestDreamEnvironment(
+ TestableLooper looper,
+ boolean shouldShowComplications,
+ boolean overlayPresent,
+ boolean windowless
+ ) {
+ MockitoAnnotations.initMocks(this);
+
+ mOverlayPresent = overlayPresent;
+ mWindowless = windowless;
+
+ mTestableLooper = looper;
+ final DreamService.Injector injector = new TestInjector(mTestableLooper.getLooper(),
+ mDreamManager, mDreamOverlayConnectionHandler, shouldShowComplications);
+
+ when(mDreamActivity.getWindow()).thenReturn(mActivityWindow);
+ when(mActivityWindow.getAttributes()).thenReturn(mock(WindowManager.LayoutParams.class));
+ when(mActivityWindow.getDecorView()).thenReturn(mDecorView);
+ when(mDreamOverlayConnectionHandler.bind()).thenReturn(true);
+
+ doAnswer((InvocationOnMock invocation) -> {
+ Consumer<IDreamOverlayClient> client =
+ (Consumer<IDreamOverlayClient>) invocation.getArguments()[0];
+ client.accept(mDreamOverlayClient);
+ return null;
+ }).when(mDreamOverlayConnectionHandler).addConsumer(any());
+ when(mDecorView.getWindowInsetsController()).thenReturn(
+ mock(WindowInsetsController.class));
+
+ mService = new DreamService(injector);
+ }
+
+ /**
+ * Advances a dream to a given state, progressing through all previous states.
+ */
+ public boolean advance(@DreamState int state) throws Exception {
+ if (state <= mCurrentDreamState) {
+ return false;
+ }
+
+ do {
+ switch(++mCurrentDreamState) {
+ case DREAM_STATE_CREATE -> createDream();
+ case DREAM_STATE_BIND -> bindToDream();
+ case DREAM_STATE_DREAM_ACTIVITY_CREATED -> createDreamActivity();
+ case DREAM_STATE_STARTED -> startDream();
+ case DREAM_STATE_WOKEN -> wakeDream();
+ }
+ } while (mCurrentDreamState < state);
+
+ return true;
+ }
+
+ private void createDream() {
+ mService.onCreate();
+ mService.setWindowless(mWindowless);
+ }
+
+ private void bindToDream() {
+ final Intent intent = new Intent();
+
+ if (mOverlayPresent) {
+ DreamService.setDreamOverlayComponent(intent, FAKE_DREAM_OVERLAY_COMPONENT);
+ }
+
+ mDreamServiceWrapper = IDreamService.Stub.asInterface(mService.onBind(intent));
+
+ if (mOverlayPresent) {
+ // Ensure that the overlay has been bound by the dream.
+ verify(mDreamOverlayConnectionHandler,
+ description("dream did not bind to the dream overlay")).bind();
+ }
+ }
+
+ private void createDreamActivity() throws RemoteException {
+ final IRemoteCallback callback = mock(IRemoteCallback.class);
+ mDreamServiceWrapper.attach(mock(IBinder.class), false, false, callback);
+ mTestableLooper.processAllMessages();
+
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mDreamManager,
+ description("dream manager was not informed to start the dream activity"))
+ .startDreamActivity(intentCaptor.capture());
+ final Intent intent = intentCaptor.getValue();
+
+ final DreamService.DreamActivityCallbacks dreamActivityCallbacks =
+ DreamActivity.getCallback(intent);
+
+ dreamActivityCallbacks.onActivityCreated(mDreamActivity);
+ }
+
+ private void startDream() throws RemoteException {
+ final ArgumentCaptor<View.OnAttachStateChangeListener> attachChangeListenerCaptor =
+ ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+ verify(mDecorView,
+ description("dream did not add a listener to when the decor view is attached"))
+ .addOnAttachStateChangeListener(attachChangeListenerCaptor.capture());
+
+ resetClientInvocations();
+ attachChangeListenerCaptor.getValue().onViewAttachedToWindow(mDecorView);
+
+ if (mOverlayPresent) {
+ final ArgumentCaptor<IDreamOverlayCallback> overlayCallbackCaptor =
+ ArgumentCaptor.forClass(IDreamOverlayCallback.class);
+ verify(mDreamOverlayClient, description("dream client not informed of dream start"))
+ .startDream(any(), overlayCallbackCaptor.capture(), any(), anyBoolean());
+
+ mDreamOverlayCallback = overlayCallbackCaptor.getValue();
+ }
+ }
+
+ private void wakeDream() throws RemoteException {
+ mService.wakeUp();
+ }
+
+ /**
+ * Retrieves the dream overlay callback.
+ */
+ public IDreamOverlayCallback getDreamOverlayCallback() throws Exception {
+ advance(DREAM_STATE_STARTED);
+ return mDreamOverlayCallback;
+ }
+
+ /**
+ * Resets interactions with the dream overlay client.
+ */
+ public void resetClientInvocations() {
+ Mockito.clearInvocations(mDreamOverlayClient);
+ }
+
+ /**
+ * Retrieves the dream overlay client.
+ */
+ public IDreamOverlayClient getDreamOverlayClient() {
+ return mDreamOverlayClient;
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
index a8b792e..80f7a06 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
@@ -197,7 +197,7 @@
+ Arrays.toString(invocation.getArguments()));
if (!wedge) {
if (mRealAms.mConstants.mEnableWaitForFinishAttachApplication) {
- mRealAms.finishAttachApplication(0);
+ mRealAms.finishAttachApplication(0, 0);
}
}
return null;
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 9590783..cc69c1d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -245,9 +245,11 @@
LocalServices.removeServiceForTest(PackageManagerInternal.class);
}
+ @SuppressWarnings("GuardedBy")
@After
public void tearDown() {
sService.mOomAdjuster.resetInternal();
+ sService.mOomAdjuster.mActiveUids.clear();
}
private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
@@ -2816,6 +2818,69 @@
SCHED_GROUP_DEFAULT);
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testSetUidTempAllowlistState() {
+ final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ setProcessesToLru(app, app2);
+
+ // App1 binds to app2 and gets temp allowlisted.
+ bindService(app2, app, null, null, 0, mock(IBinder.class));
+ sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, true);
+
+ assertEquals(true, app.getUidRecord().isSetAllowListed());
+ assertEquals(true, app.mOptRecord.shouldNotFreeze());
+ assertEquals(true, app2.mOptRecord.shouldNotFreeze());
+
+ sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
+ assertEquals(false, app.getUidRecord().isSetAllowListed());
+ assertEquals(false, app.mOptRecord.shouldNotFreeze());
+ assertEquals(false, app2.mOptRecord.shouldNotFreeze());
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testSetUidTempAllowlistState_multipleAllowlistClients() {
+ final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ setProcessesToLru(app, app2, app3);
+
+ // App1 and app2 both bind to app3 and get temp allowlisted.
+ bindService(app3, app, null, null, 0, mock(IBinder.class));
+ bindService(app3, app2, null, null, 0, mock(IBinder.class));
+ sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, true);
+ sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP2_UID, true);
+
+ assertEquals(true, app.getUidRecord().isSetAllowListed());
+ assertEquals(true, app2.getUidRecord().isSetAllowListed());
+ assertEquals(true, app.mOptRecord.shouldNotFreeze());
+ assertEquals(true, app2.mOptRecord.shouldNotFreeze());
+ assertEquals(true, app3.mOptRecord.shouldNotFreeze());
+
+ // Remove app1 from allowlist.
+ sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
+ assertEquals(false, app.getUidRecord().isSetAllowListed());
+ assertEquals(true, app2.getUidRecord().isSetAllowListed());
+ assertEquals(false, app.mOptRecord.shouldNotFreeze());
+ assertEquals(true, app2.mOptRecord.shouldNotFreeze());
+ assertEquals(true, app3.mOptRecord.shouldNotFreeze());
+
+ // Now remove app2 from allowlist.
+ sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP2_UID, false);
+ assertEquals(false, app.getUidRecord().isSetAllowListed());
+ assertEquals(false, app2.getUidRecord().isSetAllowListed());
+ assertEquals(false, app.mOptRecord.shouldNotFreeze());
+ assertEquals(false, app2.mOptRecord.shouldNotFreeze());
+ assertEquals(false, app3.mOptRecord.shouldNotFreeze());
+ }
+
private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
String packageName, boolean hasShownUi) {
return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi(
@@ -3057,6 +3122,14 @@
receivers.addCurReceiver(mock(BroadcastRecord.class));
}
providers.setLastProviderTime(mLastProviderTime);
+
+ UidRecord uidRec = sService.mOomAdjuster.mActiveUids.get(mUid);
+ if (uidRec == null) {
+ uidRec = new UidRecord(mUid, sService);
+ sService.mOomAdjuster.mActiveUids.put(mUid, uidRec);
+ }
+ uidRec.addProcess(app);
+ app.setUidRecord(uidRec);
return app;
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
index 67be93b..89c67d5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
@@ -200,7 +200,7 @@
Log.v(TAG, "Intercepting bindApplication() for "
+ Arrays.toString(invocation.getArguments()));
if (mRealAms.mConstants.mEnableWaitForFinishAttachApplication) {
- mRealAms.finishAttachApplication(0);
+ mRealAms.finishAttachApplication(0, 0);
}
return null;
}).when(thread).bindApplication(
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java b/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
index e672928..599b9cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
@@ -24,6 +24,7 @@
import android.content.ContentResolver;
import android.os.SystemProperties;
import android.provider.Settings;
+import android.provider.DeviceConfig.Properties;
import android.text.TextUtils;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
@@ -42,6 +43,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
/**
* Test SettingsToPropertiesMapper.
@@ -61,6 +63,7 @@
private HashMap<String, String> mSystemSettingsMap;
private HashMap<String, String> mGlobalSettingsMap;
+ private HashMap<String, String> mConfigSettingsMap;
@Before
public void setUp() throws Exception {
@@ -71,9 +74,11 @@
.spyStatic(SystemProperties.class)
.spyStatic(Settings.Global.class)
.spyStatic(SettingsToPropertiesMapper.class)
+ .spyStatic(Settings.Config.class)
.startMocking();
mSystemSettingsMap = new HashMap<>();
mGlobalSettingsMap = new HashMap<>();
+ mConfigSettingsMap = new HashMap<>();
// Mock SystemProperties setter and various getters
doAnswer((Answer<Void>) invocationOnMock -> {
@@ -93,7 +98,7 @@
}
).when(() -> SystemProperties.get(anyString()));
- // Mock Settings.Global methods
+ // Mock Settings.Global method
doAnswer((Answer<String>) invocationOnMock -> {
String key = invocationOnMock.getArgument(1);
@@ -101,6 +106,21 @@
}
).when(() -> Settings.Global.getString(any(), anyString()));
+ // Mock Settings.Config getstrings method
+ doAnswer((Answer<Map<String, String>>) invocationOnMock -> {
+ String namespace = invocationOnMock.getArgument(0);
+ List<String> flags = invocationOnMock.getArgument(1);
+ HashMap<String, String> values = new HashMap<>();
+ for (String flag : flags) {
+ String value = mConfigSettingsMap.get(namespace + "/" + flag);
+ if (value != null) {
+ values.put(flag, value);
+ }
+ }
+ return values;
+ }
+ ).when(() -> Settings.Config.getStrings(anyString(), any()));
+
mTestMapper = new SettingsToPropertiesMapper(
mMockContentResolver, TEST_MAPPING, new String[] {}, new String[] {});
}
@@ -239,4 +259,43 @@
Assert.assertTrue(categories.contains("category2"));
Assert.assertTrue(categories.contains("category3"));
}
+
+ @Test
+ public void testGetStagedFlagsWithValueChange() {
+ // mock up what is in the setting already
+ mConfigSettingsMap.put("namespace_1/flag_1", "true");
+ mConfigSettingsMap.put("namespace_1/flag_2", "true");
+
+ // mock up input
+ String namespace = "staged";
+ Map<String, String> keyValueMap = new HashMap<>();
+ // case 1: existing prop, stage the same value
+ keyValueMap.put("namespace_1*flag_1", "true");
+ // case 2: existing prop, stage a different value
+ keyValueMap.put("namespace_1*flag_2", "false");
+ // case 3: new prop, stage the non default value
+ keyValueMap.put("namespace_2*flag_1", "true");
+ // case 4: new prop, stage the default value
+ keyValueMap.put("namespace_2*flag_2", "false");
+ Properties props = new Properties(namespace, keyValueMap);
+
+ HashMap<String, HashMap<String, String>> toStageProps =
+ SettingsToPropertiesMapper.getStagedFlagsWithValueChange(props);
+
+ HashMap<String, String> namespace_1_to_stage = toStageProps.get("namespace_1");
+ HashMap<String, String> namespace_2_to_stage = toStageProps.get("namespace_2");
+ Assert.assertTrue(namespace_1_to_stage != null);
+ Assert.assertTrue(namespace_2_to_stage != null);
+
+ String namespace_1_flag_1 = namespace_1_to_stage.get("flag_1");
+ String namespace_1_flag_2 = namespace_1_to_stage.get("flag_2");
+ String namespace_2_flag_1 = namespace_2_to_stage.get("flag_1");
+ String namespace_2_flag_2 = namespace_2_to_stage.get("flag_2");
+ Assert.assertTrue(namespace_1_flag_1 == null);
+ Assert.assertTrue(namespace_1_flag_2 != null);
+ Assert.assertTrue(namespace_2_flag_1 != null);
+ Assert.assertTrue(namespace_2_flag_2 == null);
+ Assert.assertTrue(namespace_1_flag_2.equals("false"));
+ Assert.assertTrue(namespace_2_flag_1.equals("true"));
+ }
}
diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
index 5c74a80..7f165e0 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -3241,6 +3241,48 @@
}
}
+ @Test
+ public void testHalAutoSuspendMode_enabledByConfiguration() {
+ AtomicReference<DisplayManagerInternal.DisplayPowerCallbacks> callback =
+ new AtomicReference<>();
+ doAnswer((Answer<Void>) invocation -> {
+ callback.set(invocation.getArgument(0));
+ return null;
+ }).when(mDisplayManagerInternalMock).initPowerManagement(any(), any(), any());
+ when(mResourcesSpy.getBoolean(
+ com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay))
+ .thenReturn(false);
+ when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_useAutoSuspend))
+ .thenReturn(true);
+
+ createService();
+ startSystem();
+ callback.get().onDisplayStateChange(/* allInactive= */ true, /* allOff= */ true);
+
+ verify(mNativeWrapperMock).nativeSetAutoSuspend(true);
+ }
+
+ @Test
+ public void testHalAutoSuspendMode_disabledByConfiguration() {
+ AtomicReference<DisplayManagerInternal.DisplayPowerCallbacks> callback =
+ new AtomicReference<>();
+ doAnswer((Answer<Void>) invocation -> {
+ callback.set(invocation.getArgument(0));
+ return null;
+ }).when(mDisplayManagerInternalMock).initPowerManagement(any(), any(), any());
+ when(mResourcesSpy.getBoolean(
+ com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay))
+ .thenReturn(false);
+ when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_useAutoSuspend))
+ .thenReturn(false);
+
+ createService();
+ startSystem();
+ callback.get().onDisplayStateChange(/* allInactive= */ true, /* allOff= */ true);
+
+ verify(mNativeWrapperMock, never()).nativeSetAutoSuspend(true);
+ }
+
private void setCachedUidProcState(int uid) {
mService.updateUidProcStateInternal(uid, PROCESS_STATE_TOP_SLEEPING);
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
index d51828e..4e3e80f 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
@@ -341,7 +341,7 @@
}}, 0, 1234);
mMockClock.uptime = 1000;
- collector.forceSchedule();
+ collector.schedule();
waitForIdle();
mUidResolver.noteIsolatedUidRemoved(ISOLATED_UID, UID_2);
@@ -354,7 +354,7 @@
}}, 1234, 3421);
mMockClock.uptime = 2000;
- collector.forceSchedule();
+ collector.schedule();
waitForIdle();
assertThat(layout.getUidTimeByPowerBracket(mCollectedStats.uidStats.get(UID_2), 0))
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 94a71be..753db12 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -279,7 +279,7 @@
test_module_config {
name: "FrameworksServicesTests_contentprotection",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_filters: ["com.android.server.contentprotection"],
exclude_annotations: FLAKY_AND_IGNORED,
}
@@ -287,7 +287,7 @@
test_module_config {
name: "FrameworksServicesTests_om",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_filters: ["com.android.server.om."],
exclude_annotations: FLAKY_AND_IGNORED,
}
@@ -296,7 +296,7 @@
test_module_config {
name: "FrameworksServicesTests_contexthub_presubmit",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_filters: ["com.android.server.location.contexthub."],
// TODO(ron): are these right, does it run anything?
include_annotations: ["android.platform.test.annotations.Presubmit"],
@@ -306,7 +306,7 @@
test_module_config {
name: "FrameworksServicesTests_contexthub_postsubmit",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_filters: ["com.android.server.location.contexthub."],
// TODO(ron): are these right, does it run anything?
include_annotations: ["android.platform.test.annotations.Postsubmit"],
@@ -317,7 +317,7 @@
test_module_config {
name: "FrameworksServicesTests_contentcapture",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_filters: ["com.android.server.contentcapture"],
exclude_annotations: FLAKY_AND_IGNORED,
}
@@ -325,7 +325,7 @@
test_module_config {
name: "FrameworksServicesTests_recoverysystem",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_filters: ["com.android.server.recoverysystem."],
exclude_annotations: ["androidx.test.filters.FlakyTest"],
}
@@ -334,7 +334,7 @@
test_module_config {
name: "FrameworksServicesTests_pm_presubmit",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_annotations: ["android.platform.test.annotations.Presubmit"],
include_filters: ["com.android.server.pm."],
exclude_annotations: FLAKY_AND_IGNORED,
@@ -343,7 +343,7 @@
test_module_config {
name: "FrameworksServicesTests_pm_postsubmit",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_annotations: ["android.platform.test.annotations.Postsubmit"],
include_filters: ["com.android.server.pm."],
exclude_annotations: FLAKY_AND_IGNORED,
@@ -353,6 +353,6 @@
test_module_config {
name: "FrameworksServicesTests_os",
base: "FrameworksServicesTests",
- test_suites: ["general-tests"],
+ test_suites: ["device-tests"],
include_filters: ["com.android.server.os."],
}
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index c6f3eb3..30e3b18 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -58,6 +58,7 @@
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doNothing;
@@ -90,6 +91,7 @@
import android.os.Message;
import android.os.PowerManagerInternal;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IStorageManager;
@@ -203,7 +205,10 @@
doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
- doNothing().when(mInjector).lockDeviceNowAndWaitForKeyguardShown();
+ doAnswer(invocation -> {
+ ((Runnable) invocation.getArgument(0)).run();
+ return null;
+ }).when(mInjector).showKeyguard(any());
mockIsUsersOnSecondaryDisplaysEnabled(false);
// All UserController params are set to default.
@@ -540,7 +545,6 @@
expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
if (backgroundUserStopping) {
expectedCodes.add(CLEAR_USER_JOURNEY_SESSION_MSG);
- expectedCodes.add(0); // this is for directly posting in stopping.
}
if (expectScheduleBackgroundUserStopping) {
expectedCodes.add(SCHEDULED_STOP_BACKGROUND_USER_MSG);
@@ -1419,21 +1423,13 @@
// mock the device to be secure in order to expect the keyguard to be shown
when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
- // call real lockDeviceNowAndWaitForKeyguardShown method for this test
- doCallRealMethod().when(mInjector).lockDeviceNowAndWaitForKeyguardShown();
+ // call real showKeyguard method for this test
+ doCallRealMethod().when(mInjector).showKeyguard(any());
- // call startUser on a thread because we're expecting it to be blocked
- Thread threadStartUser = new Thread(()-> {
- mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND);
- });
- threadStartUser.start();
+ mUserController.completeUserSwitch(TEST_USER_ID1, TEST_USER_ID2);
- // make sure the switch is stalled...
- Thread.sleep(2000);
- // by checking REPORT_USER_SWITCH_MSG is not sent yet
- assertNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG));
- // and the thread is still alive
- assertTrue(threadStartUser.isAlive());
+ // make sure the switch is stalled by checking the UserSwitchingDialog is not dismissed yet
+ verify(mInjector, never()).dismissUserSwitchingDialog(any());
// mock send the keyguard shown event
ArgumentCaptor<ActivityTaskManagerInternal.ScreenObserver> captor = ArgumentCaptor.forClass(
@@ -1441,12 +1437,42 @@
verify(mInjector.mActivityTaskManagerInternal).registerScreenObserver(captor.capture());
captor.getValue().onKeyguardStateChanged(true);
- // verify the switch now moves on...
- Thread.sleep(1000);
- // by checking REPORT_USER_SWITCH_MSG is sent
- assertNotNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG));
- // and the thread is finished
- assertFalse(threadStartUser.isAlive());
+ // verify the switch now moves on by checking the UserSwitchingDialog is dismissed
+ verify(mInjector, atLeastOnce()).dismissUserSwitchingDialog(any());
+
+ // verify that SHOW_KEYGUARD_TIMEOUT is ignored and does not crash the system
+ try {
+ mInjector.mHandler.processPostDelayedCallbacksWithin(
+ UserController.SHOW_KEYGUARD_TIMEOUT_MS);
+ } catch (RuntimeException e) {
+ throw new AssertionError(
+ "SHOW_KEYGUARD_TIMEOUT is not ignored and crashed the system", e);
+ }
+ }
+
+ @Test
+ public void testRuntimeExceptionIsThrownIfTheKeyguardIsNotShown() throws Exception {
+ // enable user switch ui, because keyguard is only shown then
+ mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
+ /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+ /* backgroundUserScheduledStopTimeSecs= */ -1);
+
+ // mock the device to be secure in order to expect the keyguard to be shown
+ when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
+
+ // suppress showKeyguard method for this test
+ doNothing().when(mInjector).showKeyguard(any());
+
+ mUserController.completeUserSwitch(TEST_USER_ID1, TEST_USER_ID2);
+
+ // verify that the system has crashed
+ assertThrows("Should have thrown RuntimeException", RuntimeException.class, () -> {
+ mInjector.mHandler.processPostDelayedCallbacksWithin(
+ UserController.SHOW_KEYGUARD_TIMEOUT_MS);
+ });
+
+ // make sure the UserSwitchingDialog is not dismissed
+ verify(mInjector, never()).dismissUserSwitchingDialog(any());
}
private void setUpAndStartUserInBackground(int userId) throws Exception {
@@ -1793,7 +1819,9 @@
Set<Integer> getMessageCodes() {
Set<Integer> result = new LinkedHashSet<>();
for (Message msg : mMessages) {
- result.add(msg.what);
+ if (msg.what != 0) { // ignore mHandle.post and mHandler.postDelayed messages
+ result.add(msg.what);
+ }
}
return result;
}
@@ -1817,14 +1845,28 @@
@Override
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ final Runnable cb = msg.getCallback();
+ if (cb != null && uptimeMillis <= SystemClock.uptimeMillis()) {
+ // run mHandler.post calls immediately
+ cb.run();
+ return true;
+ }
Message copy = new Message();
copy.copyFrom(msg);
+ copy.setCallback(cb);
mMessages.add(copy);
- if (msg.getCallback() != null) {
- msg.getCallback().run();
- msg.setCallback(null);
- }
return super.sendMessageAtTime(msg, uptimeMillis);
}
+
+ public void processPostDelayedCallbacksWithin(long millis) {
+ final long whenMax = SystemClock.uptimeMillis() + millis;
+ for (Message msg : mMessages) {
+ final Runnable cb = msg.getCallback();
+ if (cb != null && msg.getWhen() <= whenMax) {
+ msg.setCallback(null);
+ cb.run();
+ }
+ }
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
index a6f2196..9862663 100644
--- a/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
@@ -16,8 +16,6 @@
package com.android.server.os;
-import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
-
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
@@ -25,9 +23,9 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.app.admin.flags.Flags;
-import android.app.role.RoleManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
@@ -61,6 +59,8 @@
import org.mockito.MockitoAnnotations;
import java.io.FileDescriptor;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -104,7 +104,7 @@
ArraySet<String> mAllowlistedPackages = new ArraySet<>();
mAllowlistedPackages.add(mContext.getPackageName());
mInjector = new TestInjector(mContext, mAllowlistedPackages, mMappingFile,
- mMockUserManager, mMockDevicePolicyManager);
+ mMockUserManager, mMockDevicePolicyManager, null);
mService = new BugreportManagerServiceImpl(mInjector);
mBugreportFileManager = new BugreportManagerServiceImpl.BugreportFileManager(mMappingFile);
when(mPackageManager.getPackageUidAsUser(anyString(), anyInt())).thenReturn(mCallingUid);
@@ -114,24 +114,8 @@
@After
public void tearDown() throws Exception {
- // Changes to RoleManager persist between tests, so we need to clear out any funny
- // business we did in previous tests.
+ // Clean up the mapping file between tests since it would otherwise persist.
mMappingFile.delete();
- RoleManager roleManager = mContext.getSystemService(RoleManager.class);
- CallbackFuture future = new CallbackFuture();
- runWithShellPermissionIdentity(
- () -> {
- roleManager.setBypassingRoleQualification(false);
- roleManager.removeRoleHolderAsUser(
- "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION",
- mContext.getPackageName(),
- /* flags= */ 0,
- Process.myUserHandle(),
- mContext.getMainExecutor(),
- future);
- });
-
- assertThat(future.get()).isEqualTo(true);
}
@Test
@@ -267,7 +251,10 @@
@Test
public void testCancelBugreportWithoutRole() {
- clearAllowlist();
+ // Create a new service to clear the allowlist
+ mService = new BugreportManagerServiceImpl(
+ new TestInjector(mContext, new ArraySet<>(), mMappingFile,
+ mMockUserManager, mMockDevicePolicyManager, null));
assertThrows(SecurityException.class, () -> mService.cancelBugreport(
Binder.getCallingUid(), mContext.getPackageName()));
@@ -275,29 +262,13 @@
@Test
public void testCancelBugreportWithRole() throws Exception {
- clearAllowlist();
- RoleManager roleManager = mContext.getSystemService(RoleManager.class);
- CallbackFuture future = new CallbackFuture();
- runWithShellPermissionIdentity(
- () -> {
- roleManager.setBypassingRoleQualification(true);
- roleManager.addRoleHolderAsUser(
- "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION",
- mContext.getPackageName(),
- /* flags= */ 0,
- Process.myUserHandle(),
- mContext.getMainExecutor(),
- future);
- });
-
- assertThat(future.get()).isEqualTo(true);
- mService.cancelBugreport(Binder.getCallingUid(), mContext.getPackageName());
- }
-
- private void clearAllowlist() {
+ // Create a new service to clear the allowlist, but override the role manager
mService = new BugreportManagerServiceImpl(
new TestInjector(mContext, new ArraySet<>(), mMappingFile,
- mMockUserManager, mMockDevicePolicyManager));
+ mMockUserManager, mMockDevicePolicyManager,
+ "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION"));
+
+ mService.cancelBugreport(Binder.getCallingUid(), mContext.getPackageName());
}
private static class Listener implements IDumpstateListener {
@@ -359,10 +330,22 @@
private boolean mBugreportStarted = false;
TestInjector(Context context, ArraySet<String> allowlistedPackages, AtomicFile mappingFile,
- UserManager um, DevicePolicyManager dpm) {
+ UserManager um, DevicePolicyManager dpm, String grantedRole) {
super(context, allowlistedPackages, mappingFile);
mUserManager = um;
mDevicePolicyManager = dpm;
+
+ if (grantedRole != null) {
+ mRoleManagerWrapper =
+ new BugreportManagerServiceImpl.Injector.RoleManagerWrapper() {
+ @Override
+ List<String> getRoleHolders(@NonNull String roleName) {
+ return roleName.equals(grantedRole)
+ ? Collections.singletonList(mContext.getPackageName())
+ : Collections.emptyList();
+ }
+ };
+ }
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index b91ef7c..37065fd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -237,6 +237,8 @@
assertThat(mainUserId).isEqualTo(parentProfileInfo.id);
removeUser(cloneProfileUser.id);
assertThat(mUserManager.getProfileParent(mainUserId)).isNull();
+ assertThat(mUserManager.getProfileAccessibilityString(cloneProfileUser.id)).isEqualTo(
+ Resources.getSystem().getString(userTypeDetails.getAccessibilityString()));
}
@Test
@@ -276,6 +278,9 @@
assertWithMessage("Communal profile not visible").that(umCommunal.isUserVisible()).isTrue();
switchUser(originalCurrent);
assertWithMessage("Communal profile not visible").that(umCommunal.isUserVisible()).isTrue();
+ assertThat(mUserManager.getProfileAccessibilityString(communal.getIdentifier()))
+ .isEqualTo(Resources.getSystem()
+ .getString(userTypeDetails.getAccessibilityString()));
}
@Test
@@ -372,6 +377,18 @@
assertThat(mUserManager.getProfileParent(mainUserId)).isNull();
assertThat(profileUM.getProfileLabel()).isEqualTo(
Resources.getSystem().getString(userTypeDetails.getLabel(0)));
+ assertThat(mUserManager.getProfileAccessibilityString(privateProfileUser.id)).isEqualTo(
+ Resources.getSystem().getString(userTypeDetails.getAccessibilityString()));
+ }
+
+ @Test
+ public void testGetProfileAccessibilityString_throwsExceptionForNonProfileUser() {
+ UserInfo user1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
+ assertThat(user1).isNotNull();
+ assertThrows(Resources.NotFoundException.class,
+ () -> mUserManager.getProfileAccessibilityString(user1.id));
+ assertThrows(Resources.NotFoundException.class,
+ () -> mUserManager.getProfileAccessibilityString(UserHandle.USER_SYSTEM));
}
@MediumTest
@@ -1003,6 +1020,8 @@
"android", 0, asHandle(userId)));
assertThat(userManagerForUser.isUserOfType(userTypeDetails.getName())).isTrue();
assertThat(userManagerForUser.isProfile()).isEqualTo(userTypeDetails.isProfile());
+ assertThat(mUserManager.getProfileAccessibilityString(managedProfileUser.id)).isEqualTo(
+ Resources.getSystem().getString(userTypeDetails.getAccessibilityString()));
}
/** Test that UserManager returns the correct UserProperties for a new managed profile. */
diff --git a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
index 669eedf..dabf531 100644
--- a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
@@ -31,11 +31,13 @@
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.os.Handler;
import android.os.PowerManager;
+import android.os.RemoteException;
import android.os.test.TestLooper;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableResources;
import android.view.Window;
+import android.view.accessibility.AccessibilityManager;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -48,7 +50,8 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.util.List;
@@ -72,9 +75,15 @@
private static final Integer AUTO_DISMISS_DIALOG = 500;
@Rule
+ public MockitoRule rule = MockitoJUnit.rule();
+
+ @Rule
public TestableContext mContext =
new TestableContext(InstrumentationRegistry.getContext(), null);
+ private final AccessibilityManager mAccessibilityManager =
+ mContext.getSystemService(AccessibilityManager.class);
+
@Mock
private PackageManager mPackageManager;
@Mock
@@ -89,9 +98,8 @@
private BiometricStateListener mBiometricStateListener;
@Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
-
+ public void setup() throws RemoteException {
+ disableAccessibility();
mContext.addMockSystemService(PackageManager.class, mPackageManager);
mContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
TestableResources resources = mContext.getOrCreateTestableResources();
@@ -192,9 +200,8 @@
}
@Test
- public void dialogDismissesAfterTime() throws Exception {
+ public void dialogDismissesAfterTime_accessibilityDisabled() throws Exception {
setupWithSensor(true /* hasSfps */, true /* initialized */);
-
setBiometricState(BiometricStateListener.STATE_ENROLLING);
when(mDialog.isShowing()).thenReturn(true);
assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
@@ -207,9 +214,23 @@
}
@Test
- public void dialogDoesNotDismissOnSensorTouch() throws Exception {
+ public void dialogDoesNotDismissAfterTime_accessibilityEnabled() throws Exception {
+ enableAccessibility();
setupWithSensor(true /* hasSfps */, true /* initialized */);
+ setBiometricState(BiometricStateListener.STATE_ENROLLING);
+ when(mDialog.isShowing()).thenReturn(true);
+ assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
+ mLooper.dispatchAll();
+ verify(mDialog).show();
+ mLooper.moveTimeForward(AUTO_DISMISS_DIALOG);
+ mLooper.dispatchAll();
+ verify(mDialog, never()).dismiss();
+ }
+
+ @Test
+ public void dialogDoesNotDismissOnSensorTouch_accessibilityDisabled() throws Exception {
+ setupWithSensor(true /* hasSfps */, true /* initialized */);
setBiometricState(BiometricStateListener.STATE_ENROLLING);
when(mDialog.isShowing()).thenReturn(true);
assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
@@ -218,12 +239,26 @@
verify(mDialog).show();
mBiometricStateListener.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
- mLooper.moveTimeForward(AUTO_DISMISS_DIALOG - 1);
mLooper.dispatchAll();
-
verify(mDialog, never()).dismiss();
}
+ @Test
+ public void dialogDismissesOnSensorTouch_accessibilityEnabled() throws Exception {
+ enableAccessibility();
+ setupWithSensor(true /* hasSfps */, true /* initialized */);
+ setBiometricState(BiometricStateListener.STATE_ENROLLING);
+ when(mDialog.isShowing()).thenReturn(true);
+ assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
+
+ mLooper.dispatchAll();
+ verify(mDialog).show();
+
+ mBiometricStateListener.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
+ mLooper.dispatchAll();
+ verify(mDialog).dismiss();
+ }
+
private void setBiometricState(@BiometricStateListener.State int newState) {
if (mBiometricStateListener != null) {
mBiometricStateListener.onStateChanged(newState);
@@ -231,6 +266,20 @@
}
}
+ private void enableAccessibility() throws RemoteException {
+ if (mAccessibilityManager != null) {
+ mAccessibilityManager.getClient().setState(1);
+ mLooper.dispatchAll();
+ }
+ }
+
+ private void disableAccessibility() throws RemoteException {
+ if (mAccessibilityManager != null) {
+ mAccessibilityManager.getClient().setState(0);
+ mLooper.dispatchAll();
+ }
+ }
+
private void setupWithSensor(boolean hasSfps, boolean initialized) throws Exception {
when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_FINGERPRINT)))
.thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java b/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java
index 44d1161..06c3db8 100644
--- a/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java
@@ -136,8 +136,14 @@
this(helper.mHandler, MSG_TIMEOUT, caller());
}
- void start(TestArg arg, long millis) {
- start(arg, arg.pid, arg.uid, millis);
+ @Override
+ public int getPid(TestArg arg) {
+ return arg.pid;
+ }
+
+ @Override
+ public int getUid(TestArg arg) {
+ return arg.uid;
}
// Return the name of method that called the constructor, assuming that this function is
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
index 0d6fdc9..4af20a9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
@@ -2638,7 +2638,7 @@
@Test
public void testSoundResetsRankingTime() throws Exception {
- mSetFlagsRule.enableFlags(android.app.Flags.FLAG_UPDATE_RANKING_TIME);
+ mSetFlagsRule.enableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME);
TestableFlagResolver flagResolver = new TestableFlagResolver();
initAttentionHelper(flagResolver);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index ce7a0a0..3a0eba1 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -24,7 +24,7 @@
import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.SHOW_IMMEDIATELY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.Flags.FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS;
-import static android.app.Flags.FLAG_UPDATE_RANKING_TIME;
+import static android.app.Flags.FLAG_SORT_SECTION_BY_TIME;
import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP;
import static android.app.Notification.EXTRA_PICTURE;
import static android.app.Notification.EXTRA_PICTURE_ICON;
@@ -243,7 +243,6 @@
import android.platform.test.flag.junit.FlagsParameterization;
import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.rule.LimitDevicesRule;
-import android.provider.DeviceConfig;
import android.provider.MediaStore;
import android.provider.Settings;
import android.service.notification.Adjustment;
@@ -280,7 +279,6 @@
import androidx.test.filters.SmallTest;
import com.android.internal.R;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.TestableFlagResolver;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.InstanceIdSequenceFake;
@@ -602,7 +600,9 @@
when(mContext.getContentResolver()).thenReturn(cr);
doNothing().when(cr).registerContentObserver(any(), anyBoolean(), any(), anyInt());
- setDpmAppOppsExemptFromDismissal(false);
+ when(mAppOpsManager.checkOpNoThrow(
+ AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
+ mPkg)).thenReturn(AppOpsManager.MODE_IGNORED);
// Use this testable looper.
mTestableLooper = TestableLooper.get(this);
@@ -900,7 +900,6 @@
@After
public void tearDown() throws Exception {
if (mFile != null) mFile.delete();
- clearDeviceConfig();
if (mActivityIntent != null) {
mActivityIntent.cancel();
@@ -1200,19 +1199,6 @@
return answers;
}
- private void clearDeviceConfig() {
- DeviceConfig.resetToDefaults(
- Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
- }
-
- private void setDefaultAssistantInDeviceConfig(String componentName) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
- componentName,
- false);
- }
-
private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
String groupKey, boolean isSummary, boolean mutable) {
// Give it a person
@@ -7390,7 +7376,7 @@
}
@Test
- @EnableFlags({android.app.Flags.FLAG_UPDATE_RANKING_TIME})
+ @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME})
public void testVisualDifference_userInitiatedJob() {
Notification.Builder nb1 = new Notification.Builder(mContext, "")
.setContentTitle("foo");
@@ -9092,7 +9078,6 @@
@Test
public void setDefaultAssistantForUser_fromConfigXml() {
- clearDeviceConfig();
ComponentName xmlConfig = new ComponentName("config", "xml");
ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
when(mResources
@@ -9115,51 +9100,6 @@
}
@Test
- public void setDefaultAssistantForUser_fromDeviceConfig() {
- ComponentName xmlConfig = new ComponentName("xml", "config");
- ComponentName deviceConfig = new ComponentName("device", "config");
- setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
- when(mResources
- .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
- .thenReturn(xmlConfig.flattenToString());
- when(mContext.getResources()).thenReturn(mResources);
- when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
- .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
- when(mAssistants.getDefaultComponents())
- .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
- mService.setNotificationAssistantAccessGrantedCallback(
- mNotificationAssistantAccessGrantedCallback);
-
- mService.setDefaultAssistantForUser(0);
-
- verify(mNotificationAssistantAccessGrantedCallback)
- .onGranted(eq(deviceConfig), eq(0), eq(true), eq(false));
- }
-
- @Test
- public void setDefaultAssistantForUser_deviceConfigInvalid() {
- ComponentName xmlConfig = new ComponentName("xml", "config");
- ComponentName deviceConfig = new ComponentName("device", "config");
- setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
- when(mResources
- .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
- .thenReturn(xmlConfig.flattenToString());
- when(mContext.getResources()).thenReturn(mResources);
- // Only xmlConfig is valid, deviceConfig is not.
- when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
- .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
- when(mAssistants.getDefaultComponents())
- .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
- mService.setNotificationAssistantAccessGrantedCallback(
- mNotificationAssistantAccessGrantedCallback);
-
- mService.setDefaultAssistantForUser(0);
-
- verify(mNotificationAssistantAccessGrantedCallback)
- .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false));
- }
-
- @Test
public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
generateResetComponentValues();
@@ -11006,7 +10946,6 @@
tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
- setDefaultAssistantInDeviceConfig("");
mService.loadDefaultApprovedServices(USER_SYSTEM);
@@ -13425,7 +13364,6 @@
throws Exception {
when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true);
// Given: a notification has the flag FLAG_ONGOING_EVENT set
- setDpmAppOppsExemptFromDismissal(false);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
@@ -13451,7 +13389,6 @@
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
mPkg)).thenReturn(AppOpsManager.MODE_ALLOWED);
// Given: a notification has the flag FLAG_ONGOING_EVENT set
- setDpmAppOppsExemptFromDismissal(true);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
@@ -13459,8 +13396,8 @@
// When: fix the notification with NotificationManagerService
mService.fixNotification(n, mPkg, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
- // Then: the notification's flag FLAG_NO_DISMISS should be cleared
- assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+ // Then: the notification's flag FLAG_NO_DISMISS should be set
+ assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
}
@Test
@@ -13468,9 +13405,8 @@
throws Exception {
when(mAppOpsManager.checkOpNoThrow(
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
- mPkg)).thenReturn(AppOpsManager.MODE_ALLOWED);
+ mPkg)).thenReturn(AppOpsManager.MODE_IGNORED);
// Given: a notification has the flag FLAG_ONGOING_EVENT set
- setDpmAppOppsExemptFromDismissal(false);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
@@ -15347,7 +15283,7 @@
}
@Test
- @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+ @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
public void rankingTime_newNotification_noisy_matchesSbn() throws Exception {
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, mUserId);
@@ -15361,7 +15297,7 @@
}
@Test
- @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+ @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
public void rankingTime_newNotification_silent_matchesSbn() throws Exception {
NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
NotificationRecord nr = generateNotificationRecord(low, mUserId);
@@ -15376,7 +15312,7 @@
}
@Test
- @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+ @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
public void rankingTime_updatedNotification_silentSameText_originalPostTime() throws Exception {
NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
NotificationRecord nr = generateNotificationRecord(low, mUserId);
@@ -15396,7 +15332,7 @@
}
@Test
- @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+ @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
public void rankingTime_updatedNotification_silentNewText_newPostTime() throws Exception {
NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
NotificationRecord nr = generateNotificationRecord(low, 0, mUserId);
@@ -15421,7 +15357,7 @@
}
@Test
- @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+ @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
public void rankingTime_updatedNotification_noisySameText_newPostTime() throws Exception {
NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
NotificationRecord nr = generateNotificationRecord(low, mUserId);
@@ -15551,14 +15487,6 @@
PendingIntent.FLAG_MUTABLE);
}
- private void setDpmAppOppsExemptFromDismissal(boolean isOn) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
- /* name= */ "application_exemptions",
- String.valueOf(isOn),
- /* makeDefault= */ false);
- }
-
private void allowTestPackageToToast() throws Exception {
assertWithMessage("toast queue").that(mService.mToastQueue).isEmpty();
mService.isSystemUid = false;
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 9a58594..d1880d2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -1561,14 +1561,14 @@
mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
false, mClock);
- loadByteArrayXml(baos.toByteArray(), false, USER_SYSTEM);
+ loadByteArrayXml(baos.toByteArray(), false, USER_ALL);
// Trigger 2nd restore pass
- when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_P);
+ when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_R);
mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
- new int[]{UID_P});
+ new int[]{UID_R});
- NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_P, id,
+ NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_R, id,
false);
assertThat(channel.getImportance()).isEqualTo(2);
assertThat(channel.canShowBadge()).isTrue();
@@ -1616,7 +1616,7 @@
mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
false, mClock);
- loadByteArrayXml(xml.getBytes(), false, USER_SYSTEM);
+ loadByteArrayXml(xml.getBytes(), false, USER_ALL);
// Trigger 2nd restore pass
mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 527001d..9a6e818 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -378,7 +378,7 @@
}
@Test
- @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME, Flags.FLAG_UPDATE_RANKING_TIME})
+ @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
public void testSort_oldWhenChildren_unspecifiedSummary() {
NotificationRecord child1 = new NotificationRecord(mContext,
new StatusBarNotification(
@@ -430,7 +430,7 @@
}
@Test
- @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME, Flags.FLAG_UPDATE_RANKING_TIME})
+ @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
public void testSort_oldChildren_unspecifiedSummary() {
NotificationRecord child1 = new NotificationRecord(mContext,
new StatusBarNotification(
@@ -480,7 +480,7 @@
}
@Test
- @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME, Flags.FLAG_UPDATE_RANKING_TIME})
+ @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
public void testSort_oldChildren_oldSummary() {
NotificationRecord child1 = new NotificationRecord(mContext,
new StatusBarNotification(
@@ -517,10 +517,10 @@
mUser, null, System.currentTimeMillis()), getLowChannel());
ArrayList<NotificationRecord> expected = new ArrayList<>();
+ expected.add(unrelated);
expected.add(summary);
expected.add(child2);
expected.add(child1);
- expected.add(unrelated);
ArrayList<NotificationRecord> actual = new ArrayList<>();
actual.addAll(expected);
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 9559a25..5fdb396 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -6095,6 +6095,67 @@
assertThat(readPolicy.allowConversations()).isFalse();
}
+ @Test
+ @EnableFlags(Flags.FLAG_MODES_API)
+ @DisableFlags(Flags.FLAG_MODES_UI)
+ public void setNotificationPolicy_updatesRulePolicies_ifRulePolicyIsDefaultOrGlobalPolicy() {
+ ZenPolicy defaultZenPolicy = mZenModeHelper.getDefaultZenPolicy();
+ Policy previousManualPolicy = mZenModeHelper.mConfig.toNotificationPolicy();
+ ZenPolicy previousManualZenPolicy = ZenAdapters.notificationPolicyToZenPolicy(
+ previousManualPolicy);
+ ZenPolicy customZenPolicy = new ZenPolicy.Builder(defaultZenPolicy).allowConversations(
+ CONVERSATION_SENDERS_ANYONE).build();
+
+ mZenModeHelper.mConfig.automaticRules.clear();
+ addZenRule(mZenModeHelper.mConfig, "appWithDefault", "app.pkg",
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS, defaultZenPolicy);
+ addZenRule(mZenModeHelper.mConfig, "appWithSameAsManual", "app.pkg",
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS, previousManualZenPolicy);
+ addZenRule(mZenModeHelper.mConfig, "appWithCustom", "app.pkg",
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS, customZenPolicy);
+ addZenRule(mZenModeHelper.mConfig, "appWithOtherFilter", "app.pkg",
+ ZEN_MODE_ALARMS, null);
+ addZenRule(mZenModeHelper.mConfig, "systemWithDefault", "android",
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS, defaultZenPolicy);
+ addZenRule(mZenModeHelper.mConfig, "systemWithSameAsManual", "android",
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS, previousManualZenPolicy);
+
+ Policy newManualPolicy = new Policy(PRIORITY_CATEGORY_EVENTS, 0, 0);
+ mZenModeHelper.setNotificationPolicy(newManualPolicy, UPDATE_ORIGIN_USER, 0);
+ ZenPolicy newManualZenPolicy = ZenAdapters.notificationPolicyToZenPolicy(newManualPolicy);
+
+ // Only app rules with default or same-as-manual policies were updated.
+ assertThat(mZenModeHelper.mConfig.automaticRules.get("appWithDefault").zenPolicy)
+ .isEqualTo(newManualZenPolicy);
+ assertThat(mZenModeHelper.mConfig.automaticRules.get("appWithSameAsManual").zenPolicy)
+ .isEqualTo(newManualZenPolicy);
+
+ assertThat(mZenModeHelper.mConfig.automaticRules.get("appWithCustom").zenPolicy)
+ .isEqualTo(customZenPolicy);
+ assertThat(mZenModeHelper.mConfig.automaticRules.get("appWithOtherFilter").zenPolicy)
+ .isNull();
+ assertThat(mZenModeHelper.mConfig.automaticRules.get("systemWithDefault").zenPolicy)
+ .isEqualTo(defaultZenPolicy);
+ assertThat(mZenModeHelper.mConfig.automaticRules.get("systemWithSameAsManual").zenPolicy)
+ .isEqualTo(previousManualZenPolicy);
+ }
+
+ private static void addZenRule(ZenModeConfig config, String id, String ownerPkg, int zenMode,
+ @Nullable ZenPolicy zenPolicy) {
+ ZenRule rule = new ZenRule();
+ rule.id = id;
+ rule.pkg = ownerPkg;
+ rule.enabled = true;
+ rule.zenMode = zenMode;
+ rule.zenPolicy = zenPolicy;
+ // Plus stuff so that isValidAutomaticRule() passes
+ rule.name = String.format("Rule %s from %s with mode=%s and policy=%s", id, ownerPkg,
+ zenMode, zenPolicy);
+ rule.conditionId = Uri.parse(rule.name);
+
+ config.automaticRules.put(id, rule);
+ }
+
private static final Correspondence<ZenRule, ZenRule> IGNORE_METADATA =
Correspondence.transforming(zr -> {
Parcel p = Parcel.obtain();
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 30eb5ef..1da5001 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -116,6 +116,7 @@
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
import android.app.ActivityOptions;
import android.app.AppOpsManager;
@@ -3507,6 +3508,23 @@
}
@Test
+ public void testIsCameraActive() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final DisplayRotationCompatPolicy displayRotationCompatPolicy = mock(
+ DisplayRotationCompatPolicy.class);
+ when(mDisplayContent.getDisplayRotationCompatPolicy()).thenReturn(
+ displayRotationCompatPolicy);
+
+ when(displayRotationCompatPolicy.isCameraActive(any(ActivityRecord.class),
+ anyBoolean())).thenReturn(false);
+ assertFalse(app.mActivityRecord.isCameraActive());
+
+ when(displayRotationCompatPolicy.isCameraActive(any(ActivityRecord.class),
+ anyBoolean())).thenReturn(true);
+ assertTrue(app.mActivityRecord.isCameraActive());
+ }
+
+ @Test
public void testUpdateCameraCompatStateFromUser_clickedOnDismiss() throws RemoteException {
final ActivityRecord activity = createActivityWithTask();
// Mock a flag being enabled.
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 ab8c53c..a39a1a8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -167,8 +167,18 @@
assertThat(typeToString(backNavigationInfo.getType()))
.isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+ // reset drawing status to test if previous task is translucent activity
+ backNavigationInfo.onBackNavigationFinished(false);
+ mBackNavigationController.clearBackAnimations();
+ // simulate translucent
+ recordA.setOccludesParent(false);
+ backNavigationInfo = startBackNavigation();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+
// reset drawing status to test keyguard occludes
topActivity.setOccludesParent(true);
+ recordA.setOccludesParent(true);
backNavigationInfo.onBackNavigationFinished(false);
mBackNavigationController.clearBackAnimations();
makeWindowVisibleAndDrawn(topActivity.findMainWindow());
diff --git a/services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java b/services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java
new file mode 100644
index 0000000..e468fd8
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+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.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.mock;
+
+import android.content.ComponentName;
+import android.hardware.camera2.CameraManager;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Tests for {@link DisplayRotationCompatPolicy}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayRotationCompatPolicyTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public final class CameraStateMonitorTests extends WindowTestsBase {
+
+ private static final String TEST_PACKAGE_1 = "com.test.package.one";
+ private static final String TEST_PACKAGE_2 = "com.test.package.two";
+ private static final String CAMERA_ID_1 = "camera-1";
+ private static final String CAMERA_ID_2 = "camera-2";
+ private static final String TEST_PACKAGE_1_LABEL = "testPackage1";
+ private CameraManager mMockCameraManager;
+ private Handler mMockHandler;
+ private LetterboxConfiguration mLetterboxConfiguration;
+
+ private CameraStateMonitor mCameraStateMonitor;
+ private CameraManager.AvailabilityCallback mCameraAvailabilityCallback;
+
+ private ActivityRecord mActivity;
+ private Task mTask;
+
+ // Simulates a listener which will not react to the change on a particular activity.
+ private final FakeCameraCompatStateListener mNotInterestedListener =
+ new FakeCameraCompatStateListener(
+ /*onCameraOpenedReturnValue=*/ false,
+ /*simulateUnsuccessfulCloseOnce=*/ false);
+ // Simulates a listener which will react to the change on a particular activity - for example
+ // put the activity in a camera compat mode.
+ private final FakeCameraCompatStateListener mInterestedListener =
+ new FakeCameraCompatStateListener(
+ /*onCameraOpenedReturnValue=*/ true,
+ /*simulateUnsuccessfulCloseOnce=*/ false);
+ // Simulates a listener which for some reason cannot process `onCameraClosed` event once it
+ // first arrives - this means that the update needs to be postponed.
+ private final FakeCameraCompatStateListener mListenerCannotClose =
+ new FakeCameraCompatStateListener(
+ /*onCameraOpenedReturnValue=*/ true,
+ /*simulateUnsuccessfulCloseOnce=*/ true);
+
+ @Before
+ public void setUp() throws Exception {
+ mLetterboxConfiguration = mDisplayContent.mWmService.mLetterboxConfiguration;
+ spyOn(mLetterboxConfiguration);
+ when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled())
+ .thenReturn(true);
+ when(mLetterboxConfiguration.isCameraCompatRefreshEnabled())
+ .thenReturn(true);
+ when(mLetterboxConfiguration.isCameraCompatRefreshCycleThroughStopEnabled())
+ .thenReturn(true);
+
+ mMockCameraManager = mock(CameraManager.class);
+ doAnswer(invocation -> {
+ mCameraAvailabilityCallback = invocation.getArgument(1);
+ return null;
+ }).when(mMockCameraManager).registerAvailabilityCallback(
+ any(Executor.class), any(CameraManager.AvailabilityCallback.class));
+
+ spyOn(mContext);
+ when(mContext.getSystemService(CameraManager.class)).thenReturn(mMockCameraManager);
+
+ spyOn(mDisplayContent);
+
+ mDisplayContent.setIgnoreOrientationRequest(true);
+
+ mMockHandler = mock(Handler.class);
+
+ when(mMockHandler.postDelayed(any(Runnable.class), anyLong())).thenAnswer(
+ invocation -> {
+ ((Runnable) invocation.getArgument(0)).run();
+ return null;
+ });
+ mCameraStateMonitor =
+ new CameraStateMonitor(mDisplayContent, mMockHandler);
+ configureActivity(TEST_PACKAGE_1);
+ configureActivity(TEST_PACKAGE_2);
+
+ mCameraStateMonitor.startListeningToCameraState();
+ }
+
+ @After
+ public void tearDown() {
+ // Remove all listeners.
+ mCameraStateMonitor.removeCameraStateListener(mNotInterestedListener);
+ mCameraStateMonitor.removeCameraStateListener(mInterestedListener);
+ mCameraStateMonitor.removeCameraStateListener(mListenerCannotClose);
+
+ // Reset the listener's state.
+ mNotInterestedListener.resetCounters();
+ mInterestedListener.resetCounters();
+ mListenerCannotClose.resetCounters();
+ }
+
+ @Test
+ public void testOnCameraOpened_listenerAdded_notifiesCameraOpened() {
+ mCameraStateMonitor.addCameraStateListener(mNotInterestedListener);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+ assertEquals(1, mNotInterestedListener.mOnCameraOpenedCounter);
+ }
+
+ @Test
+ public void testOnCameraOpened_listenerReturnsFalse_doesNotNotifyCameraClosed() {
+ mCameraStateMonitor.addCameraStateListener(mNotInterestedListener);
+ // Listener returns false on `onCameraOpened`.
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+ mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+
+ assertEquals(0, mNotInterestedListener.mOnCameraClosedCounter);
+ }
+
+ @Test
+ public void testOnCameraOpened_listenerReturnsTrue_notifyCameraClosed() {
+ mCameraStateMonitor.addCameraStateListener(mInterestedListener);
+ // Listener returns true on `onCameraOpened`.
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+ mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+
+ assertEquals(1, mInterestedListener.mOnCameraClosedCounter);
+ }
+
+ @Test
+ public void testOnCameraOpened_listenerCannotCloseYet_notifyCameraClosedAgain() {
+ mCameraStateMonitor.addCameraStateListener(mListenerCannotClose);
+ // Listener returns true on `onCameraOpened`.
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+ mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+
+ assertEquals(2, mListenerCannotClose.mOnCameraClosedCounter);
+ }
+
+ @Test
+ public void testReconnectedToDifferentCamera_notifiesListener() {
+ mCameraStateMonitor.addCameraStateListener(mInterestedListener);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+ mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_2, TEST_PACKAGE_1);
+
+ assertEquals(2, mInterestedListener.mOnCameraOpenedCounter);
+ }
+
+ @Test
+ public void testDifferentAppConnectedToCamera_notifiesListener() {
+ mCameraStateMonitor.addCameraStateListener(mInterestedListener);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+ mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_2);
+
+ assertEquals(2, mInterestedListener.mOnCameraOpenedCounter);
+ }
+
+ @Test
+ public void testCameraAlreadyClosed_notifiesListenerOnce() {
+ mCameraStateMonitor.addCameraStateListener(mInterestedListener);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+ mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+ mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
+
+ assertEquals(1, mInterestedListener.mOnCameraClosedCounter);
+ }
+
+ private void configureActivity(@NonNull String packageName) {
+ mTask = new TaskBuilder(mSupervisor)
+ .setDisplay(mDisplayContent)
+ .build();
+
+ mActivity = new ActivityBuilder(mAtm)
+ .setComponent(new ComponentName(packageName, ".TestActivity"))
+ .setTask(mTask)
+ .build();
+
+ spyOn(mActivity.mAtmService.getLifecycleManager());
+ spyOn(mActivity.mLetterboxUiController);
+
+ doReturn(mActivity).when(mDisplayContent).topRunningActivity(anyBoolean());
+ }
+
+ private class FakeCameraCompatStateListener implements
+ CameraStateMonitor.CameraCompatStateListener {
+
+ int mOnCameraOpenedCounter = 0;
+ int mOnCameraClosedCounter = 0;
+
+ boolean mOnCameraOpenedReturnValue = true;
+ private boolean mOnCameraClosedReturnValue = true;
+
+ /**
+ * @param simulateUnsuccessfulCloseOnce When false, returns `true` on every
+ * `onCameraClosed`. When true, returns `false` on the
+ * first `onCameraClosed` callback, and `true on the
+ * subsequent calls. This fake implementation tests the
+ * retry mechanism in {@link CameraStateMonitor}.
+ */
+ FakeCameraCompatStateListener(boolean onCameraOpenedReturnValue,
+ boolean simulateUnsuccessfulCloseOnce) {
+ mOnCameraOpenedReturnValue = onCameraOpenedReturnValue;
+ mOnCameraClosedReturnValue = !simulateUnsuccessfulCloseOnce;
+ }
+
+ @Override
+ public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity,
+ @NonNull String cameraId) {
+ mOnCameraOpenedCounter++;
+ return mOnCameraOpenedReturnValue;
+ }
+
+ @Override
+ public boolean onCameraClosed(@NonNull ActivityRecord cameraActivity,
+ @NonNull String cameraId) {
+ mOnCameraClosedCounter++;
+ boolean returnValue = mOnCameraClosedReturnValue;
+ // If false, return false only the first time, so it doesn't fall in the infinite retry
+ // loop.
+ mOnCameraClosedReturnValue = true;
+ return returnValue;
+ }
+
+ void resetCounters() {
+ mOnCameraOpenedCounter = 0;
+ mOnCameraClosedCounter = 0;
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index 353ba01..f92387c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -21,18 +21,16 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.server.wm.DesktopModeLaunchParamsModifier.DESKTOP_MODE_INITIAL_BOUNDS_SCALE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
-import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
@@ -71,44 +69,54 @@
@Before
public void setUp() throws Exception {
mActivity = new ActivityBuilder(mAtm).build();
- mTarget = spy(new DesktopModeLaunchParamsModifier(mContext));
- doReturn(true).when(mTarget).isDesktopModeSupported(any());
mCurrent = new LaunchParamsController.LaunchParams();
mCurrent.reset();
mResult = new LaunchParamsController.LaunchParams();
mResult.reset();
+
+ mTarget = new DesktopModeLaunchParamsModifier(mContext);
}
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsContinueIfDesktopWindowingIsDisabled() {
+ setupDesktopModeLaunchParamsModifier();
+
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsContinueIfDesktopWindowingIsEnabledOnUnsupportedDevice() {
- doReturn(false).when(mTarget).isDesktopModeSupported(any());
+ setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ false,
+ /*enforceDeviceRestrictions=*/ true);
+
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- public void testReturnsDoneIfDesktopWindowingIsEnabledAndUnsupportedDeviceOverridden() {
- doReturn(false).when(mTarget).enforceDeviceRestrictions();
+ public void testReturnsContinueIfDesktopWindowingIsEnabledAndUnsupportedDeviceOverridden() {
+ setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ true,
+ /*enforceDeviceRestrictions=*/ false);
+
final Task task = new TaskBuilder(mSupervisor).build();
- assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfTaskIsNull() {
+ setupDesktopModeLaunchParamsModifier();
+
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfNotBoundsPhase() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).build();
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).setPhase(
PHASE_DISPLAY).calculate());
@@ -117,6 +125,8 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfTaskNotUsingActivityTypeStandardOrUndefined() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_ASSISTANT).build();
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
@@ -124,23 +134,29 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- public void testReturnsDoneIfTaskUsingActivityTypeStandard() {
+ public void testReturnsContinueIfTaskUsingActivityTypeStandard() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
- assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- public void testReturnsDoneIfTaskUsingActivityTypeUndefined() {
+ public void testReturnsContinueIfTaskUsingActivityTypeUndefined() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_UNDEFINED).build();
- assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfCurrentParamsHasBounds() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
mCurrent.mBounds.set(/* left */ 0, /* top */ 0, /* right */ 100, /* bottom */ 100);
@@ -150,6 +166,8 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testUsesDefaultBounds() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
final int displayHeight = 1600;
@@ -157,7 +175,7 @@
task.getDisplayArea().setBounds(new Rect(0, 0, displayWidth, displayHeight));
final int desiredWidth = (int) (displayWidth * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredHeight = (int) (displayHeight * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -165,17 +183,32 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testUsesDisplayAreaAndWindowingModeFromSource() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
TaskDisplayArea mockTaskDisplayArea = mock(TaskDisplayArea.class);
mCurrent.mPreferredTaskDisplayArea = mockTaskDisplayArea;
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
- assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
assertEquals(mockTaskDisplayArea, mResult.mPreferredTaskDisplayArea);
assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode);
}
+ private void setupDesktopModeLaunchParamsModifier() {
+ setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ true,
+ /*enforceDeviceRestrictions=*/ true);
+ }
+
+ private void setupDesktopModeLaunchParamsModifier(boolean isDesktopModeSupported,
+ boolean enforceDeviceRestrictions) {
+ doReturn(isDesktopModeSupported)
+ .when(() -> DesktopModeLaunchParamsModifier.isDesktopModeSupported(any()));
+ doReturn(enforceDeviceRestrictions)
+ .when(DesktopModeLaunchParamsModifier::enforceDeviceRestrictions);
+ }
+
private class CalculateRequestBuilder {
private Task mTask;
private int mPhase = PHASE_BOUNDS;
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 7356b43..27d9d13 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1071,6 +1071,7 @@
@Test
public void testAllowsTopmostFullscreenOrientation() {
final DisplayContent dc = createNewDisplay();
+ assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, dc.getOrientation());
dc.getDisplayRotation().setFixedToUserRotation(
IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
@@ -1717,7 +1718,6 @@
// The display should be rotated after the launch is finished.
doReturn(false).when(app).isAnimating(anyInt(), anyInt());
mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
- waitHandlerIdle(mWm.mH);
mStatusBarWindow.finishSeamlessRotation(t);
mNavBarWindow.finishSeamlessRotation(t);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
index 0dd0239..262ba8b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
@@ -38,6 +38,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -129,13 +130,17 @@
((Runnable) invocation.getArgument(0)).run();
return null;
});
- mDisplayRotationCompatPolicy = new DisplayRotationCompatPolicy(
- mDisplayContent, mMockHandler);
+ CameraStateMonitor cameraStateMonitor =
+ new CameraStateMonitor(mDisplayContent, mMockHandler);
+ mDisplayRotationCompatPolicy =
+ new DisplayRotationCompatPolicy(mDisplayContent, mMockHandler, cameraStateMonitor);
// Do not show the real toast.
spyOn(mDisplayRotationCompatPolicy);
doNothing().when(mDisplayRotationCompatPolicy).showToast(anyInt());
doNothing().when(mDisplayRotationCompatPolicy).showToast(anyInt(), anyString());
+
+ cameraStateMonitor.startListeningToCameraState();
}
@Test
@@ -534,6 +539,42 @@
assertActivityRefreshRequested(/* refreshRequested */ true, /* cycleThroughStop */ false);
}
+ @Test
+ public void testIsCameraActiveWhenCallbackInvokedNoMultiWindow_returnTrue() {
+ configureActivity(SCREEN_ORIENTATION_PORTRAIT);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+ assertTrue(
+ mDisplayRotationCompatPolicy.isCameraActive(mActivity, /* mustBeFullscreen*/ true));
+ }
+
+ @Test
+ public void testIsCameraActiveWhenCallbackNotInvokedNoMultiWindow_returnFalse() {
+ configureActivity(SCREEN_ORIENTATION_PORTRAIT);
+
+ assertFalse(
+ mDisplayRotationCompatPolicy.isCameraActive(mActivity, /* mustBeFullscreen*/ true));
+ }
+
+ @Test
+ public void testIsCameraActiveWhenCallbackNotInvokedMultiWindow_returnFalse() {
+ configureActivity(SCREEN_ORIENTATION_PORTRAIT);
+ when(mActivity.inMultiWindowMode()).thenReturn(true);
+
+ assertFalse(
+ mDisplayRotationCompatPolicy.isCameraActive(mActivity, /* mustBeFullscreen*/ true));
+ }
+
+ @Test
+ public void testIsCameraActiveWhenCallbackInvokedMultiWindow_returnFalse() {
+ configureActivity(SCREEN_ORIENTATION_PORTRAIT);
+ when(mActivity.inMultiWindowMode()).thenReturn(true);
+ mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+ assertFalse(
+ mDisplayRotationCompatPolicy.isCameraActive(mActivity, /* mustBeFullscreen*/ true));
+ }
+
private void configureActivity(@ScreenOrientation int activityOrientation) {
configureActivityAndDisplay(activityOrientation, ORIENTATION_PORTRAIT);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index b41db31..b74da1a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -29,6 +29,7 @@
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
@@ -73,6 +74,8 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.annotation.Nullable;
@@ -1086,6 +1089,39 @@
assertFalse(mController.shouldApplyUserMinAspectRatioOverride());
}
+ @Test
+ public void testRecomputeConfigurationForCameraCompatIfNeeded() {
+ spyOn(mController);
+ doReturn(false).when(mController).isOverrideOrientationOnlyForCameraEnabled();
+ doReturn(false).when(mController).isCameraCompatSplitScreenAspectRatioAllowed();
+ doReturn(false).when(mController).shouldOverrideMinAspectRatioForCamera();
+ clearInvocations(mActivity);
+
+ mController.recomputeConfigurationForCameraCompatIfNeeded();
+
+ verify(mActivity, never()).recomputeConfiguration();
+
+ // isOverrideOrientationOnlyForCameraEnabled
+ doReturn(true).when(mController).isOverrideOrientationOnlyForCameraEnabled();
+ clearInvocations(mActivity);
+ mController.recomputeConfigurationForCameraCompatIfNeeded();
+ verify(mActivity).recomputeConfiguration();
+
+ // isCameraCompatSplitScreenAspectRatioAllowed
+ doReturn(false).when(mController).isOverrideOrientationOnlyForCameraEnabled();
+ doReturn(true).when(mController).isCameraCompatSplitScreenAspectRatioAllowed();
+ clearInvocations(mActivity);
+ mController.recomputeConfigurationForCameraCompatIfNeeded();
+ verify(mActivity).recomputeConfiguration();
+
+ // shouldOverrideMinAspectRatioForCamera
+ doReturn(false).when(mController).isCameraCompatSplitScreenAspectRatioAllowed();
+ doReturn(true).when(mController).shouldOverrideMinAspectRatioForCamera();
+ clearInvocations(mActivity);
+ mController.recomputeConfigurationForCameraCompatIfNeeded();
+ verify(mActivity).recomputeConfiguration();
+ }
+
private void prepareActivityForShouldApplyUserMinAspectRatioOverride(
boolean orientationRequest) {
spyOn(mController);
@@ -1280,6 +1316,78 @@
}
@Test
+ @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA})
+ public void shouldOverrideMinAspectRatioForCamera_overrideEnabled_returnsTrue() {
+ doReturn(true).when(mActivity).isCameraActive();
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertTrue(mController.shouldOverrideMinAspectRatioForCamera());
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA})
+ public void shouldOverrideMinAspectRatioForCamera_propertyTrue_overrideEnabled_returnsTrue()
+ throws Exception {
+ doReturn(true).when(mActivity).isCameraActive();
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ true);
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertTrue(mController.shouldOverrideMinAspectRatioForCamera());
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA})
+ public void shouldOverrideMinAspectRatioForCamera_propertyTrue_overrideEnabled_returnsFalse()
+ throws Exception {
+ doReturn(false).when(mActivity).isCameraActive();
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ true);
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertFalse(mController.shouldOverrideMinAspectRatioForCamera());
+ }
+
+ @Test
+ @DisableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA})
+ public void shouldOverrideMinAspectRatioForCamera_propertyTrue_overrideDisabled_returnsFalse()
+ throws Exception {
+ doReturn(true).when(mActivity).isCameraActive();
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ true);
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertFalse(mController.shouldOverrideMinAspectRatioForCamera());
+ }
+
+ @Test
+ @DisableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA})
+ public void shouldOverrideMinAspectRatioForCamera_overrideDisabled_returnsFalse() {
+ doReturn(true).when(mActivity).isCameraActive();
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertFalse(mController.shouldOverrideMinAspectRatioForCamera());
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA})
+ public void shouldOverrideMinAspectRatioForCamera_propertyFalse_overrideEnabled_returnsFalse()
+ throws Exception {
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ false);
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertFalse(mController.shouldOverrideMinAspectRatioForCamera());
+ }
+
+ @Test
+ @DisableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA})
+ public void shouldOverrideMinAspectRatioForCamera_propertyFalse_noOverride_returnsFalse()
+ throws Exception {
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ false);
+ doReturn(true).when(mActivity).isCameraActive();
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertFalse(mController.shouldOverrideMinAspectRatioForCamera());
+ }
+
+ @Test
@EnableCompatChanges({FORCE_RESIZE_APP})
public void testshouldOverrideForceResizeApp_overrideEnabled_returnsTrue() {
mController = new LetterboxUiController(mWm, mActivity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index dcf3dad..7756edd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -832,7 +832,8 @@
// Assume the task is at the topmost position
assertFalse(rootTask.isTopRootTaskInDisplayArea());
- doReturn(taskDisplayArea.getHomeActivity()).when(taskDisplayArea).topRunningActivity();
+ doReturn(taskDisplayArea.getHomeActivity()).when(taskDisplayArea).topRunningActivity(
+ anyBoolean());
// Use the task as target to resume.
mRootWindowContainer.resumeFocusedTasksTopActivities();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index ac1dc08..8677738 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -4193,11 +4193,49 @@
}
@Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION})
+ public void testPortraitCloseToSquareDisplayWithTaskbar_insetsOverridden_notLetterboxed() {
+ // Set up portrait close to square display.
+ setUpDisplaySizeWithApp(2200, 2280);
+ final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ // Simulate insets, final app bounds are (0, 0, 2200, 2130) - landscape.
+ final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
+ "navbar");
+ final Binder owner = new Binder();
+ navbar.mAttrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars())
+ .setInsetsSize(Insets.of(0, 0, 0, 150))
+ };
+ display.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
+ assertTrue(display.getDisplayPolicy().updateDecorInsetsInfo());
+ display.sendNewConfiguration();
+
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // Activity should not be letterboxed and should have portrait app bounds even though
+ // orientation is not respected with insets as insets have been decoupled.
+ final Rect appBounds = activity.getWindowConfiguration().getAppBounds();
+ final Rect displayBounds = display.getBounds();
+ assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertNotNull(appBounds);
+ assertEquals(displayBounds.width(), appBounds.width());
+ assertEquals(displayBounds.height(), appBounds.height());
+ }
+
+ @Test
@DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
public void testPortraitCloseToSquareDisplayWithTaskbar_letterboxed() {
// Set up portrait close to square display
setUpDisplaySizeWithApp(2200, 2280);
final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
// Simulate taskbar, final app bounds are (0, 0, 2200, 2130) - landscape
final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
"navbar");
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 b9fe074..87f26e5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -200,6 +200,7 @@
.mockStatic(DisplayControl.class, mockStubOnly)
.mockStatic(LockGuard.class, mockStubOnly)
.mockStatic(Watchdog.class, mockStubOnly)
+ .spyStatic(DesktopModeLaunchParamsModifier.class)
.strictness(Strictness.LENIENT)
.startMocking();
@@ -425,6 +426,9 @@
if (dc.mDisplayRotationCompatPolicy != null) {
dc.mDisplayRotationCompatPolicy.dispose();
}
+ if (dc.mCameraStateMonitor != null) {
+ dc.mCameraStateMonitor.dispose();
+ }
}
}
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 48fc2dc..9f85acb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -565,36 +565,17 @@
@Test
public void testGetOrientation_childSpecified() {
- testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_LANDSCAPE,
- SCREEN_ORIENTATION_LANDSCAPE);
- testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_UNSET,
- SCREEN_ORIENTATION_UNSPECIFIED);
- }
-
- private void testGetOrientation_childSpecifiedConfig(boolean childVisible, int childOrientation,
- int expectedOrientation) {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
- final TestWindowContainer root = builder.setLayer(0).build();
+ final TestWindowContainer root = builder.build();
root.setFillsParent(true);
+ assertEquals(SCREEN_ORIENTATION_UNSET, root.getOrientation());
- builder.setIsVisible(childVisible);
+ final TestWindowContainer child = root.addChildWindow();
+ child.setFillsParent(true);
+ assertEquals(SCREEN_ORIENTATION_UNSET, root.getOrientation());
- if (childOrientation != SCREEN_ORIENTATION_UNSET) {
- builder.setOrientation(childOrientation);
- }
-
- final TestWindowContainer child1 = root.addChildWindow(builder);
- child1.setFillsParent(true);
-
- assertEquals(expectedOrientation, root.getOrientation());
- }
-
- @Test
- public void testGetOrientation_Unset() {
- final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
- final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build();
- // Unspecified well because we didn't specify anything...
- assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation());
+ child.setOverrideOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, root.getOrientation());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 5fe71a1..a78fc10 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -103,6 +103,7 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
+import android.view.WindowRelayoutResult;
import android.window.ActivityWindowInfo;
import android.window.ClientWindowFrames;
import android.window.InputTransferToken;
@@ -262,7 +263,9 @@
}
@Test
- public void testRelayoutExitingWindow() {
+ public void testRelayoutExitingWindow_legacy() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO);
+
final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin");
final WindowSurfaceController surfaceController = mock(WindowSurfaceController.class);
win.mWinAnimator.mSurfaceController = surfaceController;
@@ -320,6 +323,67 @@
}
@Test
+ public void testRelayoutExitingWindow() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO);
+
+ final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin");
+ final WindowSurfaceController surfaceController = mock(WindowSurfaceController.class);
+ win.mWinAnimator.mSurfaceController = surfaceController;
+ win.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+ doReturn(true).when(surfaceController).hasSurface();
+ spyOn(win.mTransitionController);
+ doReturn(true).when(win.mTransitionController).isShellTransitionsEnabled();
+ doReturn(true).when(win.mTransitionController).inTransition(
+ eq(win.mActivityRecord));
+ win.mViewVisibility = View.VISIBLE;
+ win.mHasSurface = true;
+ win.mActivityRecord.mAppStopped = true;
+ mWm.mWindowMap.put(win.mClient.asBinder(), win);
+ spyOn(mWm.mWindowPlacerLocked);
+ // Skip unnecessary operations of relayout.
+ doNothing().when(mWm.mWindowPlacerLocked).performSurfacePlacement(anyBoolean());
+ final int w = 100;
+ final int h = 200;
+ final ClientWindowFrames outFrames = new ClientWindowFrames();
+ final MergedConfiguration outConfig = new MergedConfiguration();
+ final SurfaceControl outSurfaceControl = new SurfaceControl();
+ final InsetsState outInsetsState = new InsetsState();
+ final InsetsSourceControl.Array outControls = new InsetsSourceControl.Array();
+ final WindowRelayoutResult outRelayoutResult = new WindowRelayoutResult(outFrames,
+ outConfig, outSurfaceControl, outInsetsState, outControls);
+ mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.GONE, 0, 0, 0,
+ outRelayoutResult);
+ // The window is in transition, so its destruction is deferred.
+ assertTrue(win.mAnimatingExit);
+ assertFalse(win.mDestroying);
+ assertTrue(win.mTransitionController.mAnimatingExitWindows.contains(win));
+
+ win.mAnimatingExit = false;
+ win.mViewVisibility = View.VISIBLE;
+ win.mActivityRecord.setVisibleRequested(false);
+ win.mActivityRecord.setVisible(false);
+ mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.GONE, 0, 0, 0,
+ outRelayoutResult);
+ // Because the window is already invisible, it doesn't need to apply exiting animation
+ // and WMS#tryStartExitingAnimation() will destroy the surface directly.
+ assertFalse(win.mAnimatingExit);
+ assertFalse(win.mHasSurface);
+ assertNull(win.mWinAnimator.mSurfaceController);
+
+ // Invisible requested activity should not get the last config even if its view is visible.
+ mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0,
+ outRelayoutResult);
+ assertEquals(0, outConfig.getMergedConfiguration().densityDpi);
+ // Non activity window can still get the last config.
+ win.mActivityRecord = null;
+ win.fillClientWindowFramesAndConfiguration(outFrames, outConfig,
+ null /* outActivityWindowInfo*/, false /* useLatestConfig */,
+ true /* relayoutVisible */);
+ assertEquals(win.getConfiguration().densityDpi,
+ outConfig.getMergedConfiguration().densityDpi);
+ }
+
+ @Test
public void testRelayout_firstLayout_dwpcHelperCalledWithCorrectFlags() {
// When doing the first layout, the initial flags should be reported as changed to
// keepActivityOnWindowFlagsChanged.
@@ -417,10 +481,15 @@
win.mRelayoutSeq = 1;
seq = 2;
}
- mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq,
- 0, new ClientWindowFrames(), new MergedConfiguration(),
- new SurfaceControl(), new InsetsState(), new InsetsSourceControl.Array(),
- new Bundle());
+ if (Flags.windowSessionRelayoutInfo()) {
+ mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq,
+ 0, new WindowRelayoutResult());
+ } else {
+ mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq,
+ 0, new ClientWindowFrames(), new MergedConfiguration(),
+ new SurfaceControl(), new InsetsState(), new InsetsSourceControl.Array(),
+ new Bundle());
+ }
ArgumentCaptor<Integer> changedFlags = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Integer> changedPrivateFlags = ArgumentCaptor.forClass(Integer.class);
@@ -1245,8 +1314,9 @@
}
@Test
- public void testRelayout_appWindowSendActivityWindowInfo() {
+ public void testRelayout_appWindowSendActivityWindowInfo_legacy() {
mSetFlagsRule.enableFlags(Flags.FLAG_ACTIVITY_WINDOW_INFO_FLAG);
+ mSetFlagsRule.disableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO);
// Skip unnecessary operations of relayout.
spyOn(mWm.mWindowPlacerLocked);
@@ -1305,6 +1375,65 @@
}
@Test
+ public void testRelayout_appWindowSendActivityWindowInfo() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ACTIVITY_WINDOW_INFO_FLAG);
+ mSetFlagsRule.enableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO);
+
+ // Skip unnecessary operations of relayout.
+ spyOn(mWm.mWindowPlacerLocked);
+ doNothing().when(mWm.mWindowPlacerLocked).performSurfacePlacement(anyBoolean());
+
+ final Task task = createTask(mDisplayContent);
+ final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "appWindow");
+ mWm.mWindowMap.put(win.mClient.asBinder(), win);
+
+ final int w = 100;
+ final int h = 200;
+ final ClientWindowFrames outFrames = new ClientWindowFrames();
+ final MergedConfiguration outConfig = new MergedConfiguration();
+ final SurfaceControl outSurfaceControl = new SurfaceControl();
+ final InsetsState outInsetsState = new InsetsState();
+ final InsetsSourceControl.Array outControls = new InsetsSourceControl.Array();
+ final WindowRelayoutResult outRelayoutResult = new WindowRelayoutResult(outFrames,
+ outConfig, outSurfaceControl, outInsetsState, outControls);
+
+ final ActivityRecord activity = win.mActivityRecord;
+ final ActivityWindowInfo expectedInfo = new ActivityWindowInfo();
+ expectedInfo.set(true, new Rect(0, 0, 1000, 2000), new Rect(0, 0, 500, 2000));
+ doReturn(expectedInfo).when(activity).getActivityWindowInfo();
+ activity.setVisibleRequested(false);
+ activity.setVisible(false);
+
+ mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0,
+ outRelayoutResult);
+
+ // No latest reported value, so return empty when activity is invisible
+ final ActivityWindowInfo activityWindowInfo = outRelayoutResult.activityWindowInfo;
+ assertEquals(new ActivityWindowInfo(), activityWindowInfo);
+
+ activity.setVisibleRequested(true);
+ activity.setVisible(true);
+
+ mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0,
+ outRelayoutResult);
+
+ // Report the latest when activity is visible.
+ final ActivityWindowInfo activityWindowInfo2 = outRelayoutResult.activityWindowInfo;
+ assertEquals(expectedInfo, activityWindowInfo2);
+
+ expectedInfo.set(false, new Rect(0, 0, 1000, 2000), new Rect(0, 0, 1000, 2000));
+ activity.setVisibleRequested(false);
+ activity.setVisible(false);
+
+ mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0,
+ outRelayoutResult);
+
+ // Report the last reported value when activity is invisible.
+ final ActivityWindowInfo activityWindowInfo3 = outRelayoutResult.activityWindowInfo;
+ assertEquals(activityWindowInfo2, activityWindowInfo3);
+ }
+
+ @Test
public void testAddOverlayWindowToUnassignedDisplay_notAllowed_ForVisibleBackgroundUsers() {
doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());
int uid = 100000; // uid for non-system user
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 43b424f..fb854c5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1235,6 +1235,12 @@
assertNotNull(o.mInfo);
assertNotNull(o.mInfo.pictureInPictureParams);
+ // Bypass the quota check, which causes NPE in current test setup.
+ if (mWm.mAtmService.mActivityClientController.mSetPipAspectRatioQuotaTracker != null) {
+ mWm.mAtmService.mActivityClientController.mSetPipAspectRatioQuotaTracker
+ .setEnabled(false);
+ }
+
final PictureInPictureParams p2 = new PictureInPictureParams.Builder()
.setAspectRatio(new Rational(3, 4)).build();
mWm.mAtmService.mActivityClientController.setPictureInPictureParams(record.token, p2);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index e20f822..fbbb9a2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -104,6 +104,7 @@
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.view.WindowRelayoutResult;
import android.view.inputmethod.ImeTracker;
import android.window.ClientWindowFrames;
import android.window.ITaskFragmentOrganizer;
@@ -113,6 +114,7 @@
import com.android.server.testutils.StubTransaction;
import com.android.server.wm.SensitiveContentPackages.PackageInfo;
+import com.android.window.flags.Flags;
import org.junit.After;
import org.junit.Test;
@@ -1350,7 +1352,9 @@
@SetupWindows(addWindows = {W_INPUT_METHOD})
@Test
- public void testImeTargetChangeListener_OnImeTargetOverlayVisibilityChanged() {
+ public void testImeTargetChangeListener_OnImeTargetOverlayVisibilityChanged_legacy() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO);
+
final TestImeTargetChangeListener listener = new TestImeTargetChangeListener();
mWm.mImeTargetChangeListener = listener;
@@ -1404,6 +1408,65 @@
assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse();
}
+ @SetupWindows(addWindows = {W_INPUT_METHOD})
+ @Test
+ public void testImeTargetChangeListener_OnImeTargetOverlayVisibilityChanged() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO);
+
+ final TestImeTargetChangeListener listener = new TestImeTargetChangeListener();
+ mWm.mImeTargetChangeListener = listener;
+
+ // Scenario 1: test addWindow/relayoutWindow to add Ime layering overlay window as visible.
+ final WindowToken windowToken = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
+ mDisplayContent);
+ final IWindow client = new TestIWindow();
+ final Session session = getTestSession();
+ final ClientWindowFrames outFrames = new ClientWindowFrames();
+ final MergedConfiguration outConfig = new MergedConfiguration();
+ final SurfaceControl outSurfaceControl = new SurfaceControl();
+ final InsetsState outInsetsState = new InsetsState();
+ final InsetsSourceControl.Array outControls = new InsetsSourceControl.Array();
+ final WindowRelayoutResult outRelayoutResult = new WindowRelayoutResult(outFrames,
+ outConfig, outSurfaceControl, outInsetsState, outControls);
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ TYPE_APPLICATION_OVERLAY);
+ params.setTitle("imeLayeringTargetOverlay");
+ params.token = windowToken.token;
+ params.flags = FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM;
+
+ mWm.addWindow(session, client, params, View.VISIBLE, DEFAULT_DISPLAY,
+ 0 /* userUd */, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
+ new InsetsSourceControl.Array(), new Rect(), new float[1]);
+ mWm.relayoutWindow(session, client, params, 100, 200, View.VISIBLE, 0, 0, 0,
+ outRelayoutResult);
+ waitHandlerIdle(mWm.mH);
+
+ final WindowState imeLayeringTargetOverlay = mDisplayContent.getWindow(
+ w -> w.mClient.asBinder() == client.asBinder());
+ assertThat(imeLayeringTargetOverlay.isVisible()).isTrue();
+ assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
+ assertThat(listener.mIsRemoved).isFalse();
+ assertThat(listener.mIsVisibleForImeTargetOverlay).isTrue();
+
+ // Scenario 2: test relayoutWindow to let the Ime layering target overlay window invisible.
+ mWm.relayoutWindow(session, client, params, 100, 200, View.GONE, 0, 0, 0,
+ outRelayoutResult);
+ waitHandlerIdle(mWm.mH);
+
+ assertThat(imeLayeringTargetOverlay.isVisible()).isFalse();
+ assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
+ assertThat(listener.mIsRemoved).isFalse();
+ assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse();
+
+ // Scenario 3: test removeWindow to remove the Ime layering target overlay window.
+ mWm.removeClientToken(session, client.asBinder());
+ waitHandlerIdle(mWm.mH);
+
+ assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
+ assertThat(listener.mIsRemoved).isTrue();
+ assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse();
+ }
+
@Test
@RequiresFlagsEnabled(FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION)
public void testIsSecureLocked_sensitiveContentProtectionManagerEnabled() {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index a35a35a..9d14290 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1241,7 +1241,7 @@
break;
case Event.SHORTCUT_INVOCATION:
case Event.CHOOSER_ACTION:
- case Event.STANDBY_BUCKET_CHANGED:
+ // case Event.STANDBY_BUCKET_CHANGED:
case Event.FOREGROUND_SERVICE_START:
case Event.FOREGROUND_SERVICE_STOP:
logAppUsageEventReportedAtomLocked(event.mEventType, uid, event.mPackage);
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index b005715..40ad312 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -959,6 +959,11 @@
*/
public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8;
/**
+ * The satellite modem is being powered off.
+ * @hide
+ */
+ public static final int SATELLITE_MODEM_STATE_DISABLING_SATELLITE = 9;
+ /**
* Satellite modem state is unknown. This generic modem state should be used only when the
* modem state cannot be mapped to other specific modem states.
*/
@@ -976,6 +981,7 @@
SATELLITE_MODEM_STATE_NOT_CONNECTED,
SATELLITE_MODEM_STATE_CONNECTED,
SATELLITE_MODEM_STATE_ENABLING_SATELLITE,
+ SATELLITE_MODEM_STATE_DISABLING_SATELLITE,
SATELLITE_MODEM_STATE_UNKNOWN
})
@Retention(RetentionPolicy.SOURCE)
diff --git a/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml b/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
index 439cf13..1dc1037 100644
--- a/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/AppClose/AndroidTestTemplate.xml b/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
index 4b6224e..57a58c8 100644
--- a/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml b/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
index 583bcb7..2cb86e0 100644
--- a/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml b/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
index d6ae2b3..2cf85fa 100644
--- a/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/IME/AndroidTestTemplate.xml b/tests/FlickerTests/IME/AndroidTestTemplate.xml
index 988f76f..b93e1be 100644
--- a/tests/FlickerTests/IME/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/IME/AndroidTestTemplate.xml
@@ -8,8 +8,12 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
+ <!-- enable AOD -->
+ <option name="set-secure-setting" key="doze_always_on" value="1" />
<!-- prevents the phone from restarting -->
<option name="force-skip-system-props" value="true"/>
<!-- set WM tracing verbose level to all -->
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index 063088d..03f3a68 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -50,7 +50,7 @@
testApp.launchViaIntent(wmHelper)
testApp.openIME(wmHelper)
this.setRotation(flicker.scenario.startRotation)
- if (flicker.scenario.isTablet) {
+ if (flicker.scenario.isTablet && tapl.isTransientTaskbar()) {
tapl.launchedAppState.swipeUpToUnstashTaskbar()
}
tapl.launchedAppState.switchToOverview()
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
new file mode 100644
index 0000000..31506b5
--- /dev/null
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.ime
+
+import android.platform.test.annotations.Presubmit
+import android.platform.test.rule.UnlockScreenRule
+import android.tools.Rotation
+import android.tools.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.flicker.legacy.FlickerBuilder
+import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
+import com.android.server.wm.flicker.BaseTest
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test IME window closing on lock and opening on screen unlock. To run this test: `atest
+ * FlickerTests:CloseImeWindowToHomeTest`
+ */
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ShowImeOnUnlockScreenTest(flicker: LegacyFlickerTest) : BaseTest(flicker) {
+ private val testApp = ImeAppHelper(instrumentation)
+ private val imeOrSnapshot = ComponentNameMatcher.IME.or(ComponentNameMatcher.IME_SNAPSHOT)
+
+ /** {@inheritDoc} */
+ override val transition: FlickerBuilder.() -> Unit = {
+ setup {
+ tapl.expectedRotationCheckEnabled = false
+ testApp.launchViaIntent(wmHelper)
+ testApp.openIME(wmHelper)
+ }
+ transitions {
+ device.sleep()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+ UnlockScreenRule.unlockScreen(device)
+ wmHelper.StateSyncBuilder().withImeShown().waitForAndVerify()
+ }
+ teardown { testApp.exit(wmHelper) }
+ }
+
+ @Presubmit
+ @Test
+ fun imeAndAppAnimateTogetherWhenLockingAndUnlocking() {
+ flicker.assertLayers {
+ this.isVisible(testApp)
+ .isVisible(imeOrSnapshot)
+ .then()
+ .isInvisible(testApp)
+ .isInvisible(imeOrSnapshot)
+ .then()
+ .isVisible(testApp)
+ .isVisible(imeOrSnapshot)
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun navBarWindowIsAlwaysVisible() {}
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun statusBarWindowIsAlwaysVisible() {}
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun taskBarWindowIsAlwaysVisible() {}
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams() =
+ LegacyFlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(Rotation.ROTATION_0)
+ )
+ }
+}
diff --git a/tests/FlickerTests/Notification/AndroidTestTemplate.xml b/tests/FlickerTests/Notification/AndroidTestTemplate.xml
index 4036858..9c6a17d3 100644
--- a/tests/FlickerTests/Notification/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/Notification/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml b/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
index 797ca4e..ecbed28 100644
--- a/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/Rotation/AndroidTestTemplate.xml b/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
index b5ea739..1eacdfd 100644
--- a/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
<option name="isolated-storage" value="false"/>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
<!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
index 461dfec..9a5e88b 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -16,6 +16,7 @@
package com.android.server.wm.flicker.helpers
+import android.graphics.Rect
import android.tools.device.apphelpers.IStandardAppHelper
import android.tools.helpers.SYSTEMUI_PACKAGE
import android.tools.traces.parsers.WindowManagerStateHelper
@@ -32,6 +33,14 @@
*/
open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
IStandardAppHelper by innerHelper {
+
+ enum class Corners {
+ LEFT_TOP,
+ RIGHT_TOP,
+ LEFT_BOTTOM,
+ RIGHT_BOTTOM
+ }
+
private val TIMEOUT_MS = 3_000L
private val CAPTION = "desktop_mode_caption"
private val CAPTION_HANDLE = "caption_handle"
@@ -121,4 +130,39 @@
wmHelper.getWindowRegion(innerHelper).bounds.contains(it.visibleBounds)
}
}
+
+ /** Resize a desktop app from its corners. */
+ fun cornerResize(
+ wmHelper: WindowManagerStateHelper,
+ device: UiDevice,
+ corner: Corners,
+ horizontalChange: Int,
+ verticalChange: Int
+ ) {
+ val windowRect = wmHelper.getWindowRegion(innerHelper).bounds
+ val (startX, startY) = getStartCoordinatesForCornerResize(windowRect, corner)
+
+ // The position we want to drag to
+ val endY = startY + verticalChange
+ val endX = startX + horizontalChange
+
+ // drag the specified corner of the window to the end coordinate.
+ device.drag(startX, startY, endX, endY, 100)
+ wmHelper
+ .StateSyncBuilder()
+ .withAppTransitionIdle()
+ .waitForAndVerify()
+ }
+
+ private fun getStartCoordinatesForCornerResize(
+ windowRect: Rect,
+ corner: Corners
+ ): Pair<Int, Int> {
+ return when (corner) {
+ Corners.LEFT_TOP -> Pair(windowRect.left, windowRect.top)
+ Corners.RIGHT_TOP -> Pair(windowRect.right, windowRect.top)
+ Corners.LEFT_BOTTOM -> Pair(windowRect.left, windowRect.bottom)
+ Corners.RIGHT_BOTTOM -> Pair(windowRect.right, windowRect.bottom)
+ }
+ }
}
diff --git a/tests/Input/src/com/android/server/input/InputShellCommandTest.java b/tests/Input/src/com/android/server/input/InputShellCommandTest.java
index f4845a5..11f4633 100644
--- a/tests/Input/src/com/android/server/input/InputShellCommandTest.java
+++ b/tests/Input/src/com/android/server/input/InputShellCommandTest.java
@@ -125,6 +125,14 @@
assertThat(mInputEventInjector.mInjectedEvents).isEmpty();
}
+ @Test
+ public void testInvalidKeyEventCommandArgsCombination() {
+ // --duration and --longpress must not be sent together
+ runCommand("keyevent --duration 1000 --longpress KEYCODE_A");
+
+ assertThat(mInputEventInjector.mInjectedEvents).isEmpty();
+ }
+
private InputEvent getSingleInjectedInputEvent() {
assertThat(mInputEventInjector.mInjectedEvents).hasSize(1);
return mInputEventInjector.mInjectedEvents.get(0);
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index 7c5dcf8..e8be33c 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -51,6 +51,7 @@
"android.view.CutoutSpecificationTest",
"android.view.DisplayCutoutTest",
"android.view.DisplayShapeTest",
+ "android.view.ImeBackAnimationControllerTest",
"android.view.InsetsAnimationControlImplTest",
"android.view.InsetsControllerTest",
"android.view.InsetsFlagsTest",
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 994adc9..4c81939 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -227,56 +227,3 @@
],
},
}
-
-cc_genrule {
- name: "aapt2_results",
- srcs: [
- ":aapt2_tests",
- "integration-tests/CompileTest/**/*",
- "integration-tests/CommandTests/**/*",
- "integration-tests/ConvertTest/**/*",
- "integration-tests/DumpTest/**/*",
- ],
- host_supported: true,
- device_supported: false,
- target: {
- windows: {
- compile_multilib: "64",
- },
- },
- out: ["result.xml"],
- cmd: "mkdir -p $(genDir)/integration-tests/CompileTest/ && " +
- "cp $(locations integration-tests/CompileTest/**/*) $(genDir)/integration-tests/CompileTest/ && " +
- "mkdir -p $(genDir)/integration-tests/CommandTests/ && " +
- "cp $(locations integration-tests/CommandTests/**/*) $(genDir)/integration-tests/CommandTests/ && " +
- "mkdir -p $(genDir)/integration-tests/ConvertTest/ && " +
- "cp $(locations integration-tests/ConvertTest/**/*) $(genDir)/integration-tests/ConvertTest/ && " +
- "mkdir -p $(genDir)/integration-tests/DumpTest/ && " +
- "cp $(locations integration-tests/DumpTest/**/*) $(genDir)/integration-tests/DumpTest/ && " +
- "cp $(locations :aapt2_tests) $(genDir)/ && " +
- "$(genDir)/aapt2_tests " +
- "--gtest_output=xml:$(out) " +
- ">/dev/null 2>&1 ; true",
- dist: {
- targets: ["aapt2_run_host_unit_tests"],
- dir: "gtest",
- dest: "aapt2_host_unit_tests_result.xml",
- },
- arch: {
- x86: {
- dist: {
- suffix: "_x86",
- },
- },
- x86_64: {
- dist: {
- suffix: "_x86_64",
- },
- },
- },
-}
-
-phony_rule {
- name: "aapt2_run_host_unit_tests",
- phony_deps: ["aapt2_results"],
-}
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index dc18b1c..8fe414f 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -335,6 +335,11 @@
"are separated by ',' and the name is separated from the value by '='.\n"
"Example: \"flag1=true,flag2=false,flag3=\" (flag3 has no given value).",
&feature_flags_args_);
+ AddOptionalSwitch("--non-updatable-system",
+ "Mark the app as a non-updatable system app. This inserts\n"
+ "updatableSystem=\"false\" to the root manifest node, overwriting any\n"
+ "existing attribute. This is ignored if the manifest has a versionCode.",
+ &options_.manifest_fixer_options.non_updatable_system);
}
int Action(const std::vector<std::string>& args) override;
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index d03f97e..f1e4ead 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -489,6 +489,16 @@
}
}
+ if (options_.non_updatable_system) {
+ if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
+ el->RemoveAttribute("", "updatableSystem");
+ el->attributes.push_back(xml::Attribute{"", "updatableSystem", "false"});
+ } else {
+ diag->Note(android::DiagMessage(el->line_number)
+ << "Ignoring --non-updatable-system because the manifest has a versionCode");
+ }
+ }
+
return true;
});
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 42938a4..df0ece6 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -91,6 +91,11 @@
// Whether to suppress `android:compileSdkVersion*` and `platformBuildVersion*` attributes.
bool no_compile_sdk_metadata = false;
+
+ // Whether to mark the app as a non-updatable system app. This adds `updatableSystem="false"` to
+ // the <manifest> tag. Not used if a version code is set either explicitly in the manifest or
+ // through version_code_default.
+ bool non_updatable_system = false;
};
// Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 6151a8e..3cfdf78 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -677,6 +677,83 @@
EXPECT_THAT(attr->value, StrEq("0x00000002"));
}
+TEST_F(ManifestFixerTest, MarkNonUpdatableSystem) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("false"));
+}
+
+TEST_F(ManifestFixerTest, MarkNonUpdatableSystemOverwritingValue) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android"
+ updatableSystem="true" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("false"));
+}
+
+TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenExplicitVersion) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android"
+ android:versionCode="0x00000001" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, IsNull());
+}
+
+TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenAddedVersion) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+ options.version_code_default = std::string("0x10000000");
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, IsNull());
+
+ attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
diff --git a/tools/hoststubgen/TEST_MAPPING b/tools/hoststubgen/TEST_MAPPING
index eca258c..f6885e1 100644
--- a/tools/hoststubgen/TEST_MAPPING
+++ b/tools/hoststubgen/TEST_MAPPING
@@ -1,13 +1,63 @@
+// Keep the following two TEST_MAPPINGs in sync:
+// frameworks/base/ravenwood/TEST_MAPPING
+// frameworks/base/tools/hoststubgen/TEST_MAPPING
{
"presubmit": [
{ "name": "tiny-framework-dump-test" },
{ "name": "hoststubgentest" },
- { "name": "hoststubgen-invoke-test" }
+ { "name": "hoststubgen-invoke-test" },
+ {
+ "name": "RavenwoodMockitoTest_device"
+ },
+ {
+ "name": "RavenwoodBivalentTest_device"
+ },
+ // The sysui tests should match vendor/unbundled_google/packages/SystemUIGoogle/TEST_MAPPING
+ {
+ "name": "SystemUIGoogleTests",
+ "options": [
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "presubmit-large": [
+ {
+ "name": "SystemUITests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
],
"ravenwood-presubmit": [
{
+ "name": "RavenwoodMinimumTest",
+ "host": true
+ },
+ {
+ "name": "RavenwoodMockitoTest",
+ "host": true
+ },
+ {
"name": "CtsUtilTestCasesRavenwood",
"host": true
+ },
+ {
+ "name": "RavenwoodCoreTest",
+ "host": true
+ },
+ {
+ "name": "RavenwoodBivalentTest",
+ "host": true
}
]
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 2f432cc..7212beb 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -16,6 +16,7 @@
package com.android.hoststubgen
import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.dumper.ApiDumper
import com.android.hoststubgen.filters.AnnotationBasedFilter
import com.android.hoststubgen.filters.ClassWidePolicyPropagatingFilter
import com.android.hoststubgen.filters.ConstantFilter
@@ -89,7 +90,11 @@
log.i("Dump file created at $it")
}
options.apiListFile.ifSet {
- PrintWriter(it).use { pw -> stats.dumpApis(pw) }
+ PrintWriter(it).use { pw ->
+ // TODO, when dumping a jar that's not framework-minus-apex.jar, we need to feed
+ // framework-minus-apex.jar so that we can dump inherited methods from it.
+ ApiDumper(pw, allClasses, null, filter).dump()
+ }
log.i("API list file created at $it")
}
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
index da61469..9045db2 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
@@ -15,7 +15,8 @@
*/
package com.android.hoststubgen
-import com.android.hoststubgen.asm.toHumanReadableClassName
+import com.android.hoststubgen.asm.getOuterClassNameFromFullClassName
+import com.android.hoststubgen.asm.getPackageNameFromFullClassName
import com.android.hoststubgen.filters.FilterPolicyWithReason
import org.objectweb.asm.Opcodes
import java.io.PrintWriter
@@ -55,8 +56,8 @@
// Ignore methods where policy isn't relevant
if (policy.isIgnoredForStats) return
- val packageName = resolvePackageName(fullClassName)
- val className = resolveOuterClassName(fullClassName)
+ val packageName = getPackageNameFromFullClassName(fullClassName)
+ val className = getOuterClassNameFromFullClassName(fullClassName)
// Ignore methods for certain generated code
if (className.endsWith("Proto")
@@ -88,42 +89,4 @@
}
}
}
-
- fun dumpApis(pw: PrintWriter) {
- pw.printf("PackageName,ClassName,MethodName,MethodDesc\n")
- apis.sortedWith(compareBy({ it.fullClassName }, { it.methodName }, { it.methodDesc }))
- .forEach { api ->
- pw.printf(
- "%s,%s,%s,%s\n",
- csvEscape(resolvePackageName(api.fullClassName)),
- csvEscape(resolveClassName(api.fullClassName)),
- csvEscape(api.methodName),
- csvEscape(api.methodDesc),
- )
- }
- }
-
- private fun resolvePackageName(fullClassName: String): String {
- val start = fullClassName.lastIndexOf('/')
- return fullClassName.substring(0, start).toHumanReadableClassName()
- }
-
- private fun resolveOuterClassName(fullClassName: String): String {
- val start = fullClassName.lastIndexOf('/')
- val end = fullClassName.indexOf('$')
- if (end == -1) {
- return fullClassName.substring(start + 1)
- } else {
- return fullClassName.substring(start + 1, end)
- }
- }
-
- private fun resolveClassName(fullClassName: String): String {
- val pos = fullClassName.lastIndexOf('/')
- if (pos == -1) {
- return fullClassName
- } else {
- return fullClassName.substring(pos + 1)
- }
- }
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index 83e122f..b8d1800 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -76,17 +76,45 @@
return null
}
-private val removeLastElement = """[./][^./]*$""".toRegex()
+val periodOrSlash = charArrayOf('.', '/')
-fun getPackageNameFromClassName(className: String): String {
- return className.replace(removeLastElement, "")
+fun getPackageNameFromFullClassName(fullClassName: String): String {
+ val pos = fullClassName.lastIndexOfAny(periodOrSlash)
+ if (pos == -1) {
+ return ""
+ } else {
+ return fullClassName.substring(0, pos)
+ }
}
-fun resolveClassName(className: String, packageName: String): String {
+fun getClassNameFromFullClassName(fullClassName: String): String {
+ val pos = fullClassName.lastIndexOfAny(periodOrSlash)
+ if (pos == -1) {
+ return fullClassName
+ } else {
+ return fullClassName.substring(pos + 1)
+ }
+}
+
+fun getOuterClassNameFromFullClassName(fullClassName: String): String {
+ val start = fullClassName.lastIndexOfAny(periodOrSlash)
+ val end = fullClassName.indexOf('$')
+ if (end == -1) {
+ return fullClassName.substring(start + 1)
+ } else {
+ return fullClassName.substring(start + 1, end)
+ }
+}
+
+/**
+ * If [className] is a fully qualified name, just return it.
+ * Otherwise, prepend [defaultPackageName].
+ */
+fun resolveClassNameWithDefaultPackage(className: String, defaultPackageName: String): String {
if (className.contains('.') || className.contains('/')) {
return className
}
- return "$packageName.$className"
+ return "$defaultPackageName.$className"
}
fun String.toJvmClassName(): String {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
new file mode 100644
index 0000000..aaefee4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.dumper
+
+import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
+import com.android.hoststubgen.asm.CTOR_NAME
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.getClassNameFromFullClassName
+import com.android.hoststubgen.asm.getPackageNameFromFullClassName
+import com.android.hoststubgen.asm.toHumanReadableClassName
+import com.android.hoststubgen.csvEscape
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.log
+import org.objectweb.asm.Type
+import org.objectweb.asm.tree.ClassNode
+import java.io.PrintWriter
+
+/**
+ * Dump all the API methods in [classes], with inherited methods, with their policies.
+ */
+class ApiDumper(
+ val pw: PrintWriter,
+ val classes: ClassNodes,
+ val frameworkClasses: ClassNodes?,
+ val filter: OutputFilter,
+) {
+ private data class MethodKey(
+ val name: String,
+ val descriptor: String,
+ )
+
+ val javaStandardApiPolicy = FilterPolicy.Stub.withReason("Java standard API")
+
+ private val shownMethods = mutableSetOf<MethodKey>()
+
+ /**
+ * Do the dump.
+ */
+ fun dump() {
+ pw.printf("PackageName,ClassName,FromSubclass,DeclareClass,MethodName,MethodDesc" +
+ ",Supported,Policy,Reason\n")
+
+ classes.forEach { classNode ->
+ shownMethods.clear()
+ dump(classNode, classNode)
+ }
+ }
+
+ private fun dumpMethod(
+ classPackage: String,
+ className: String,
+ isSuperClass: Boolean,
+ methodClassName: String,
+ methodName: String,
+ methodDesc: String,
+ policy: FilterPolicyWithReason,
+ ) {
+ pw.printf(
+ "%s,%s,%d,%s,%s,%s,%d,%s,%s\n",
+ csvEscape(classPackage),
+ csvEscape(className),
+ if (isSuperClass) { 1 } else { 0 },
+ csvEscape(methodClassName),
+ csvEscape(methodName),
+ csvEscape(methodDesc),
+ if (policy.policy.isSupported) { 1 } else { 0 },
+ policy.policy,
+ csvEscape(policy.reason),
+ )
+ }
+
+ private fun isDuplicate(methodName: String, methodDesc: String): Boolean {
+ val methodKey = MethodKey(methodName, methodDesc)
+
+ if (shownMethods.contains(methodKey)) {
+ return true
+ }
+ shownMethods.add(methodKey)
+ return false
+ }
+
+ private fun dump(
+ dumpClass: ClassNode,
+ methodClass: ClassNode,
+ ) {
+ val pkg = getPackageNameFromFullClassName(dumpClass.name).toHumanReadableClassName()
+ val cls = getClassNameFromFullClassName(dumpClass.name).toHumanReadableClassName()
+
+ val isSuperClass = dumpClass != methodClass
+
+ methodClass.methods?.sortedWith(compareBy({ it.name }, { it.desc }))?.forEach { method ->
+
+ // Don't print ctor's from super classes.
+ if (isSuperClass) {
+ if (CTOR_NAME == method.name || CLASS_INITIALIZER_NAME == method.name) {
+ return@forEach
+ }
+ }
+ // If we already printed the method from a subclass, don't print it.
+ if (isDuplicate(method.name, method.desc)) {
+ return@forEach
+ }
+
+ val policy = filter.getPolicyForMethod(methodClass.name, method.name, method.desc)
+
+ // Let's skip "Remove" APIs. Ideally we want to print it, just to make the CSV
+ // complete, we still need to hide methods substituted (== @RavenwoodReplace) methods
+ // and for now we don't have an easy way to detect it.
+ if (policy.policy == FilterPolicy.Remove) {
+ return@forEach
+ }
+
+ val renameTo = filter.getRenameTo(methodClass.name, method.name, method.desc)
+
+ dumpMethod(pkg, cls, isSuperClass, methodClass.name.toHumanReadableClassName(),
+ renameTo ?: method.name, method.desc, policy)
+ }
+
+ // Dump super class methods.
+ dumpSuper(dumpClass, methodClass.superName)
+
+ // Dump interface methods (which may have default methods).
+ methodClass.interfaces?.sorted()?.forEach { interfaceName ->
+ dumpSuper(dumpClass, interfaceName)
+ }
+ }
+
+ /**
+ * Dump a given super class / interface.
+ */
+ private fun dumpSuper(
+ dumpClass: ClassNode,
+ methodClassName: String,
+ ) {
+ classes.findClass(methodClassName)?.let { methodClass ->
+ dump(dumpClass, methodClass)
+ return
+ }
+ frameworkClasses?.findClass(methodClassName)?.let { methodClass ->
+ dump(dumpClass, methodClass)
+ return
+ }
+ if (methodClassName.startsWith("java/") ||
+ methodClassName.startsWith("javax/")
+ ) {
+ dumpStandardClass(dumpClass, methodClassName)
+ return
+ }
+ log.w("Super class or interface $methodClassName (used by ${dumpClass.name}) not found.")
+ }
+
+ /**
+ * Dump methods from Java standard classes.
+ */
+ private fun dumpStandardClass(
+ dumpClass: ClassNode,
+ methodClassName: String,
+ ) {
+ val pkg = getPackageNameFromFullClassName(dumpClass.name).toHumanReadableClassName()
+ val cls = getClassNameFromFullClassName(dumpClass.name).toHumanReadableClassName()
+
+ val methodClassName = methodClassName.toHumanReadableClassName()
+
+ try {
+ val clazz = Class.forName(methodClassName)
+
+ // Method.getMethods() returns only public methods, but with inherited ones.
+ // Method.getDeclaredMethods() returns private methods too, but no inherited methods.
+ //
+ // Since we're only interested in public ones, just use getMethods().
+ clazz.methods.forEach { method ->
+ val methodName = method.name
+ val methodDesc = Type.getMethodDescriptor(method)
+
+ // If we already printed the method from a subclass, don't print it.
+ if (isDuplicate(methodName, methodDesc)) {
+ return@forEach
+ }
+
+ dumpMethod(pkg, cls, true, methodClassName,
+ methodName, methodDesc, javaStandardApiPolicy)
+ }
+ } catch (e: ClassNotFoundException) {
+ log.w("JVM type $methodClassName (used by ${dumpClass.name}) not found.")
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
index 76bac92..16785d1 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
@@ -51,6 +51,8 @@
}
/**
+ * Effectively apply @RavenwoodKeepWholeClass to all classes with these names
+ *
* @return if a given class "seems like" an feature flags class.
*/
private fun ClassNodes.isFeatureFlagsClass(className: String): Boolean {
@@ -59,6 +61,7 @@
return className.endsWith("/Flags")
|| className.endsWith("/FeatureFlags")
|| className.endsWith("/FeatureFlagsImpl")
+ || className.endsWith("/CustomFeatureFlags")
|| className.endsWith("/FakeFeatureFlagsImpl");
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
index 45e140c..6643492 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -20,8 +20,8 @@
import com.android.hoststubgen.LogLevel
import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.UnifiedVisitor
-import com.android.hoststubgen.asm.getPackageNameFromClassName
-import com.android.hoststubgen.asm.resolveClassName
+import com.android.hoststubgen.asm.getPackageNameFromFullClassName
+import com.android.hoststubgen.asm.resolveClassNameWithDefaultPackage
import com.android.hoststubgen.asm.toJvmClassName
import com.android.hoststubgen.filters.FilterPolicy
import com.android.hoststubgen.filters.FilterPolicyWithReason
@@ -89,7 +89,7 @@
) {
super.visit(version, access, name, signature, superName, interfaces)
currentClassName = name
- currentPackageName = getPackageNameFromClassName(name)
+ currentPackageName = getPackageNameFromFullClassName(name)
classPolicy = filter.getPolicyForClass(currentClassName)
log.d("[%s] visit: %s (package: %s)", this.javaClass.simpleName, name, currentPackageName)
@@ -98,7 +98,8 @@
log.indent()
filter.getNativeSubstitutionClass(currentClassName)?.let { className ->
- val fullClassName = resolveClassName(className, currentPackageName).toJvmClassName()
+ val fullClassName = resolveClassNameWithDefaultPackage(className, currentPackageName)
+ .toJvmClassName()
log.d(" NativeSubstitutionClass: $fullClassName")
if (classes.findClass(fullClassName) == null) {
log.w("Native substitution class $fullClassName not found. Class must be " +